mirror of
https://github.com/vxcontrol/MemoryModule.git
synced 2026-07-21 06:05:55 -04:00
Added memory module resource loading API.
This commit is contained in:
+206
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
#include <winnt.h>
|
||||
#include <tchar.h>
|
||||
#ifdef DEBUG_OUTPUT
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
@@ -517,3 +518,208 @@ void MemoryFreeLibrary(HMEMORYMODULE mod)
|
||||
HeapFree(GetProcessHeap(), 0, module);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFAULT_LANGUAGE MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
|
||||
|
||||
HMEMORYRSRC MemoryFindResource(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type)
|
||||
{
|
||||
return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE);
|
||||
}
|
||||
|
||||
static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(
|
||||
void *root,
|
||||
PIMAGE_RESOURCE_DIRECTORY resources,
|
||||
LPCTSTR key)
|
||||
{
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resources + 1);
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL;
|
||||
DWORD start;
|
||||
DWORD end;
|
||||
DWORD middle;
|
||||
|
||||
if (!IS_INTRESOURCE(key) && key[0] == _T('#')) {
|
||||
// special case: resource id given as string
|
||||
_TCHAR *endpos = NULL;
|
||||
long int tmpkey = (WORD) _tcstol((_TCHAR *) &key[1], &endpos, 10);
|
||||
if (tmpkey <= 0xffff && _tcslen(endpos) == 0) {
|
||||
key = MAKEINTRESOURCE(tmpkey);
|
||||
}
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
WORD check = (WORD) (POINTER_TYPE) 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 = middle;
|
||||
} else if (check > entryName) {
|
||||
start = middle;
|
||||
} else {
|
||||
result = &entries[middle];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start = 0;
|
||||
end = resources->NumberOfIdEntries;
|
||||
#ifndef _UNICODE
|
||||
_TCHAR *searchKey = NULL;
|
||||
int searchKeyLength = 0;
|
||||
#endif
|
||||
while (end > start) {
|
||||
// resource names are always stored using 16bit characters
|
||||
middle = (start + end) >> 1;
|
||||
PIMAGE_RESOURCE_DIR_STRING_U resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) (((char *) root) + (entries[middle].Name & 0x7FFFFFFF));
|
||||
int cmp;
|
||||
#ifndef _UNICODE
|
||||
if (searchKey == NULL || searchKeyLength < resourceString->Length) {
|
||||
void *tmp = realloc(searchKey, resourceString->Length);
|
||||
if (tmp == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
searchKey = (_TCHAR *) tmp;
|
||||
}
|
||||
wcstombs(searchKey, resourceString->NameString, resourceString->Length);
|
||||
cmp = strncmp(key, searchKey, resourceString->Length);
|
||||
#else
|
||||
cmp = wcsncmp((_TCHAR *) key, resourceString->NameString, resourceString->Length);
|
||||
#endif
|
||||
if (cmp < 0) {
|
||||
end = middle;
|
||||
} else if (cmp > 0) {
|
||||
start = middle;
|
||||
} else {
|
||||
result = &entries[middle];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifndef _UNICODE
|
||||
free(searchKey);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR 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 = _MemorySearchResourceEntry(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);
|
||||
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) (POINTER_TYPE) language);
|
||||
if (foundLanguage == NULL) {
|
||||
// requested language not found, use first available
|
||||
if (nameResources->NumberOfIdEntries == 0) {
|
||||
SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (nameResources + 1);
|
||||
}
|
||||
|
||||
return (codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff));
|
||||
}
|
||||
|
||||
DWORD MemorySizeofResource(HMEMORYMODULE module, HMEMORYRSRC resource)
|
||||
{
|
||||
PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource;
|
||||
|
||||
return entry->Size;
|
||||
}
|
||||
|
||||
LPVOID MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource)
|
||||
{
|
||||
unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase;
|
||||
PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource;
|
||||
|
||||
return codeBase + entry->OffsetToData;
|
||||
}
|
||||
|
||||
int
|
||||
MemoryLoadString(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize)
|
||||
{
|
||||
return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE);
|
||||
}
|
||||
|
||||
int
|
||||
MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WORD language)
|
||||
{
|
||||
if (maxsize == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HMEMORYRSRC resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), RT_STRING, language);
|
||||
if (resource == NULL) {
|
||||
buffer[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIMAGE_RESOURCE_DIR_STRING_U data = MemoryLoadResource(module, resource);
|
||||
id = id & 0x0f;
|
||||
while (id--) {
|
||||
data = (PIMAGE_RESOURCE_DIR_STRING_U) (((char *) data) + (data->Length + 1) * sizeof(WCHAR));
|
||||
}
|
||||
if (data->Length == 0) {
|
||||
SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
|
||||
buffer[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD size = data->Length;
|
||||
if (size >= maxsize) {
|
||||
size = maxsize;
|
||||
} else {
|
||||
buffer[size] = 0;
|
||||
}
|
||||
#ifdef _UNICODE
|
||||
_tcsncpy(buffer, data->NameString, size);
|
||||
#else
|
||||
wcstombs(buffer, data->NameString, size);
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
typedef void *HMEMORYMODULE;
|
||||
|
||||
typedef void *HMEMORYRSRC;
|
||||
|
||||
typedef void *HCUSTOMMODULE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -70,6 +72,36 @@ FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR);
|
||||
*/
|
||||
void MemoryFreeLibrary(HMEMORYMODULE);
|
||||
|
||||
/**
|
||||
* Find the location of a resource with the specified type and name.
|
||||
*/
|
||||
HMEMORYRSRC MemoryFindResource(HMEMORYMODULE, LPCTSTR, LPCTSTR);
|
||||
|
||||
/**
|
||||
* Find the location of a resource with the specified type, name and language.
|
||||
*/
|
||||
HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE, LPCTSTR, LPCTSTR, WORD);
|
||||
|
||||
/**
|
||||
* Get the size of the resource in bytes.
|
||||
*/
|
||||
DWORD MemorySizeofResource(HMEMORYMODULE, HMEMORYRSRC);
|
||||
|
||||
/**
|
||||
* Get a pointer to the contents of the resource.
|
||||
*/
|
||||
LPVOID MemoryLoadResource(HMEMORYMODULE, HMEMORYRSRC);
|
||||
|
||||
/**
|
||||
* Load a string resource.
|
||||
*/
|
||||
int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int);
|
||||
|
||||
/**
|
||||
* Load a string resource with a given language.
|
||||
*/
|
||||
int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user