MemLoadLibraryCPP
作者:互联网
1 /* 2 * Memory DLL loading code 3 * Version 0.0.3 4 * 5 * Copyright (c) 2004-2013 by Joachim Bauch / mail@joachim-bauch.de 6 * http://www.joachim-bauch.de 7 * 8 * The contents of this file are subject to the Mozilla Public License Version 9 * 2.0 (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * http://www.mozilla.org/MPL/ 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 15 * for the specific language governing rights and limitations under the 16 * License. 17 * 18 * The Original Code is MemoryModule.c 19 * 20 * The Initial Developer of the Original Code is Joachim Bauch. 21 * 22 * Portions created by Joachim Bauch are Copyright (C) 2004-2013 23 * Joachim Bauch. All Rights Reserved. 24 * 25 */ 26 27 #include "StdAfx.h" 28 #ifndef __GNUC__ 29 // disable warnings about pointer <-> DWORD conversions 30 #pragma warning( disable : 4311 4312 ) 31 #endif 32 33 #ifdef _WIN64 34 #define POINTER_TYPE ULONGLONG 35 #else 36 #define POINTER_TYPE DWORD 37 #endif 38 39 #include <windows.h> 40 #include <winnt.h> 41 #include <tchar.h> 42 #ifdef DEBUG_OUTPUT 43 #include <stdio.h> 44 #endif 45 46 #ifndef IMAGE_SIZEOF_BASE_RELOCATION 47 // Vista SDKs no longer define IMAGE_SIZEOF_BASE_RELOCATION!? 48 #define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION)) 49 #endif 50 51 #include "MemoryModule.h" 52 53 typedef struct { 54 PIMAGE_NT_HEADERS headers; 55 unsigned char *codeBase; 56 HCUSTOMMODULE *modules; 57 int numModules; 58 int initialized; 59 CustomLoadLibraryFunc loadLibrary; 60 CustomGetProcAddressFunc getProcAddress; 61 CustomFreeLibraryFunc freeLibrary; 62 void *userdata; 63 } MEMORYMODULE, *PMEMORYMODULE; 64 65 typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); 66 67 #define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx] 68 69 #ifdef DEBUG_OUTPUT 70 static void 71 OutputLastError(const char *msg) 72 { 73 LPVOID tmp; 74 char *tmpmsg; 75 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 76 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL); 77 tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3); 78 sprintf(tmpmsg, "%s: %s", msg, tmp); 79 OutputDebugString(tmpmsg); 80 LocalFree(tmpmsg); 81 LocalFree(tmp); 82 } 83 #endif 84 85 static void 86 CopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module) 87 { 88 int i, size; 89 unsigned char *codeBase = module->codeBase; 90 unsigned char *dest; 91 PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); 92 for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) { 93 if (section->SizeOfRawData == 0) { 94 // section doesn't contain data in the dll itself, but may define 95 // uninitialized data 96 size = old_headers->OptionalHeader.SectionAlignment; 97 if (size > 0) { 98 dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress, 99 size, 100 MEM_COMMIT, 101 PAGE_READWRITE); 102 103 section->Misc.PhysicalAddress = (DWORD) (POINTER_TYPE) dest; 104 memset(dest, 0, size); 105 } 106 107 // section is empty 108 continue; 109 } 110 111 // commit memory block and copy data from dll 112 dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress, 113 section->SizeOfRawData, 114 MEM_COMMIT, 115 PAGE_READWRITE); 116 memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData); 117 section->Misc.PhysicalAddress = (DWORD) (POINTER_TYPE) dest; 118 } 119 } 120 121 // Protection flags for memory pages (Executable, Readable, Writeable) 122 static int ProtectionFlags[2][2][2] = { 123 { 124 // not executable 125 {PAGE_NOACCESS, PAGE_WRITECOPY}, 126 {PAGE_READONLY, PAGE_READWRITE}, 127 }, { 128 // executable 129 {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY}, 130 {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}, 131 }, 132 }; 133 134 static void 135 FinalizeSections(PMEMORYMODULE module) 136 { 137 int i; 138 PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); 139 #ifdef _WIN64 140 POINTER_TYPE imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000); 141 #else 142 #define imageOffset 0 143 #endif 144 145 // loop through all sections and change access flags 146 for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) { 147 DWORD protect, oldProtect, size; 148 int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0; 149 int readable = (section->Characteristics & IMAGE_SCN_MEM_READ) != 0; 150 int writeable = (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0; 151 152 if (section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) { 153 // section is not needed any more and can safely be freed 154 VirtualFree((LPVOID)((POINTER_TYPE)section->Misc.PhysicalAddress | imageOffset), section->SizeOfRawData, MEM_DECOMMIT); 155 continue; 156 } 157 158 // determine protection flags based on characteristics 159 protect = ProtectionFlags[executable][readable][writeable]; 160 if (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) { 161 protect |= PAGE_NOCACHE; 162 } 163 164 // determine size of region 165 size = section->SizeOfRawData; 166 if (size == 0) { 167 if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { 168 size = module->headers->OptionalHeader.SizeOfInitializedData; 169 } else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { 170 size = module->headers->OptionalHeader.SizeOfUninitializedData; 171 } 172 } 173 174 if (size > 0) 175 { 176 // change memory access flags 177 if (VirtualProtect((LPVOID)((POINTER_TYPE)section->Misc.PhysicalAddress | imageOffset), size, protect, &oldProtect) == 0) 178 { 179 #ifdef DEBUG_OUTPUT 180 OutputLastError("Error protecting memory page"); 181 #endif 182 } 183 } 184 } 185 #ifndef _WIN64 186 #undef imageOffset 187 #endif 188 } 189 190 static void 191 PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta) 192 { 193 DWORD i; 194 unsigned char *codeBase = module->codeBase; 195 196 PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC); 197 if (directory->Size > 0) { 198 PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION) (codeBase + directory->VirtualAddress); 199 for (; relocation->VirtualAddress > 0; ) { 200 unsigned char *dest = codeBase + relocation->VirtualAddress; 201 unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION); 202 for (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) { 203 DWORD *patchAddrHL; 204 #ifdef _WIN64 205 ULONGLONG *patchAddr64; 206 #endif 207 int type, offset; 208 209 // the upper 4 bits define the type of relocation 210 type = *relInfo >> 12; 211 // the lower 12 bits define the offset 212 offset = *relInfo & 0xfff; 213 214 switch (type) 215 { 216 case IMAGE_REL_BASED_ABSOLUTE: 217 // skip relocation 218 break; 219 220 case IMAGE_REL_BASED_HIGHLOW: 221 // change complete 32 bit address 222 patchAddrHL = (DWORD *) (dest + offset); 223 *patchAddrHL += (DWORD) delta; 224 break; 225 226 #ifdef _WIN64 227 case IMAGE_REL_BASED_DIR64: 228 patchAddr64 = (ULONGLONG *) (dest + offset); 229 *patchAddr64 += (ULONGLONG) delta; 230 break; 231 #endif 232 233 default: 234 //printf("Unknown relocation: %d\n", type); 235 break; 236 } 237 } 238 239 // advance to next relocation block 240 relocation = (PIMAGE_BASE_RELOCATION) (((char *) relocation) + relocation->SizeOfBlock); 241 } 242 } 243 } 244 245 static int 246 BuildImportTable(PMEMORYMODULE module) 247 { 248 int result=1; 249 unsigned char *codeBase = module->codeBase; 250 HCUSTOMMODULE *tmp; 251 252 PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT); 253 if (directory->Size > 0) { 254 PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress); 255 for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) { 256 POINTER_TYPE *thunkRef; 257 FARPROC *funcRef; 258 HCUSTOMMODULE handle = module->loadLibrary((LPCSTR) (codeBase + importDesc->Name), module->userdata); 259 if (handle == NULL) { 260 SetLastError(ERROR_MOD_NOT_FOUND); 261 result = 0; 262 break; 263 } 264 265 tmp = (HCUSTOMMODULE *) realloc(module->modules, (module->numModules+1)*(sizeof(HCUSTOMMODULE))); 266 if (tmp == NULL) { 267 module->freeLibrary(handle, module->userdata); 268 SetLastError(ERROR_OUTOFMEMORY); 269 result = 0; 270 break; 271 } 272 module->modules = tmp; 273 274 module->modules[module->numModules++] = handle; 275 if (importDesc->OriginalFirstThunk) { 276 thunkRef = (POINTER_TYPE *) (codeBase + importDesc->OriginalFirstThunk); 277 funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk); 278 } else { 279 // no hint table 280 thunkRef = (POINTER_TYPE *) (codeBase + importDesc->FirstThunk); 281 funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk); 282 } 283 for (; *thunkRef; thunkRef++, funcRef++) { 284 if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) { 285 *funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata); 286 } else { 287 PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME) (codeBase + (*thunkRef)); 288 *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata); 289 } 290 if (*funcRef == 0) { 291 result = 0; 292 break; 293 } 294 } 295 296 if (!result) { 297 module->freeLibrary(handle, module->userdata); 298 SetLastError(ERROR_PROC_NOT_FOUND); 299 break; 300 } 301 } 302 } 303 304 return result; 305 } 306 307 static HCUSTOMMODULE _LoadLibrary(LPCSTR filename, void *userdata) 308 { 309 HMODULE result = LoadLibraryA(filename); 310 if (result == NULL) { 311 return NULL; 312 } 313 314 return (HCUSTOMMODULE) result; 315 } 316 317 static FARPROC _GetProcAddress(HCUSTOMMODULE module, LPCSTR name, void *userdata) 318 { 319 return (FARPROC) GetProcAddress((HMODULE) module, name); 320 } 321 322 static void _FreeLibrary(HCUSTOMMODULE module, void *userdata) 323 { 324 FreeLibrary((HMODULE) module); 325 } 326 327 HMEMORYMODULE MemoryLoadLibrary(const void *data) 328 { 329 return MemoryLoadLibraryEx(data, _LoadLibrary, _GetProcAddress, _FreeLibrary, NULL); 330 } 331 332 HMEMORYMODULE MemoryLoadLibraryEx(const void *data, 333 CustomLoadLibraryFunc loadLibrary, 334 CustomGetProcAddressFunc getProcAddress, 335 CustomFreeLibraryFunc freeLibrary, 336 void *userdata) 337 { 338 PMEMORYMODULE result; 339 PIMAGE_DOS_HEADER dos_header; 340 PIMAGE_NT_HEADERS old_header; 341 unsigned char *code, *headers; 342 SIZE_T locationDelta; 343 DllEntryProc DllEntry; 344 BOOL successfull; 345 346 dos_header = (PIMAGE_DOS_HEADER)data; 347 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { 348 SetLastError(ERROR_BAD_EXE_FORMAT); 349 return NULL; 350 } 351 352 old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew]; 353 if (old_header->Signature != IMAGE_NT_SIGNATURE) { 354 SetLastError(ERROR_BAD_EXE_FORMAT); 355 return NULL; 356 } 357 358 // reserve memory for image of library 359 // XXX: is it correct to commit the complete memory region at once? 360 // calling DllEntry raises an exception if we don't... 361 code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase), 362 old_header->OptionalHeader.SizeOfImage, 363 MEM_RESERVE | MEM_COMMIT, 364 PAGE_READWRITE); 365 366 if (code == NULL) { 367 // try to allocate memory at arbitrary position 368 code = (unsigned char *)VirtualAlloc(NULL, 369 old_header->OptionalHeader.SizeOfImage, 370 MEM_RESERVE | MEM_COMMIT, 371 PAGE_READWRITE); 372 if (code == NULL) { 373 SetLastError(ERROR_OUTOFMEMORY); 374 return NULL; 375 } 376 } 377 378 result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), 0, sizeof(MEMORYMODULE)); 379 if (result == NULL) { 380 SetLastError(ERROR_OUTOFMEMORY); 381 VirtualFree(code, 0, MEM_RELEASE); 382 return NULL; 383 } 384 385 result->codeBase = code; 386 result->numModules = 0; 387 result->modules = NULL; 388 result->initialized = 0; 389 result->loadLibrary = loadLibrary; 390 result->getProcAddress = getProcAddress; 391 result->freeLibrary = freeLibrary; 392 result->userdata = userdata; 393 394 // commit memory for headers 395 headers = (unsigned char *)VirtualAlloc(code, 396 old_header->OptionalHeader.SizeOfHeaders, 397 MEM_COMMIT, 398 PAGE_READWRITE); 399 400 // copy PE header to code 401 memcpy(headers, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders); 402 result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew]; 403 404 // update position 405 result->headers->OptionalHeader.ImageBase = (POINTER_TYPE)code; 406 407 // copy sections from DLL file block to new memory location 408 CopySections((UCHAR *)data, old_header, result); 409 410 // adjust base address of imported data 411 locationDelta = (SIZE_T)(code - old_header->OptionalHeader.ImageBase); 412 if (locationDelta != 0) { 413 PerformBaseRelocation(result, locationDelta); 414 } 415 416 // load required dlls and adjust function table of imports 417 if (!BuildImportTable(result)) { 418 goto error; 419 } 420 421 // mark memory pages depending on section headers and release 422 // sections that are marked as "discardable" 423 FinalizeSections(result); 424 425 // get entry point of loaded library 426 if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) { 427 DllEntry = (DllEntryProc) (code + result->headers->OptionalHeader.AddressOfEntryPoint); 428 // notify library about attaching to process 429 successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0); 430 if (!successfull) { 431 SetLastError(ERROR_DLL_INIT_FAILED); 432 goto error; 433 } 434 result->initialized = 1; 435 } 436 437 return (HMEMORYMODULE)result; 438 439 error: 440 // cleanup 441 MemoryFreeLibrary(result); 442 return NULL; 443 } 444 445 FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name) 446 { 447 unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; 448 int idx=-1; 449 DWORD i, *nameRef; 450 WORD *ordinal; 451 PIMAGE_EXPORT_DIRECTORY exports; 452 PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT); 453 if (directory->Size == 0) { 454 // no export table found 455 SetLastError(ERROR_PROC_NOT_FOUND); 456 return NULL; 457 } 458 459 exports = (PIMAGE_EXPORT_DIRECTORY) (codeBase + directory->VirtualAddress); 460 if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { 461 // DLL doesn't export anything 462 SetLastError(ERROR_PROC_NOT_FOUND); 463 return NULL; 464 } 465 466 // search function name in list of exported names 467 nameRef = (DWORD *) (codeBase + exports->AddressOfNames); 468 ordinal = (WORD *) (codeBase + exports->AddressOfNameOrdinals); 469 for (i=0; i<exports->NumberOfNames; i++, nameRef++, ordinal++) { 470 if (_stricmp(name, (const char *) (codeBase + (*nameRef))) == 0) { 471 idx = *ordinal; 472 break; 473 } 474 } 475 476 if (idx == -1) { 477 // exported symbol not found 478 SetLastError(ERROR_PROC_NOT_FOUND); 479 return NULL; 480 } 481 482 if ((DWORD)idx > exports->NumberOfFunctions) { 483 // name <-> ordinal number don't match 484 SetLastError(ERROR_PROC_NOT_FOUND); 485 return NULL; 486 } 487 488 // AddressOfFunctions contains the RVAs to the "real" functions 489 return (FARPROC) (codeBase + (*(DWORD *) (codeBase + exports->AddressOfFunctions + (idx*4)))); 490 } 491 492 void MemoryFreeLibrary(HMEMORYMODULE mod) 493 { 494 int i; 495 PMEMORYMODULE module = (PMEMORYMODULE)mod; 496 497 if (module != NULL) { 498 if (module->initialized != 0) { 499 // notify library about detaching from process 500 DllEntryProc DllEntry = (DllEntryProc) (module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint); 501 (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); 502 module->initialized = 0; 503 } 504 505 if (module->modules != NULL) { 506 // free previously opened libraries 507 for (i=0; i<module->numModules; i++) { 508 if (module->modules[i] != NULL) { 509 module->freeLibrary(module->modules[i], module->userdata); 510 } 511 } 512 513 free(module->modules); 514 } 515 516 if (module->codeBase != NULL) { 517 // release memory of library 518 VirtualFree(module->codeBase, 0, MEM_RELEASE); 519 } 520 521 HeapFree(GetProcessHeap(), 0, module); 522 } 523 } 524 525 #define DEFAULT_LANGUAGE MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) 526 527 HMEMORYRSRC MemoryFindResource(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type) 528 { 529 return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE); 530 } 531 532 static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry( 533 void *root, 534 PIMAGE_RESOURCE_DIRECTORY resources, 535 LPCTSTR key) 536 { 537 PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resources + 1); 538 PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; 539 DWORD start; 540 DWORD end; 541 DWORD middle; 542 543 if (!IS_INTRESOURCE(key) && key[0] == TEXT('#')) { 544 // special case: resource id given as string 545 TCHAR *endpos = NULL; 546 #if defined(UNICODE) 547 long int tmpkey = (WORD) wcstol((TCHAR *) &key[1], &endpos, 10); 548 #else 549 long int tmpkey = (WORD) strtol((TCHAR *) &key[1], &endpos, 10); 550 #endif 551 if (tmpkey <= 0xffff && lstrlen(endpos) == 0) { 552 key = MAKEINTRESOURCE(tmpkey); 553 } 554 } 555 556 // entries are stored as ordered list of named entries, 557 // followed by an ordered list of id entries - we can do 558 // a binary search to find faster... 559 if (IS_INTRESOURCE(key)) { 560 WORD check = (WORD) (POINTER_TYPE) key; 561 start = resources->NumberOfNamedEntries; 562 end = start + resources->NumberOfIdEntries; 563 564 while (end > start) { 565 WORD entryName; 566 middle = (start + end) >> 1; 567 entryName = (WORD) entries[middle].Name; 568 if (check < entryName) { 569 end = (end != middle ? middle : middle-1); 570 } else if (check > entryName) { 571 start = (start != middle ? middle : middle+1); 572 } else { 573 result = &entries[middle]; 574 break; 575 } 576 } 577 } else { 578 #if !defined(UNICODE) 579 char *searchKey = NULL; 580 int searchKeyLength = 0; 581 #endif 582 start = 0; 583 end = resources->NumberOfIdEntries; 584 while (end > start) { 585 // resource names are always stored using 16bit characters 586 int cmp; 587 PIMAGE_RESOURCE_DIR_STRING_U resourceString; 588 middle = (start + end) >> 1; 589 resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) (((char *) root) + (entries[middle].Name & 0x7FFFFFFF)); 590 #if !defined(UNICODE) 591 if (searchKey == NULL || searchKeyLength < resourceString->Length) { 592 void *tmp = realloc(searchKey, resourceString->Length); 593 if (tmp == NULL) { 594 break; 595 } 596 597 searchKey = (char *) tmp; 598 } 599 wcstombs(searchKey, resourceString->NameString, resourceString->Length); 600 cmp = strncmp(key, searchKey, resourceString->Length); 601 #else 602 cmp = wcsncmp(key, resourceString->NameString, resourceString->Length); 603 #endif 604 if (cmp < 0) { 605 end = (middle != end ? middle : middle-1); 606 } else if (cmp > 0) { 607 start = (middle != start ? middle : middle+1); 608 } else { 609 result = &entries[middle]; 610 break; 611 } 612 } 613 #if !defined(UNICODE) 614 free(searchKey); 615 #endif 616 } 617 618 619 return result; 620 } 621 622 HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type, WORD language) 623 { 624 unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase; 625 PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE) module, IMAGE_DIRECTORY_ENTRY_RESOURCE); 626 PIMAGE_RESOURCE_DIRECTORY rootResources; 627 PIMAGE_RESOURCE_DIRECTORY nameResources; 628 PIMAGE_RESOURCE_DIRECTORY typeResources; 629 PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType; 630 PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName; 631 PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage; 632 if (directory->Size == 0) { 633 // no resource table found 634 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); 635 return NULL; 636 } 637 638 if (language == DEFAULT_LANGUAGE) { 639 // use language from current thread 640 language = LANGIDFROMLCID(GetThreadLocale()); 641 } 642 643 // resources are stored as three-level tree 644 // - first node is the type 645 // - second node is the name 646 // - third node is the language 647 rootResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress); 648 foundType = _MemorySearchResourceEntry(rootResources, rootResources, type); 649 if (foundType == NULL) { 650 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); 651 return NULL; 652 } 653 654 typeResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff)); 655 foundName = _MemorySearchResourceEntry(rootResources, typeResources, name); 656 if (foundName == NULL) { 657 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 658 return NULL; 659 } 660 661 nameResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff)); 662 foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCTSTR) (POINTER_TYPE) language); 663 if (foundLanguage == NULL) { 664 // requested language not found, use first available 665 if (nameResources->NumberOfIdEntries == 0) { 666 SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND); 667 return NULL; 668 } 669 670 foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (nameResources + 1); 671 } 672 673 return (codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff)); 674 } 675 676 DWORD MemorySizeofResource(HMEMORYMODULE module, HMEMORYRSRC resource) 677 { 678 PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource; 679 680 return entry->Size; 681 } 682 683 LPVOID MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource) 684 { 685 unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase; 686 PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource; 687 688 return codeBase + entry->OffsetToData; 689 } 690 691 int 692 MemoryLoadString(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize) 693 { 694 return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE); 695 } 696 697 int 698 MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WORD language) 699 { 700 HMEMORYRSRC resource; 701 PIMAGE_RESOURCE_DIR_STRING_U data; 702 DWORD size; 703 if (maxsize == 0) { 704 return 0; 705 } 706 707 resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), RT_STRING, language); 708 if (resource == NULL) { 709 buffer[0] = 0; 710 return 0; 711 } 712 713 data = (PIMAGE_RESOURCE_DIR_STRING_U)MemoryLoadResource(module, resource); 714 id = id & 0x0f; 715 while (id--) { 716 data = (PIMAGE_RESOURCE_DIR_STRING_U) (((char *) data) + (data->Length + 1) * sizeof(WCHAR)); 717 } 718 if (data->Length == 0) { 719 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 720 buffer[0] = 0; 721 return 0; 722 } 723 724 size = data->Length; 725 if (size >= (DWORD) maxsize) { 726 size = maxsize; 727 } else { 728 buffer[size] = 0; 729 } 730 #if defined(UNICODE) 731 wcsncpy(buffer, data->NameString, size); 732 #else 733 wcstombs(buffer, data->NameString, size); 734 #endif 735 return size; 736 }
标签:RESOURCE,module,codeBase,MemLoadLibraryCPP,result,PIMAGE,NULL 来源: https://www.cnblogs.com/admrty/p/15270936.html