Advertisement
Guest User

Untitled

a guest
Sep 19th, 2014
346
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 21.32 KB | None | 0 0
  1. unit BTMemoryModule;
  2.  
  3.  {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  4.   * Memory DLL loading code                                                 *
  5.   * ------------------------                                                *
  6.   *                                                                         *
  7.   * MemoryModule "Conversion to Delphi"                                     *
  8.   * Copyright (c) 2005 - 2006 by Martin Offenwanger / coder@dsplayer.de     *
  9.   * http://www.dsplayer.de                                                  *
  10.   *                                                                         *
  11.   * Original C++ Code "MemoryModule Version 0.0.1"                          *
  12.   * Copyright (c) 2004- 2006 by Joachim Bauch / mail@joachim-bauch.de       *
  13.   * http://www.joachim-bauch.de                                             *
  14.   *                                                                         *
  15.   * This library is free software; you can redistribute it and/or           *
  16.   * modify it under the terms of the GNU Lesser General Public              *
  17.   * License as published by the Free Software Foundation; either            *
  18.   * version 2.1 of the License, or (at your option) any later version.      *
  19.   *                                                                         *
  20.   * This library is distributed in the hope that it will be useful,         *
  21.   * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
  22.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
  23.   * Lesser General Public License for more details.                         *
  24.   *                                                                         *
  25.   * You should have received a copy of the GNU Lesser General Public        *
  26.   * License along with this library; if not, write to the Free Software     *
  27.   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
  28.   *                                                                         *
  29.   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
  30. {
  31. @author(Martin Offenwanger: coder@dsplayer.de)
  32. @created(Mar 20, 2005)
  33. @lastmod(Sep 27, 2005)
  34. }
  35.  
  36. interface
  37.  
  38. uses
  39.   // Borland Run-time Library
  40.   Windows;
  41.  
  42.    {++++++++++++++++++++++++++++++++++++++
  43.     ***  MemoryModule Type Definition  ***
  44.     --------------------------------------}
  45. type
  46.   PBTMemoryModule = ^TBTMemoryModule;
  47.   _BT_MEMORY_MODULE = packed record
  48.     headers: PImageNtHeaders;
  49.     codeBase: Pointer;
  50.     modules: Pointer;
  51.     numModules: integer;
  52.     initialized: boolean;
  53.   end;
  54. {$EXTERNALSYM _BT_MEMORY_MODULE}
  55.   TBTMemoryModule = _BT_MEMORY_MODULE;
  56.   BT_MEMORY_MODULE = _BT_MEMORY_MODULE;
  57. {$EXTERNALSYM BT_MEMORY_MODULE}
  58.  
  59.  
  60.    {++++++++++++++++++++++++++++++++++++++++++++++++++
  61.     ***  Memory DLL loading functions Declaration  ***
  62.     --------------------------------------------------}
  63.  
  64. // return value is nil if function fails
  65. function BTMemoryLoadLibary(var f_data: Pointer; const f_size: int64): PBTMemoryModule; stdcall;
  66. // return value is nil if function fails
  67. function BTMemoryGetProcAddress(var f_module: PBTMemoryModule; const f_name: PAnsiChar): Pointer; stdcall;
  68. // free module
  69. procedure BTMemoryFreeLibrary(var f_module: PBTMemoryModule); stdcall;
  70. // returns last error
  71. function BTMemoryGetLastError: AnsiString; stdcall;
  72.  
  73.  
  74. implementation
  75.  
  76. uses
  77.   // Borland Run-time Library
  78.   SysUtils;
  79.  
  80.    {+++++++++++++++++++++++++++++++++++
  81.     ***  Dll EntryPoint Definition  ***
  82.     -----------------------------------}
  83. type
  84.   TDllEntryProc = function(hinstdll: THandle; fdwReason: DWORD; lpReserved: Pointer): BOOL; stdcall;
  85.  
  86.  
  87.    {++++++++++++++++++++++++++++++++++++++++
  88.     ***  Missing Windows API Definitions ***
  89.     ----------------------------------------}
  90.  
  91.   PImageBaseRelocation = ^TImageBaseRelocation;
  92.   _IMAGE_BASE_RELOCATION = packed record
  93.     VirtualAddress: DWORD;
  94.     SizeOfBlock: DWORD;
  95.   end;
  96. {$EXTERNALSYM _IMAGE_BASE_RELOCATION}
  97.   TImageBaseRelocation = _IMAGE_BASE_RELOCATION;
  98.   IMAGE_BASE_RELOCATION = _IMAGE_BASE_RELOCATION;
  99. {$EXTERNALSYM IMAGE_BASE_RELOCATION}
  100.  
  101.   PImageImportDescriptor = ^TImageImportDescriptor;
  102.   _IMAGE_IMPORT_DESCRIPTOR = packed record
  103.     OriginalFirstThunk: DWORD;
  104.     TimeDateStamp: DWORD;
  105.     ForwarderChain: DWORD;
  106.     Name: DWORD;
  107.     FirstThunk: DWORD;
  108.   end;
  109. {$EXTERNALSYM _IMAGE_IMPORT_DESCRIPTOR}
  110.   TImageImportDescriptor = _IMAGE_IMPORT_DESCRIPTOR;
  111.   IMAGE_IMPORT_DESCRIPTOR = _IMAGE_IMPORT_DESCRIPTOR;
  112. {$EXTERNALSYM IMAGE_IMPORT_DESCRIPTOR}
  113.  
  114.   PImageImportByName = ^TImageImportByName;
  115.   _IMAGE_IMPORT_BY_NAME = packed record
  116.     Hint: Word;
  117.     Name: array[0..255] of Byte; // original: "Name: array [0..0] of Byte;"
  118.   end;
  119. {$EXTERNALSYM _IMAGE_IMPORT_BY_NAME}
  120.   TImageImportByName = _IMAGE_IMPORT_BY_NAME;
  121.   IMAGE_IMPORT_BY_NAME = _IMAGE_IMPORT_BY_NAME;
  122. {$EXTERNALSYM IMAGE_IMPORT_BY_NAME}
  123.  
  124. const
  125.   IMAGE_SIZEOF_BASE_RELOCATION = 8;
  126. {$EXTERNALSYM IMAGE_SIZEOF_BASE_RELOCATION}
  127.   IMAGE_REL_BASED_HIGHLOW = 3;
  128. {$EXTERNALSYM IMAGE_REL_BASED_HIGHLOW}
  129.   IMAGE_ORDINAL_FLAG32 = DWORD($80000000);
  130. {$EXTERNALSYM IMAGE_ORDINAL_FLAG32}
  131.  
  132. var
  133.   lastErrStr: AnsiString;
  134.  
  135.  
  136.    {+++++++++++++++++++++++++++++++++++++++++++++++++++++
  137.     ***  Memory DLL loading functions Implementation  ***
  138.     -----------------------------------------------------}
  139.  
  140. function BTMemoryGetLastError: AnsiString; stdcall;
  141. begin
  142.   Result := lastErrStr;
  143. end;
  144.  
  145. function GetFieldOffset(const Struc; const Field): Cardinal; stdcall;
  146. begin
  147.   Result := Cardinal(@Field) - Cardinal(@Struc);
  148. end;
  149.  
  150. function GetImageFirstSection(NtHeader: PImageNtHeaders): PImageSectionHeader; stdcall;
  151. begin
  152.   Result := PImageSectionHeader(Cardinal(NtHeader) +
  153.     GetFieldOffset(NtHeader^, NtHeader^.OptionalHeader) +
  154.     NtHeader^.FileHeader.SizeOfOptionalHeader);
  155. end;
  156.  
  157. function GetHeaderDictionary(f_module: PBTMemoryModule; f_idx: integer): PImageDataDirectory; stdcall;
  158. begin
  159.   Result := PImageDataDirectory(@(f_module.headers.OptionalHeader.DataDirectory[f_idx]));
  160. end;
  161.  
  162. function GetImageOrdinal(Ordinal: DWORD): Word; stdcall;
  163. begin
  164.   Result := Ordinal and $FFFF;
  165. end;
  166.  
  167. function GetImageSnapByOrdinal(Ordinal: DWORD): Boolean; stdcall;
  168. begin
  169.   Result := ((Ordinal and IMAGE_ORDINAL_FLAG32) <> 0);
  170. end;
  171.  
  172. procedure CopySections(const f_data: Pointer; const f_old_headers: TImageNtHeaders; f_module: PBTMemoryModule); stdcall;
  173. var
  174.   l_size, i: integer;
  175.   l_codebase: Pointer;
  176.   l_dest: Pointer;
  177.   l_section: PImageSectionHeader;
  178. begin
  179.   l_codebase := f_module.codeBase;
  180.   l_section := GetImageFirstSection(f_module.headers);
  181.   for i := 0 to f_module.headers.FileHeader.NumberOfSections - 1 do begin
  182.     // section doesn't contain data in the dll itself, but may define
  183.     // uninitialized data
  184.     if (l_section.SizeOfRawData = 0) then begin
  185.       l_size := f_old_headers.OptionalHeader.SectionAlignment;
  186.       if l_size > 0 then begin
  187.         l_dest := VirtualAlloc(Pointer(Cardinal(l_codebase) + l_section.VirtualAddress), l_size, MEM_COMMIT, PAGE_READWRITE);
  188.         l_section.Misc.PhysicalAddress := cardinal(l_dest);
  189.         ZeroMemory(l_dest, l_size);
  190.       end;
  191.       inc(longword(l_section), sizeof(TImageSectionHeader));
  192.       // Continue with the nex loop
  193.       Continue;
  194.     end;
  195.     // commit memory block and copy data from dll
  196.     l_dest := VirtualAlloc(Pointer(Cardinal(l_codebase) + l_section.VirtualAddress), l_section.SizeOfRawData, MEM_COMMIT, PAGE_READWRITE);
  197.     CopyMemory(l_dest, Pointer(longword(f_data) + l_section.PointerToRawData), l_section.SizeOfRawData);
  198.     l_section.Misc.PhysicalAddress := cardinal(l_dest);
  199.     // IMAGE_SIZEOF_SECTION_HEADER
  200.     inc(longword(l_section), sizeof(TImageSectionHeader));
  201.   end;
  202. end;
  203.  
  204. procedure PerformBaseRelocation(f_module: PBTMemoryModule; f_delta: Cardinal); stdcall;
  205. var
  206.   l_i: Cardinal;
  207.   l_codebase: Pointer;
  208.   l_directory: PImageDataDirectory;
  209.   l_relocation: PImageBaseRelocation;
  210.   l_dest: Pointer;
  211.   l_relInfo: ^Word;
  212.   l_patchAddrHL: ^DWord;
  213.   l_type, l_offset: integer;
  214. begin
  215.   l_codebase := f_module.codeBase;
  216.   l_directory := GetHeaderDictionary(f_module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
  217.   if l_directory.Size > 0 then begin
  218.     l_relocation := PImageBaseRelocation(Cardinal(l_codebase) + l_directory.VirtualAddress);
  219.     while l_relocation.VirtualAddress > 0 do begin
  220.       l_dest := Pointer((Cardinal(l_codebase) + l_relocation.VirtualAddress));
  221.       l_relInfo := Pointer(Cardinal(l_relocation) + IMAGE_SIZEOF_BASE_RELOCATION);
  222.       for l_i := 0 to (trunc(((l_relocation.SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2)) - 1) do begin
  223.         // the upper 4 bits define the type of relocation
  224.         l_type := (l_relInfo^ shr 12);
  225.         // the lower 12 bits define the offset
  226.         l_offset := l_relInfo^ and $FFF;
  227.         //showmessage(inttostr(l_relInfo^));
  228.         if l_type = IMAGE_REL_BASED_HIGHLOW then begin
  229.           // change complete 32 bit address
  230.           l_patchAddrHL := Pointer(Cardinal(l_dest) + Cardinal(l_offset));
  231.           l_patchAddrHL^ := l_patchAddrHL^ + f_delta;
  232.         end;
  233.         inc(l_relInfo);
  234.       end;
  235.       l_relocation := Pointer(cardinal(l_relocation) + l_relocation.SizeOfBlock);
  236.     end;
  237.   end;
  238. end;
  239.  
  240. function BuildImportTable(f_module: PBTMemoryModule): boolean; stdcall;
  241. var
  242.   l_codeBase: Pointer;
  243.   l_directory: PImageDataDirectory;
  244.   l_importDesc: PImageImportDescriptor;
  245.   l_thunkRef, l_funcRef: ^DWORD;
  246.   l_handle: HMODULE;
  247.   l_temp: integer;
  248.   l_thunkData: TImageImportByName;
  249. begin
  250.   Result := true;
  251.   l_codeBase := f_module.codeBase;
  252.   l_directory := GetHeaderDictionary(f_module, IMAGE_DIRECTORY_ENTRY_IMPORT);
  253.   if (l_directory.Size > 0) then begin
  254.     l_importDesc := PImageImportDescriptor(Cardinal(l_codeBase) + l_directory.VirtualAddress);
  255.     while (not IsBadReadPtr(l_importDesc, sizeof(TImageImportDescriptor))) and (l_importDesc.Name <> 0) do begin
  256.       l_handle := LoadLibraryA(PAnsiChar(Cardinal(l_codeBase) + l_importDesc.Name));
  257.       if (l_handle = INVALID_HANDLE_VALUE) then begin
  258.         lastErrStr := AnsiString('BuildImportTable: can''t load library: ') + PAnsiChar(Cardinal(l_codeBase) + l_importDesc.Name);
  259.         Result := false;
  260.         exit;
  261.       end;
  262.       // ReallocMemory crashes if "f_module.modules = nil"
  263.       if f_module.modules = nil then
  264.         f_module.modules := AllocMem(1);
  265.       f_module.modules := ReallocMemory(f_module.modules, ((f_module.numModules + 1) * (sizeof(HMODULE))));
  266.       if f_module.modules = nil then begin
  267.         lastErrStr := 'BuildImportTable: ReallocMemory failed';
  268.         result := false;
  269.         exit;
  270.       end;
  271.       // module->modules[module->numModules++] = handle;
  272.       l_temp := (sizeof(cardinal) * (f_module.numModules));
  273.       inc(Cardinal(f_module.modules), l_temp);
  274.       cardinal(f_module.modules^) := l_handle;
  275.       dec(Cardinal(f_module.modules), l_temp);
  276.       f_module.numModules := f_module.numModules + 1;
  277.       if l_importDesc.OriginalFirstThunk <> 0 then begin
  278.         l_thunkRef := Pointer(Cardinal(l_codeBase) + l_importDesc.OriginalFirstThunk);
  279.         l_funcRef := Pointer(Cardinal(l_codeBase) + l_importDesc.FirstThunk);
  280.       end else begin
  281.         // no hint table
  282.         l_thunkRef := Pointer(Cardinal(l_codeBase) + l_importDesc.FirstThunk);
  283.         l_funcRef := Pointer(Cardinal(l_codeBase) + l_importDesc.FirstThunk);
  284.       end;
  285.       while l_thunkRef^ <> 0 do begin
  286.         if GetImageSnapByOrdinal(l_thunkRef^) then
  287.           l_funcRef^ := Cardinal(GetProcAddress(l_handle, PAnsiChar(GetImageOrdinal(l_thunkRef^))))
  288.         else begin
  289.           CopyMemory(@l_thunkData, Pointer(Cardinal(l_codeBase) + l_thunkRef^), sizeof(TImageImportByName));
  290.           l_funcRef^ := Cardinal(GetProcAddress(l_handle, PAnsiChar(@(l_thunkData.Name))));
  291.         end;
  292.         if l_funcRef^ = 0 then begin
  293.           lastErrStr := 'BuildImportTable: GetProcAddress failed';
  294.           result := false;
  295.           break;
  296.         end;
  297.         inc(l_funcRef);
  298.         inc(l_thunkRef);
  299.       end;
  300.       inc(longword(l_importDesc), sizeof(TImageImportDescriptor));
  301.     end;
  302.   end;
  303. end;
  304.  
  305. function GetSectionProtection(SC: cardinal): cardinal; stdcall;
  306. //SC – ImageSectionHeader.Characteristics
  307. begin
  308.   result := 0;
  309.   if (SC and IMAGE_SCN_MEM_NOT_CACHED) <> 0 then
  310.     result := result or PAGE_NOCACHE;
  311.   // E - Execute, R – Read , W – Write
  312.   if (SC and IMAGE_SCN_MEM_EXECUTE) <> 0 //E ?
  313.     then if (SC and IMAGE_SCN_MEM_READ) <> 0 //ER ?
  314.     then if (SC and IMAGE_SCN_MEM_WRITE) <> 0 //ERW ?
  315.       then result := result or PAGE_EXECUTE_READWRITE
  316.       else result := result or PAGE_EXECUTE_READ
  317.     else if (SC and IMAGE_SCN_MEM_WRITE) <> 0 //EW?
  318.       then result := result or PAGE_EXECUTE_WRITECOPY
  319.     else result := result or PAGE_EXECUTE
  320.   else if (SC and IMAGE_SCN_MEM_READ) <> 0 // R?
  321.     then if (SC and IMAGE_SCN_MEM_WRITE) <> 0 //RW?
  322.     then result := result or PAGE_READWRITE
  323.     else result := result or PAGE_READONLY
  324.   else if (SC and IMAGE_SCN_MEM_WRITE) <> 0 //W?
  325.     then result := result or PAGE_WRITECOPY
  326.   else result := result or PAGE_NOACCESS;
  327. end;
  328.  
  329. procedure FinalizeSections(f_module: PBTMemoryModule); stdcall;
  330. var
  331.   l_i: integer;
  332.   l_section: PImageSectionHeader;
  333.   l_protect, l_oldProtect, l_size: Cardinal;
  334. begin
  335.   l_section := GetImageFirstSection(f_module.headers);
  336.   for l_i := 0 to f_module.headers.FileHeader.NumberOfSections - 1 do begin
  337.  
  338.     if (l_section.Characteristics and IMAGE_SCN_MEM_DISCARDABLE) <> 0 then begin
  339.       // section is not needed any more and can safely be freed
  340.       VirtualFree(Pointer(l_section.Misc.PhysicalAddress), l_section.SizeOfRawData, MEM_DECOMMIT);
  341.       inc(longword(l_section), sizeof(TImageSectionHeader));
  342.       continue;
  343.     end;
  344.  
  345.     l_protect := GetSectionProtection(l_section.Characteristics);
  346.     if (l_section.Characteristics and IMAGE_SCN_MEM_NOT_CACHED) <> 0 then
  347.       l_protect := (l_protect or PAGE_NOCACHE);
  348.  
  349.     // determine size of region
  350.     l_size := l_section.SizeOfRawData;
  351.     if l_size = 0 then begin
  352.       if (l_section.Characteristics and IMAGE_SCN_CNT_INITIALIZED_DATA) <> 0 then begin
  353.         l_size := f_module.headers.OptionalHeader.SizeOfInitializedData;
  354.       end else begin
  355.         if (l_section.Characteristics and IMAGE_SCN_CNT_UNINITIALIZED_DATA) <> 0 then
  356.           l_size := f_module.headers.OptionalHeader.SizeOfUninitializedData;
  357.       end;
  358.       if l_size > 0 then begin
  359.         if not VirtualProtect(Pointer(l_section.Misc.PhysicalAddress), l_section.SizeOfRawData, l_protect, @l_oldProtect) then begin
  360.           lastErrStr := 'FinalizeSections: VirtualProtect failed';
  361.           exit;
  362.         end;
  363.       end;
  364.     end;
  365.     inc(longword(l_section), sizeof(TImageSectionHeader));
  366.   end;
  367. end;
  368.  
  369. function BTMemoryLoadLibary(var f_data: Pointer; const f_size: int64): PBTMemoryModule; stdcall;
  370. var
  371.   l_result: PBTMemoryModule;
  372.   l_dos_header: TImageDosHeader;
  373.   l_old_header: TImageNtHeaders;
  374.   l_code, l_headers: Pointer;
  375.   l_locationdelta: Cardinal;
  376.   l_DllEntry: TDllEntryProc;
  377.   l_successfull: boolean;
  378. begin
  379.   l_result := nil;
  380.   Result := nil;
  381.   try
  382.     CopyMemory(@l_dos_header, f_data, sizeof(_IMAGE_DOS_HEADER));
  383.     if (l_dos_header.e_magic <> IMAGE_DOS_SIGNATURE) then begin
  384.       lastErrStr := 'BTMemoryLoadLibary: dll dos header is not valid';
  385.       exit;
  386.     end;
  387.     CopyMemory(@l_old_header, pointer(longint(f_data) + l_dos_header._lfanew), sizeof(_IMAGE_NT_HEADERS));
  388.     if l_old_header.Signature <> IMAGE_NT_SIGNATURE then begin
  389.       lastErrStr := 'BTMemoryLoadLibary: IMAGE_NT_SIGNATURE is not valid';
  390.       exit;
  391.     end;
  392.     // reserve memory for image of library
  393.     l_code := VirtualAlloc(Pointer(l_old_header.OptionalHeader.ImageBase), l_old_header.OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_READWRITE);
  394.     if l_code = nil then
  395.         // try to allocate memory at arbitrary position
  396.       l_code := VirtualAlloc(nil, l_old_header.OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_READWRITE);
  397.     if l_code = nil then begin
  398.       lastErrStr := 'BTMemoryLoadLibary: VirtualAlloc failed';
  399.       exit;
  400.     end;
  401.     // alloc space for the result record
  402.     l_result := PBTMemoryModule(HeapAlloc(GetProcessHeap(), 0, sizeof(TBTMemoryModule)));
  403.     l_result.codeBase := l_code;
  404.     l_result.numModules := 0;
  405.     l_result.modules := nil;
  406.     l_result.initialized := false;
  407.     // xy: is it correct to commit the complete memory region at once?
  408.     //     calling DllEntry raises an exception if we don't...
  409.     VirtualAlloc(l_code, l_old_header.OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_READWRITE);
  410.     // commit memory for headers
  411.     l_headers := VirtualAlloc(l_code, l_old_header.OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE);
  412.     // copy PE header to code
  413.     CopyMemory(l_headers, f_data, (Cardinal(l_dos_header._lfanew) + l_old_header.OptionalHeader.SizeOfHeaders));
  414.     l_result.headers := PImageNtHeaders(longint(l_headers) + l_dos_header._lfanew);
  415.     // update position
  416.     l_result.headers.OptionalHeader.ImageBase := cardinal(l_code);
  417.     // copy sections from DLL file block to new memory location
  418.     CopySections(f_data, l_old_header, l_result);
  419.     // adjust base address of imported data
  420.     l_locationdelta := Cardinal(Cardinal(l_code) - l_old_header.OptionalHeader.ImageBase);
  421.     if l_locationdelta <> 0 then
  422.       PerformBaseRelocation(l_result, l_locationdelta);
  423.     // load required dlls and adjust function table of imports
  424.     if not BuildImportTable(l_result) then begin
  425.       lastErrStr := lastErrStr + ' BTMemoryLoadLibary: BuildImportTable failed';
  426.       Abort;
  427.     end;
  428.     // mark memory pages depending on section headers and release
  429.     // sections that are marked as "discardable"
  430.     FinalizeSections(l_result);
  431.     // get entry point of loaded library
  432.     if (l_result.headers.OptionalHeader.AddressOfEntryPoint) <> 0 then begin
  433.       @l_DllEntry := Pointer(Cardinal(l_code) + l_result.headers.OptionalHeader.AddressOfEntryPoint);
  434.       if @l_DllEntry = nil then begin
  435.         lastErrStr := 'BTMemoryLoadLibary: Get DLLEntyPoint failed';
  436.         Abort;
  437.       end;
  438.       l_successfull := l_DllEntry(Cardinal(l_code), DLL_PROCESS_ATTACH, nil);
  439.       if not l_successfull then begin
  440.         lastErrStr := 'BTMemoryLoadLibary: Can''t attach library';
  441.         Abort;
  442.       end;
  443.       l_result.initialized := true;
  444.     end;
  445.   except
  446.     BTMemoryFreeLibrary(l_result);
  447.     exit;
  448.   end;
  449.   Result := l_result;
  450. end;
  451.  
  452. function BTMemoryGetProcAddress(var f_module: PBTMemoryModule; const f_name: PAnsiChar): Pointer; stdcall;
  453. var
  454.   l_codeBase: Pointer;
  455.   l_idx: integer;
  456.   l_i: DWORD;
  457.   l_nameRef: ^DWORD;
  458.   l_ordinal: ^WORD;
  459.   l_exports: PImageExportDirectory;
  460.   l_directory: PImageDataDirectory;
  461.   l_temp: ^DWORD;
  462. begin
  463.   Result := nil;
  464.   l_codeBase := f_module.codeBase;
  465.   l_idx := -1;
  466.   l_directory := GetHeaderDictionary(f_module, IMAGE_DIRECTORY_ENTRY_EXPORT);
  467.   if l_directory.Size = 0 then begin
  468.     lastErrStr := 'BTMemoryGetProcAddress: no export table found';
  469.     exit;
  470.   end;
  471.   l_exports := PImageExportDirectory(Cardinal(l_codeBase) + l_directory.VirtualAddress);
  472.   if ((l_exports.NumberOfNames = 0) or (l_exports.NumberOfFunctions = 0)) then begin
  473.     lastErrStr := 'BTMemoryGetProcAddress: DLL doesn''t export anything';
  474.     exit;
  475.   end;
  476.   // search function name in list of exported names
  477.   l_nameRef := Pointer(Cardinal(l_codeBase) + Cardinal(l_exports.AddressOfNames));
  478.   l_ordinal := Pointer(Cardinal(l_codeBase) + Cardinal(l_exports.AddressOfNameOrdinals));
  479.   for l_i := 0 to l_exports.NumberOfNames - 1 do begin
  480.     if StrComp(f_name, PAnsiChar(Cardinal(l_codeBase) + l_nameRef^)) = 0 then begin
  481.       l_idx := l_ordinal^;
  482.       break;
  483.     end;
  484.     inc(l_nameRef);
  485.     inc(l_ordinal);
  486.   end;
  487.   if (l_idx = -1) then begin
  488.     lastErrStr := 'BTMemoryGetProcAddress: exported symbol not found';
  489.     exit;
  490.   end;
  491.   if (Cardinal(l_idx) > l_exports.NumberOfFunctions - 1) then begin
  492.     lastErrStr := 'BTMemoryGetProcAddress: name <-> ordinal number don''t match';
  493.     exit;
  494.   end;
  495.   // AddressOfFunctions contains the RVAs to the "real" functions
  496.   l_temp := Pointer(Cardinal(l_codeBase) + Cardinal(l_exports.AddressOfFunctions) + Cardinal((l_idx * 4)));
  497.   Result := Pointer(Cardinal(l_codeBase) + l_temp^);
  498. end;
  499.  
  500. procedure BTMemoryFreeLibrary(var f_module: PBTMemoryModule); stdcall;
  501. var
  502.   l_module: PBTMemoryModule;
  503.   l_i: integer;
  504.   l_temp: integer;
  505.   l_DllEntry: TDllEntryProc;
  506. begin
  507.   l_module := f_module;
  508.   if l_module <> nil then begin
  509.     if l_module.initialized then begin
  510.       @l_DllEntry := Pointer(Cardinal(l_module.codeBase) + l_module.headers.OptionalHeader.AddressOfEntryPoint);
  511.       l_DllEntry(Cardinal(l_module.codeBase), DLL_PROCESS_DETACH, nil);
  512.       l_module.initialized := false;
  513.       // free previously opened libraries
  514.       for l_i := 0 to l_module.numModules - 1 do begin
  515.         l_temp := (sizeof(cardinal) * (l_i));
  516.         inc(Cardinal(l_module.modules), l_temp);
  517.         if Cardinal(f_module.modules^) <> INVALID_HANDLE_VALUE then
  518.           FreeLibrary(Cardinal(f_module.modules^));
  519.         dec(Cardinal(l_module.modules), l_temp);
  520.       end;
  521.       FreeMemory(l_module.modules);
  522.       if l_module.codeBase <> nil then
  523.         // release memory of library
  524.         VirtualFree(l_module.codeBase, 0, MEM_RELEASE);
  525.       HeapFree(GetProcessHeap(), 0, f_module);
  526.       Pointer(f_module) := nil;
  527.     end;
  528.   end;
  529. end;
  530.  
  531. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement