LoadDLL.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. #include "LoadDLL.h"
  2. #include <windows.h>
  3. #include <winnt.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #define READ_PROC(buff, pos, size) \
  7. __try { \
  8. if (!read_proc((buff), (pos), (size), (read_proc_param))) \
  9. return ELoadDLLResult_ReadProcError; \
  10. } __except (EXCEPTION_EXECUTE_HANDLER) { \
  11. return ELoadDLLResult_ReadProcError; \
  12. }
  13. typedef struct LOAD_DLL_CONTEXT
  14. {
  15. IMAGE_DOS_HEADER dos_hdr;
  16. IMAGE_NT_HEADERS hdr;
  17. IMAGE_SECTION_HEADER* sect;
  18. size_t file_offset_section_headers;
  19. size_t size_section_headers;
  20. DWORD_PTR image_base;
  21. void* image;
  22. HMODULE* loaded_import_modules_array;
  23. unsigned num_import_modules;
  24. unsigned import_modules_array_capacity;
  25. LPDLLMAIN dll_main;
  26. } LOAD_DLL_CONTEXT;
  27. static ELoadDLLResult LoadDLL_LoadHeaders(LOAD_DLL_CONTEXT* ctx, LOAD_DLL_READPROC read_proc, void* read_proc_param)
  28. {
  29. /* Read and check the DOS header... */
  30. READ_PROC(&ctx->dos_hdr, 0, sizeof(ctx->dos_hdr));
  31. if (ctx->dos_hdr.e_magic != IMAGE_DOS_SIGNATURE || !ctx->dos_hdr.e_lfanew)
  32. return ELoadDLLResult_InvalidImage;
  33. /* Read and check the NT header... */
  34. READ_PROC(&ctx->hdr, ctx->dos_hdr.e_lfanew, sizeof(ctx->hdr))
  35. if (ctx->hdr.Signature != IMAGE_NT_SIGNATURE ||
  36. ctx->hdr.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC ||
  37. !ctx->hdr.FileHeader.NumberOfSections)
  38. return ELoadDLLResult_InvalidImage;
  39. /* Allocating memory and reading section headers. */
  40. ctx->size_section_headers = ctx->hdr.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
  41. ctx->sect = (IMAGE_SECTION_HEADER*)malloc(ctx->size_section_headers);
  42. if (!ctx->sect)
  43. return ELoadDLLResult_MemoryAllocationError;
  44. ctx->file_offset_section_headers = ctx->dos_hdr.e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + ctx->hdr.FileHeader.SizeOfOptionalHeader;
  45. READ_PROC(ctx->sect, ctx->file_offset_section_headers, ctx->size_section_headers);
  46. return ELoadDLLResult_OK;
  47. }
  48. static ELoadDLLResult LoadDLL_AllocateMemory(LOAD_DLL_CONTEXT* ctx, int flags)
  49. {
  50. DWORD rva_low, rva_high, i;
  51. IMAGE_SECTION_HEADER* s;
  52. /*
  53. // We do not trust the value of hdr.OptionalHeader.SizeOfImage so we calculate our own SizeOfImage.
  54. // This is the size of the continuous memory block that can hold the headers and all sections.
  55. // We will search the lowest and highest RVA among the section boundaries. If we must load the
  56. // header then its RVA will be the lowest (zero) and its size will be (file_offset_section_headers + size_section_headers).
  57. */
  58. rva_low = (flags & ELoadDLLFlag_NoHeaders) ? 0xFFFFFFFF : 0;
  59. rva_high = 0;
  60. for (i=0,s=ctx->sect; i<ctx->hdr.FileHeader.NumberOfSections; ++i,++s)
  61. {
  62. if (!s->Misc.VirtualSize)
  63. continue;
  64. if (s->VirtualAddress < rva_low)
  65. rva_low = s->VirtualAddress;
  66. if ((s->VirtualAddress + s->Misc.VirtualSize) > rva_high)
  67. rva_high = s->VirtualAddress + s->Misc.VirtualSize;
  68. }
  69. /*
  70. // RVAlow and RVA high holds the boundaries of the memory block needed to load the sections & header of the image.
  71. // Now we allocate the memory block to load the sections and additionally the headers. We will try to allocate
  72. // the block at the preferred image base to avoid doing the base relocations.
  73. */
  74. ctx->image = VirtualAlloc(
  75. (LPVOID)(ctx->hdr.OptionalHeader.ImageBase + rva_low),
  76. rva_high - rva_low,
  77. MEM_COMMIT | MEM_RESERVE,
  78. PAGE_EXECUTE_READWRITE
  79. );
  80. ctx->image_base = ctx->hdr.OptionalHeader.ImageBase;
  81. /*
  82. // Note: image may differ from the address (LPVOID)(hdr.OptionalHeader.ImageBase + RVAlow)
  83. // because windows rounds down addresses to next page boundary.
  84. */
  85. if (!ctx->image)
  86. {
  87. /*
  88. // If allocation at preferred imagebase failed then we let windows to allocate memory at arbitrary location.
  89. // Unfortunately we can not skip doing base relocations so we are in crap if the relocation info is stripped
  90. // from the DLL. :(
  91. */
  92. if (ctx->hdr.FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
  93. return ELoadDLLResult_RelocationError;
  94. ctx->image = VirtualAlloc(
  95. NULL,
  96. rva_high - rva_low,
  97. MEM_COMMIT | MEM_RESERVE,
  98. PAGE_EXECUTE_READWRITE);
  99. ctx->image_base = (DWORD_PTR)ctx->image - rva_low;
  100. }
  101. if (!ctx->image)
  102. return ELoadDLLResult_MemoryAllocationError;
  103. return ELoadDLLResult_OK;
  104. }
  105. static ELoadDLLResult LoadDLL_LoadSections(LOAD_DLL_CONTEXT* ctx, LOAD_DLL_READPROC read_proc, void* read_proc_param, int flags)
  106. {
  107. DWORD i;
  108. DWORD section_size;
  109. IMAGE_SECTION_HEADER* s;
  110. /* Loading the header if required. */
  111. if (!(flags & ELoadDLLFlag_NoHeaders))
  112. {
  113. READ_PROC((void*)ctx->image_base, 0, ctx->file_offset_section_headers + ctx->size_section_headers);
  114. }
  115. /* Loading the sections. */
  116. for (i=0,s=ctx->sect; i<ctx->hdr.FileHeader.NumberOfSections; ++i,++s)
  117. {
  118. section_size = std::min(s->Misc.VirtualSize, s->SizeOfRawData);
  119. if (section_size)
  120. {
  121. READ_PROC((void*)(s->VirtualAddress + ctx->image_base), s->PointerToRawData, section_size);
  122. }
  123. }
  124. return ELoadDLLResult_OK;
  125. }
  126. static ELoadDLLResult LoadDLL_PerformRelocation(LOAD_DLL_CONTEXT* ctx)
  127. {
  128. DWORD i, num_items;
  129. DWORD_PTR diff;
  130. IMAGE_BASE_RELOCATION* r;
  131. IMAGE_BASE_RELOCATION* r_end;
  132. WORD* reloc_item;
  133. /* Do we need to do the base relocations? Are there any relocatable items? */
  134. if (ctx->image_base == ctx->hdr.OptionalHeader.ImageBase)
  135. return ELoadDLLResult_OK;
  136. if (!ctx->hdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress ||
  137. !ctx->hdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
  138. return ELoadDLLResult_RelocationError;
  139. __try
  140. {
  141. diff = ctx->image_base - ctx->hdr.OptionalHeader.ImageBase;
  142. r = (IMAGE_BASE_RELOCATION*)(ctx->image_base + ctx->hdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
  143. r_end = (IMAGE_BASE_RELOCATION*)((DWORD_PTR)r + ctx->hdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size - sizeof (IMAGE_BASE_RELOCATION));
  144. for (; r<r_end; r=(IMAGE_BASE_RELOCATION*)((DWORD_PTR)r + r->SizeOfBlock))
  145. {
  146. reloc_item = (WORD*)(r + 1);
  147. num_items = (r->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
  148. for (i=0; i<num_items; ++i,++reloc_item)
  149. {
  150. switch (*reloc_item >> 12)
  151. {
  152. case IMAGE_REL_BASED_ABSOLUTE:
  153. break;
  154. case IMAGE_REL_BASED_HIGHLOW:
  155. *(DWORD_PTR*)(ctx->image_base + r->VirtualAddress + (*reloc_item & 0xFFF)) += diff;
  156. break;
  157. default:
  158. return ELoadDLLResult_BadRelocationTable;
  159. }
  160. }
  161. }
  162. }
  163. __except (EXCEPTION_EXECUTE_HANDLER)
  164. {
  165. return ELoadDLLResult_BadRelocationTable;
  166. }
  167. return ELoadDLLResult_OK;
  168. }
  169. static ELoadDLLResult LoadDLL_ResolveImports(LOAD_DLL_CONTEXT* ctx)
  170. {
  171. IMAGE_IMPORT_DESCRIPTOR* import_desc;
  172. HMODULE hDLL;
  173. DWORD_PTR* src_iat;
  174. DWORD_PTR* dest_iat;
  175. HMODULE* new_module_array;
  176. if (!ctx->hdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress ||
  177. !ctx->hdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
  178. return ELoadDLLResult_OK;
  179. import_desc = (IMAGE_IMPORT_DESCRIPTOR*)(ctx->image_base + ctx->hdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  180. for (; import_desc->Name; ++import_desc)
  181. {
  182. hDLL = LoadLibraryA((char*)(ctx->image_base + import_desc->Name));
  183. if (!hDLL)
  184. return ELoadDLLResult_ImportModuleError;
  185. if (ctx->num_import_modules >= ctx->import_modules_array_capacity)
  186. {
  187. ctx->import_modules_array_capacity = ctx->import_modules_array_capacity ? ctx->import_modules_array_capacity*2 : 16;
  188. new_module_array = (HMODULE*)malloc(sizeof(HMODULE)*ctx->import_modules_array_capacity);
  189. if (!new_module_array)
  190. return ELoadDLLResult_MemoryAllocationError;
  191. if (ctx->num_import_modules)
  192. memcpy(new_module_array, ctx->loaded_import_modules_array, sizeof(HMODULE)*ctx->num_import_modules);
  193. free(ctx->loaded_import_modules_array);
  194. ctx->loaded_import_modules_array = new_module_array;
  195. }
  196. new_module_array[ctx->num_import_modules++] = hDLL;
  197. /*
  198. // We do not trust bound imports. If FirstThunk is not bound then we use that to find the function ordinals/names.
  199. // If it's bound we must use OriginalFirstThunk. If FirstThunk is bound and OriginalFirstThunk is not present then
  200. // we return with error.
  201. */
  202. src_iat = dest_iat = (DWORD_PTR*)(ctx->image_base + import_desc->FirstThunk);
  203. if (import_desc->TimeDateStamp)
  204. {
  205. if (!import_desc->OriginalFirstThunk)
  206. return ELoadDLLResult_BoundImportDirectoriesNotSupported;
  207. src_iat = (DWORD_PTR*)(ctx->image_base + import_desc->OriginalFirstThunk);
  208. }
  209. for (; *src_iat; ++src_iat,++dest_iat)
  210. {
  211. *dest_iat = (DWORD_PTR)GetProcAddress(hDLL, (const char*)((*src_iat & IMAGE_ORDINAL_FLAG) ? IMAGE_ORDINAL(*src_iat) : ctx->image_base + *src_iat + 2));
  212. if (!*dest_iat)
  213. return ELoadDLLResult_ImportFunctionError;
  214. }
  215. }
  216. return ELoadDLLResult_OK;
  217. }
  218. static ELoadDLLResult LoadDLL_SetSectionMemoryProtection(LOAD_DLL_CONTEXT* ctx)
  219. {
  220. IMAGE_SECTION_HEADER* s;
  221. DWORD i, protection;
  222. /*
  223. // Setting the protection of memory pages. We leave the protection of header PAGE_EXECUTE_READWRITE.
  224. // Note: We must convert the section characterictics flag into memory page protection flag of VirtualProtect().
  225. // In the characterictics flags of a section there are 4 bits that are important for us now:
  226. //
  227. // IMAGE_SCN_CNT_CODE 0x00000020
  228. // IMAGE_SCN_MEM_EXECUTE 0x20000000
  229. // IMAGE_SCN_MEM_READ 0x40000000
  230. // IMAGE_SCN_MEM_WRITE 0x80000000
  231. //
  232. // IMAGE_SC_CNT_CODE is equivalent to (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ)
  233. // so we have only 3 flags that means 8 cases.
  234. */
  235. for (i=0,s=ctx->sect; i<ctx->hdr.FileHeader.NumberOfSections; ++i,++s)
  236. {
  237. if (s->Characteristics & IMAGE_SCN_CNT_CODE)
  238. s->Characteristics |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
  239. /* We rotate the upper 3 important bits down so the resulting value is in the range 0-7. */
  240. switch ((DWORD)s->Characteristics >> (32-3))
  241. {
  242. /* meaning of bits: 1: execute, 2: read, 4: write */
  243. case 1: protection = PAGE_EXECUTE; break;
  244. case 0: // case 0: should we use PAGE_NOACCESS? What is it good for?
  245. case 2: protection = PAGE_READONLY; break;
  246. case 3: protection = PAGE_EXECUTE_READ; break;
  247. case 4:
  248. case 6: protection = PAGE_READWRITE; break;
  249. case 5:
  250. default: protection = PAGE_EXECUTE_READWRITE; break;
  251. }
  252. if (!VirtualProtect(
  253. (LPVOID)(ctx->image_base + s->VirtualAddress),
  254. s->Misc.VirtualSize,
  255. protection,
  256. &protection
  257. ))
  258. return ELoadDLLResult_ErrorSettingMemoryProtection;
  259. }
  260. return ELoadDLLResult_OK;
  261. }
  262. static ELoadDLLResult LoadDLL_CallDLLEntryPoint(LOAD_DLL_CONTEXT* ctx, int flags)
  263. {
  264. /*
  265. // Do we have to call the entrypoint of the DLL? If yes then we do the DLL_PROCESS_ATTACH
  266. // notification but if it returns FALSE we unload the whole image immediately.
  267. */
  268. if (flags & ELoadDLLFlag_NoEntryCall)
  269. return ELoadDLLResult_OK;
  270. if (ctx->hdr.OptionalHeader.AddressOfEntryPoint)
  271. {
  272. ctx->dll_main = (LPDLLMAIN)(ctx->hdr.OptionalHeader.AddressOfEntryPoint + ctx->image_base);
  273. __try
  274. {
  275. if (!ctx->dll_main(ctx->image_base, DLL_PROCESS_ATTACH, NULL))
  276. return ELoadDLLResult_DllMainCallError;
  277. }
  278. __except (EXCEPTION_EXECUTE_HANDLER)
  279. {
  280. return ELoadDLLResult_DllMainCallError;
  281. }
  282. }
  283. return ELoadDLLResult_OK;
  284. }
  285. ELoadDLLResult LoadDLL(LOAD_DLL_READPROC read_proc, void* read_proc_param, int flags, LOAD_DLL_INFO* info)
  286. {
  287. LOAD_DLL_CONTEXT ctx;
  288. ELoadDLLResult res;
  289. BOOL finished_successfully = FALSE;
  290. unsigned i;
  291. if (!read_proc)
  292. return ELoadDLLResult_WrongFunctionParameters;
  293. ctx.sect = NULL;
  294. ctx.loaded_import_modules_array = NULL;
  295. ctx.import_modules_array_capacity = 0;
  296. ctx.num_import_modules = 0;
  297. ctx.dll_main = NULL;
  298. __try
  299. {
  300. __try
  301. {
  302. res = LoadDLL_LoadHeaders(&ctx, read_proc, read_proc_param);
  303. if (res != ELoadDLLResult_OK)
  304. return res;
  305. res = LoadDLL_AllocateMemory(&ctx, flags);
  306. if (res != ELoadDLLResult_OK)
  307. return res;
  308. __try
  309. {
  310. res = LoadDLL_LoadSections(&ctx, read_proc, read_proc_param, flags);
  311. if (res != ELoadDLLResult_OK)
  312. return res;
  313. res = LoadDLL_PerformRelocation(&ctx);
  314. if (res != ELoadDLLResult_OK)
  315. return res;
  316. res = LoadDLL_ResolveImports(&ctx);
  317. if (res != ELoadDLLResult_OK)
  318. return res;
  319. res = LoadDLL_SetSectionMemoryProtection(&ctx);
  320. if (res != ELoadDLLResult_OK)
  321. return res;
  322. res = LoadDLL_CallDLLEntryPoint(&ctx, flags);
  323. if (res != ELoadDLLResult_OK)
  324. return res;
  325. /* We finished!!! :) Filling in the callers info structure... */
  326. if (info)
  327. {
  328. __try
  329. {
  330. info->size = sizeof(*info);
  331. info->flags = flags;
  332. info->image_base = ctx.image_base;
  333. info->mem_block = ctx.image;
  334. info->dll_main = ctx.dll_main;
  335. info->export_dir_rva = ctx.hdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  336. info->loaded_import_modules_array = ctx.loaded_import_modules_array;
  337. info->num_import_modules = ctx.num_import_modules;
  338. }
  339. __except (EXCEPTION_EXECUTE_HANDLER)
  340. {
  341. return ELoadDLLResult_WrongFunctionParameters;
  342. }
  343. }
  344. finished_successfully = TRUE;
  345. return ELoadDLLResult_OK;
  346. }
  347. __finally
  348. {
  349. if (!finished_successfully)
  350. VirtualFree(ctx.image, 0, MEM_RELEASE);
  351. if (!finished_successfully || !info)
  352. {
  353. if (ctx.loaded_import_modules_array)
  354. {
  355. for (i=0; i<ctx.num_import_modules; ++i)
  356. FreeLibrary(ctx.loaded_import_modules_array[i]);
  357. free(ctx.loaded_import_modules_array);
  358. }
  359. }
  360. }
  361. }
  362. __finally
  363. {
  364. if (ctx.sect)
  365. free(ctx.sect);
  366. }
  367. }
  368. __except (EXCEPTION_EXECUTE_HANDLER)
  369. {
  370. return ELoadDLLResult_UnknownError;
  371. }
  372. }
  373. //------------------------------------------------------------------------------
  374. BOOL UnloadDLL(LOAD_DLL_INFO* info)
  375. {
  376. unsigned i;
  377. BOOL res = TRUE;
  378. __try
  379. {
  380. if (!info || info->size!=sizeof(*info) || !info->image_base || !info->mem_block)
  381. return FALSE;
  382. if (info->loaded_import_modules_array)
  383. {
  384. for (i=0; i<info->num_import_modules; ++i)
  385. FreeLibrary(info->loaded_import_modules_array[i]);
  386. free(info->loaded_import_modules_array);
  387. }
  388. if (!(info->flags & ELoadDLLFlag_NoEntryCall) && info->dll_main)
  389. {
  390. __try
  391. {
  392. res = info->dll_main(info->image_base, DLL_PROCESS_DETACH, NULL);
  393. }
  394. __except (EXCEPTION_EXECUTE_HANDLER)
  395. {
  396. res = FALSE;
  397. }
  398. }
  399. VirtualFree(info->mem_block, 0, MEM_RELEASE);
  400. return res;
  401. }
  402. __except (EXCEPTION_EXECUTE_HANDLER)
  403. {
  404. return FALSE;
  405. }
  406. }
  407. //------------------------------------------------------------------------------
  408. /*
  409. // LoadDLLFromFile...
  410. *
  411. typedef struct _LOAD_DLL_FROM_FILE_STRUCT {
  412. FILE* f;
  413. size_t dll_offset;
  414. size_t dll_size;
  415. } LOAD_DLL_FROM_FILE_STRUCT;
  416. static BOOL LoadDLLFromFileCallback(void* buff, size_t position, size_t size, LOAD_DLL_FROM_FILE_STRUCT* param)
  417. {
  418. if (!size)
  419. return TRUE;
  420. if ((position + size) > param->dll_size)
  421. return FALSE;
  422. fseek(param->f, param->dll_offset + position, SEEK_SET);
  423. return fread(buff, 1, size, param->f) == size;
  424. }
  425. ELoadDLLResult LoadDLLFromCFile(FILE* f, size_t dll_offset, size_t dll_size, int flags, LOAD_DLL_INFO* info)
  426. {
  427. LOAD_DLL_FROM_FILE_STRUCT ldffs = { f, dll_offset, dll_size };
  428. return LoadDLL((LOAD_DLL_READPROC)&LoadDLLFromFileCallback, &ldffs, flags, info);
  429. }
  430. ELoadDLLResult LoadDLLFromFileNameOffset(const char* filename, size_t dll_offset, size_t dll_size, int flags, LOAD_DLL_INFO* info)
  431. {
  432. ELoadDLLResult res;
  433. FILE* f = fopen(filename, "rb");
  434. if (!f)
  435. return ELoadDLLResult_DLLFileNotFound;
  436. res = LoadDLLFromCFile(f, dll_offset, dll_size, flags, info);
  437. fclose(f);
  438. return res;
  439. }
  440. ELoadDLLResult LoadDLLFromFileName(const char* filename, int flags, LOAD_DLL_INFO* info)
  441. {
  442. return LoadDLLFromFileNameOffset(filename, 0, DLL_SIZE_UNKNOWN, flags, info);
  443. }
  444. /*
  445. // LoadDLLFromMemory()
  446. */
  447. typedef struct _LOAD_DLL_FROM_MEMORY_STRUCT {
  448. const void* dll_data;
  449. size_t dll_size;
  450. } LOAD_DLL_FROM_MEMORY_STRUCT;
  451. static BOOL LoadDLLFromMemoryCallback(void* buff, size_t position, size_t size, LOAD_DLL_FROM_MEMORY_STRUCT* param)
  452. {
  453. if (!size)
  454. return TRUE;
  455. if ((position + size) > param->dll_size)
  456. return FALSE;
  457. memcpy(buff, (char*)param->dll_data + position, size);
  458. return TRUE;
  459. }
  460. ELoadDLLResult LoadDLLFromMemory(const void* dll_data, size_t dll_size, int flags, LOAD_DLL_INFO* info)
  461. {
  462. LOAD_DLL_FROM_MEMORY_STRUCT ldfms = { dll_data, dll_size };
  463. return LoadDLL ((LOAD_DLL_READPROC)&LoadDLLFromMemoryCallback, &ldfms, flags, info);
  464. }
  465. //------------------------------------------------------------------------------
  466. /*
  467. // GetProcAddress functions:
  468. */
  469. FARPROC myGetProcAddress_LoadDLLInfo(LOAD_DLL_INFO* info, const char* func_name)
  470. {
  471. return MyGetProcAddress_ExportDir(info->export_dir_rva, info->image_base, func_name);
  472. }
  473. FARPROC MyGetProcAddress(HMODULE module, const char* func_name)
  474. {
  475. IMAGE_NT_HEADERS* hdr;
  476. __try
  477. {
  478. if (((IMAGE_DOS_HEADER*)module)->e_magic != IMAGE_DOS_SIGNATURE)
  479. return NULL;
  480. hdr = (IMAGE_NT_HEADERS*)((DWORD_PTR)module + ((IMAGE_DOS_HEADER*)module)->e_lfanew);
  481. if (hdr->Signature != IMAGE_NT_SIGNATURE || hdr->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
  482. return NULL;
  483. return MyGetProcAddress_ExportDir(
  484. hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
  485. (DWORD_PTR)module,
  486. func_name
  487. );
  488. }
  489. __except (EXCEPTION_EXECUTE_HANDLER)
  490. {
  491. return NULL;
  492. }
  493. }
  494. FARPROC MyGetProcAddress_ExportDir(DWORD export_dir_rva, DWORD_PTR image_base, const char* func_name)
  495. {
  496. IMAGE_EXPORT_DIRECTORY* exp;
  497. DWORD_PTR ord;
  498. DWORD i;
  499. if (!export_dir_rva)
  500. return NULL;
  501. exp = (IMAGE_EXPORT_DIRECTORY*)(image_base + export_dir_rva);
  502. ord = (DWORD_PTR)func_name;
  503. __try
  504. {
  505. if (ord < 0x10000)
  506. {
  507. /* Search for ordinal. */
  508. if (ord < exp->Base)
  509. return NULL;
  510. ord -= exp->Base;
  511. }
  512. else
  513. {
  514. /* Search for name. */
  515. for (i=0; i<exp->NumberOfNames; ++i)
  516. {
  517. if ( !strcmp( (char*)(((DWORD*)(exp->AddressOfNames + image_base))[i] + image_base), func_name) )
  518. {
  519. ord = ((WORD*)(exp->AddressOfNameOrdinals + image_base))[i];
  520. break;
  521. }
  522. }
  523. }
  524. if (ord >= exp->NumberOfFunctions)
  525. return NULL;
  526. return (FARPROC)(((DWORD*)(exp->AddressOfFunctions + image_base))[ord] + image_base);
  527. }
  528. __except (EXCEPTION_EXECUTE_HANDLER)
  529. {
  530. return NULL;
  531. }
  532. }