From a5c5bc30e6d1233975950f528b82b96e2800dea0 Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Wed, 21 Sep 2016 01:52:35 +0200 Subject: [PATCH 1/3] Provide ANSI and UNICODE versions of all resource functions. --- MemoryModule.c | 353 ++++++++++++++++++++++++++++++++++--------------- MemoryModule.h | 22 ++- 2 files changed, 265 insertions(+), 110 deletions(-) diff --git a/MemoryModule.c b/MemoryModule.c index cf38388..07f0e1f 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -27,7 +27,6 @@ #include #include #include -#include #ifdef DEBUG_OUTPUT #include #endif @@ -792,28 +791,89 @@ int MemoryCallEntryPoint(HMEMORYMODULE mod) #define DEFAULT_LANGUAGE MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) -HMEMORYRSRC MemoryFindResource(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type) +HMEMORYRSRC MemoryFindResourceA(HMEMORYMODULE module, LPCSTR name, LPCSTR type) { - return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE); + return MemoryFindResourceExA(module, name, type, DEFAULT_LANGUAGE); } -static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry( +HMEMORYRSRC MemoryFindResourceW(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type) +{ + return MemoryFindResourceExW(module, name, type, DEFAULT_LANGUAGE); +} + +static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryById( + PIMAGE_RESOURCE_DIRECTORY resources, + WORD id) +{ + PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resources + 1); + PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; + DWORD start = resources->NumberOfNamedEntries; + DWORD end = start + resources->NumberOfIdEntries; + + while (end > start) { + DWORD middle = (start + end) >> 1; + WORD entryName = (WORD) entries[middle].Name; + if (id < entryName) { + end = (end != middle ? middle : middle-1); + } else if (id > entryName) { + start = (start != middle ? middle : middle+1); + } else { + result = &entries[middle]; + break; + } + } + return result; +} + +static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryByString( void *root, PIMAGE_RESOURCE_DIRECTORY resources, - LPCTSTR key) + LPCWSTR key, + size_t keylen) { PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resources + 1); PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; - DWORD start; - DWORD end; - DWORD middle; + DWORD start = 0; + DWORD end = resources->NumberOfNamedEntries; + + while (end > start) { + DWORD middle = (start + end) >> 1; + PIMAGE_RESOURCE_DIR_STRING_U resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(root, entries[middle].Name & 0x7FFFFFFF); + int cmp = _wcsnicmp(key, resourceString->NameString, resourceString->Length); + if (cmp == 0) { + // Handle partial match + if (keylen > (size_t) resourceString->Length) { + cmp = 1; + } else if (keylen < (size_t) resourceString->Length) { + cmp = -1; + } + } + if (cmp < 0) { + end = (middle != end ? middle : middle-1); + } else if (cmp > 0) { + start = (middle != start ? middle : middle+1); + } else { + result = &entries[middle]; + break; + } + } + + return result; +} + +static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryA( + void *root, + PIMAGE_RESOURCE_DIRECTORY resources, + LPCSTR key) +{ + PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; - if (!IS_INTRESOURCE(key) && key[0] == TEXT('#')) { + if (!IS_INTRESOURCE(key) && key[0] == '#') { // special case: resource id given as string - TCHAR *endpos = NULL; - long int tmpkey = (WORD) _tcstol((TCHAR *) &key[1], &endpos, 10); - if (tmpkey <= 0xffff && lstrlen(endpos) == 0) { - key = MAKEINTRESOURCE(tmpkey); + char *endpos = NULL; + long int tmpkey = (WORD) strtol(key + 1, &endpos, 10); + if (tmpkey <= 0xffff && strlen(endpos) == 0) { + key = MAKEINTRESOURCEA(tmpkey); } } @@ -821,88 +881,117 @@ static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry( // followed by an ordered list of id entries - we can do // a binary search to find faster... if (IS_INTRESOURCE(key)) { - WORD check = (WORD) (uintptr_t) key; - start = resources->NumberOfNamedEntries; - end = start + resources->NumberOfIdEntries; - - while (end > start) { - WORD entryName; - middle = (start + end) >> 1; - entryName = (WORD) entries[middle].Name; - if (check < entryName) { - end = (end != middle ? middle : middle-1); - } else if (check > entryName) { - start = (start != middle ? middle : middle+1); - } else { - result = &entries[middle]; - break; - } - } - } else { - LPCWSTR searchKey; - size_t searchKeyLen = _tcslen(key); -#if defined(UNICODE) - searchKey = key; -#else - // Resource names are always stored using 16bit characters, need to - // convert string we search for. + return _MemorySearchResourceEntryById(resources, (WORD) (uintptr_t) key); + } + + // Resource names are always stored using 16bit characters, need to + // convert string we search for. #define MAX_LOCAL_KEY_LENGTH 2048 - // In most cases resource names are short, so optimize for that by - // using a pre-allocated array. - wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH+1]; - LPWSTR _searchKey; - if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { - size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); - _searchKey = (LPWSTR) malloc(_searchKeySize); - if (_searchKey == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - } else { - _searchKey = &_searchKeySpace[0]; + size_t searchKeyLen = strlen(key); + // In most cases resource names are short, so optimize for that by + // using a pre-allocated array. + wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH+1]; + LPWSTR _searchKey; + if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { + size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); + _searchKey = (LPWSTR) malloc(_searchKeySize); + if (_searchKey == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; } + } else { + _searchKey = &_searchKeySpace[0]; + } + mbstowcs(_searchKey, key, searchKeyLen); + _searchKey[searchKeyLen] = 0; - mbstowcs(_searchKey, key, searchKeyLen); - _searchKey[searchKeyLen] = 0; - searchKey = _searchKey; -#endif - start = 0; - end = resources->NumberOfNamedEntries; - while (end > start) { - int cmp; - PIMAGE_RESOURCE_DIR_STRING_U resourceString; - middle = (start + end) >> 1; - resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(root, entries[middle].Name & 0x7FFFFFFF); - cmp = _wcsnicmp(searchKey, resourceString->NameString, resourceString->Length); - if (cmp == 0) { - // Handle partial match - if (searchKeyLen > resourceString->Length) { - cmp = 1; - } else if (searchKeyLen < resourceString->Length) { - cmp = -1; - } - } - if (cmp < 0) { - end = (middle != end ? middle : middle-1); - } else if (cmp > 0) { - start = (middle != start ? middle : middle+1); - } else { - result = &entries[middle]; - break; - } + result = _MemorySearchResourceEntryByString(root, resources, _searchKey, searchKeyLen); + if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { + free(_searchKey); + } +#undef MAX_LOCAL_KEY_LENGTH + return result; +} + +static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryW( + void *root, + PIMAGE_RESOURCE_DIRECTORY resources, + LPCWSTR key) +{ + if (!IS_INTRESOURCE(key) && key[0] == L'#') { + // special case: resource id given as string + wchar_t *endpos = NULL; + long int tmpkey = (WORD) wcstol(key + 1, &endpos, 10); + if (tmpkey <= 0xffff && wcslen(endpos) == 0) { + key = MAKEINTRESOURCEW(tmpkey); } -#if !defined(UNICODE) - if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { - free(_searchKey); + } + + // entries are stored as ordered list of named entries, + // followed by an ordered list of id entries - we can do + // a binary search to find faster... + if (IS_INTRESOURCE(key)) { + return _MemorySearchResourceEntryById(resources, (WORD) (uintptr_t) key); + } + + return _MemorySearchResourceEntryByString(root, resources, key, wcslen(key)); +} + +HMEMORYRSRC MemoryFindResourceExA(HMEMORYMODULE module, LPCSTR name, LPCSTR type, WORD language) +{ + unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase; + PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE) module, IMAGE_DIRECTORY_ENTRY_RESOURCE); + PIMAGE_RESOURCE_DIRECTORY rootResources; + PIMAGE_RESOURCE_DIRECTORY nameResources; + PIMAGE_RESOURCE_DIRECTORY typeResources; + PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType; + PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName; + PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage; + if (directory->Size == 0) { + // no resource table found + SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); + return NULL; + } + + if (language == DEFAULT_LANGUAGE) { + // use language from current thread + language = LANGIDFROMLCID(GetThreadLocale()); + } + + // resources are stored as three-level tree + // - first node is the type + // - second node is the name + // - third node is the language + rootResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress); + foundType = _MemorySearchResourceEntryA(rootResources, rootResources, type); + if (foundType == NULL) { + SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); + return NULL; + } + + typeResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff)); + foundName = _MemorySearchResourceEntryA(rootResources, typeResources, name); + if (foundName == NULL) { + SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); + return NULL; + } + + nameResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff)); + foundLanguage = _MemorySearchResourceEntryA(rootResources, nameResources, (LPCSTR) (uintptr_t) language); + if (foundLanguage == NULL) { + // requested language not found, use first available + if (nameResources->NumberOfIdEntries == 0) { + SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND); + return NULL; } -#undef MAX_LOCAL_KEY_LENGTH -#endif + + foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (nameResources + 1); } - return result; + return (codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff)); } -HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type, WORD language) +HMEMORYRSRC MemoryFindResourceExW(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type, WORD language) { unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase; PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE) module, IMAGE_DIRECTORY_ENTRY_RESOURCE); @@ -928,21 +1017,21 @@ HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR typ // - second node is the name // - third node is the language rootResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress); - foundType = _MemorySearchResourceEntry(rootResources, rootResources, type); + foundType = _MemorySearchResourceEntryW(rootResources, rootResources, type); if (foundType == NULL) { SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); return NULL; } typeResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff)); - foundName = _MemorySearchResourceEntry(rootResources, typeResources, name); + foundName = _MemorySearchResourceEntryW(rootResources, typeResources, name); if (foundName == NULL) { SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); return NULL; } nameResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff)); - foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCTSTR) (uintptr_t) language); + foundLanguage = _MemorySearchResourceEntryW(rootResources, nameResources, (LPWSTR) (uintptr_t) language); if (foundLanguage == NULL) { // requested language not found, use first available if (nameResources->NumberOfIdEntries == 0) { @@ -980,49 +1069,101 @@ LPVOID MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource) } int -MemoryLoadString(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize) +MemoryLoadStringA(HMEMORYMODULE module, UINT id, LPSTR buffer, int maxsize) { - return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE); + return MemoryLoadStringExA(module, id, buffer, maxsize, DEFAULT_LANGUAGE); +} + +int +MemoryLoadStringW(HMEMORYMODULE module, UINT id, LPWSTR buffer, int maxsize) +{ + return MemoryLoadStringExW(module, id, buffer, maxsize, DEFAULT_LANGUAGE); +} + +static BOOL +MemoryLoadStringData(HMEMORYMODULE module, UINT id, HMEMORYRSRC resource, PIMAGE_RESOURCE_DIR_STRING_U* res) +{ + PIMAGE_RESOURCE_DIR_STRING_U data; + + data = (PIMAGE_RESOURCE_DIR_STRING_U) MemoryLoadResource(module, resource); + id = id & 0x0f; + while (id--) { + data = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(data, (data->Length + 1) * sizeof(WCHAR)); + } + if (data->Length == 0) { + SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); + return FALSE; + } + + *res = data; + return TRUE; } int -MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WORD language) +MemoryLoadStringExA(HMEMORYMODULE module, UINT id, LPSTR buffer, int maxsize, WORD language) { HMEMORYRSRC resource; PIMAGE_RESOURCE_DIR_STRING_U data; - DWORD size; + int size; + if (maxsize == 0) { + // TODO(fancycode): Should provide pointer to raw data in "buffer". + // Check what should be returned in this case (bytes or characters?). + buffer[0] = 0; return 0; } - resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), RT_STRING, language); + resource = MemoryFindResourceExA(module, MAKEINTRESOURCEA((id >> 4) + 1), (LPCSTR) RT_STRING, language); if (resource == NULL) { buffer[0] = 0; return 0; } - data = (PIMAGE_RESOURCE_DIR_STRING_U) MemoryLoadResource(module, resource); - id = id & 0x0f; - while (id--) { - data = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(data, (data->Length + 1) * sizeof(WCHAR)); - } - if (data->Length == 0) { - SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); + if (!MemoryLoadStringData(module, id, resource, &data)) { buffer[0] = 0; return 0; } size = data->Length; - if (size >= (DWORD) maxsize) { + if (size >= maxsize) { size = maxsize; } else { buffer[size] = 0; } -#if defined(UNICODE) - wcsncpy(buffer, data->NameString, size); -#else wcstombs(buffer, data->NameString, size); -#endif + return size; +} + +int +MemoryLoadStringExW(HMEMORYMODULE module, UINT id, LPWSTR buffer, int maxsize, WORD language) +{ + HMEMORYRSRC resource; + PIMAGE_RESOURCE_DIR_STRING_U data; + int size; + + if (maxsize == 0) { + // TODO(fancycode): Should provide pointer to raw data in "buffer". + // Check what should be returned in this case (bytes or characters?). + buffer[0] = 0; + return 0; + } + + resource = MemoryFindResourceExW(module, MAKEINTRESOURCEW((id >> 4) + 1), (LPCWSTR) RT_STRING, language); + if (resource == NULL) { + buffer[0] = 0; + return 0; + } + + if (!MemoryLoadStringData(module, id, resource, &data)) { + buffer[0] = 0; + return 0; + } + + size = data->Length; + if (size >= maxsize) { + size = maxsize - 1; + } + wcsncpy(buffer, data->NameString, size); return size; } diff --git a/MemoryModule.h b/MemoryModule.h index a728f6b..df68957 100644 --- a/MemoryModule.h +++ b/MemoryModule.h @@ -39,6 +39,12 @@ typedef void *HCUSTOMMODULE; extern "C" { #endif +#if defined(UNICODE) +#define MEMORYMODULE_FUNCTION_AW(func) func##W +#else +#define MEMORYMODULE_FUNCTION_AW(func) func##A +#endif + typedef LPVOID (*CustomAllocFunc)(LPVOID, SIZE_T, DWORD, DWORD, void*); typedef BOOL (*CustomFreeFunc)(LPVOID, SIZE_T, DWORD, void*); typedef HCUSTOMMODULE (*CustomLoadLibraryFunc)(LPCSTR, void *); @@ -94,12 +100,16 @@ int MemoryCallEntryPoint(HMEMORYMODULE); /** * Find the location of a resource with the specified type and name. */ -HMEMORYRSRC MemoryFindResource(HMEMORYMODULE, LPCTSTR, LPCTSTR); +HMEMORYRSRC MemoryFindResourceA(HMEMORYMODULE, LPCSTR, LPCSTR); +HMEMORYRSRC MemoryFindResourceW(HMEMORYMODULE, LPCWSTR, LPCWSTR); +#define MemoryFindResource MEMORYMODULE_FUNCTION_AW(MemoryFindResource) /** * Find the location of a resource with the specified type, name and language. */ -HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE, LPCTSTR, LPCTSTR, WORD); +HMEMORYRSRC MemoryFindResourceExA(HMEMORYMODULE, LPCSTR, LPCSTR, WORD); +HMEMORYRSRC MemoryFindResourceExW(HMEMORYMODULE, LPCWSTR, LPCWSTR, WORD); +#define MemoryFindResourceEx MEMORYMODULE_FUNCTION_AW(MemoryFindResourceEx) /** * Get the size of the resource in bytes. @@ -114,12 +124,16 @@ LPVOID MemoryLoadResource(HMEMORYMODULE, HMEMORYRSRC); /** * Load a string resource. */ -int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int); +int MemoryLoadStringA(HMEMORYMODULE, UINT, LPSTR, int); +int MemoryLoadStringW(HMEMORYMODULE, UINT, LPWSTR, int); +#define MemoryLoadString MEMORYMODULE_FUNCTION_AW(MemoryLoadString) /** * Load a string resource with a given language. */ -int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD); +int MemoryLoadStringExA(HMEMORYMODULE, UINT, LPSTR, int, WORD); +int MemoryLoadStringExW(HMEMORYMODULE, UINT, LPWSTR, int, WORD); +#define MemoryLoadStringEx MEMORYMODULE_FUNCTION_AW(MemoryLoadStringEx) /** * Default implementation of CustomAllocFunc that calls VirtualAlloc From 13e979e0b71ac294cb9b7aee766cad198d0fa2a5 Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Wed, 21 Sep 2016 01:55:57 +0200 Subject: [PATCH 2/3] MSVC needs the variables to be declared earlier. --- MemoryModule.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/MemoryModule.c b/MemoryModule.c index 07f0e1f..8431c54 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -867,6 +867,12 @@ static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryA( LPCSTR key) { PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; + size_t searchKeyLen; +#define MAX_LOCAL_KEY_LENGTH 2048 + // In most cases resource names are short, so optimize for that by + // using a pre-allocated array. + wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH+1]; + LPWSTR _searchKey; if (!IS_INTRESOURCE(key) && key[0] == '#') { // special case: resource id given as string @@ -886,12 +892,7 @@ static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryA( // Resource names are always stored using 16bit characters, need to // convert string we search for. -#define MAX_LOCAL_KEY_LENGTH 2048 - size_t searchKeyLen = strlen(key); - // In most cases resource names are short, so optimize for that by - // using a pre-allocated array. - wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH+1]; - LPWSTR _searchKey; + searchKeyLen = strlen(key); if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); _searchKey = (LPWSTR) malloc(_searchKeySize); From d718478cfccdfc45ec2b6655727fce57fff3602e Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Wed, 21 Sep 2016 01:59:27 +0200 Subject: [PATCH 3/3] Fix string termination for UNICODE. --- MemoryModule.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MemoryModule.c b/MemoryModule.c index 8431c54..817ccef 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -1162,7 +1162,9 @@ MemoryLoadStringExW(HMEMORYMODULE module, UINT id, LPWSTR buffer, int maxsize, W size = data->Length; if (size >= maxsize) { - size = maxsize - 1; + size = maxsize; + } else { + buffer[size] = 0; } wcsncpy(buffer, data->NameString, size); return size; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy