Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.06.05;
Скачать: CL | DM;

Вниз

загрузка dll из ресурса   Найти похожие ветки 

 
Scott Storch   (2011-01-13 17:47) [0]

Приложение юзает функции библиотеки 7z.dll. Проблема, заказчик не хочет таскать вместе с исполняемым файлом файл библиотеки. Думаю запихнуть ее в ресурс. Как из ресурса ее потом загрузить через LoadLibrary?


 
Ega23 ©   (2011-01-13 17:53) [1]


>  Проблема, заказчик не хочет таскать вместе с исполняемым
> файлом файл библиотеки.


Запиши всё в один rar.exe :)


 
Scott Storch   (2011-01-13 17:57) [2]

А по существу


 
Leonid Troyanovsky ©   (2011-01-13 18:00) [3]


> Scott Storch   (13.01.11 17:57) [2]

> А по существу

Красть грешно.

--
Regards, LVT.


 
DiamondShark ©   (2011-01-13 18:13) [4]


> Как из ресурса ее потом загрузить через LoadLibrary?

Записать в файл и загрузить.

А вообще, заказчик странного хочет.


 
Rouse_ ©   (2011-01-13 19:22) [5]

////////////////////////////////////////////////////////////////////////////////
//
//  ****************************************************************************
//  * Unit Name : DLLLoader
//  * Purpose   : Модуль подгрузки и инициализации DLL из памяти
//  *           : без выгрузки на диск.
//  *           : На основе статьи "Загрузчик PE-файлов" Максима Гумерова
//  *           : http://rsdn.ru/article/baseserv/peloader.xml
//  * Author    : Александр (Rouse_) Багель
//  * Copyright : Центр Гранд 2001 - 2007 г.
//  * Version   : 1.00
//  ****************************************************************************
//

unit DLLLoader;

interface

uses
 Windows;

 function xLoadLibrary(Image: Pointer): HMODULE;
 function xGetProcAddress(Module: HMODULE; ProcName: PChar): Pointer;
 function xFreeLibrary(Module: HMODULE): Boolean;

implementation

uses
 Classes, SysUtils, Types, Math;

type
 TSections = array [0..0] of TImageSectionHeader;
 TDllEntryProc = function(Hinst: Integer;
   Reason: Integer; Resvd: Pointer): LongBool; stdcall;

 TLibInfo = record
   ImageBase: Pointer;//Базовый адрес образа
   DllProc: TDllEntryProc;
   //Список, содержащий имена импользуемых DLL модулей и их значения HModule
   LibsUsed: array of record
     Name: String;
     Instance: HModule;
   end;
   PExports: PImageExportDirectory;
   BlockSize: Cardinal;
 end;
 PLibInfo = ^TLibInfo;

 TWordArray = array [0..0] of Word;
 PWordArray = ^TWordArray;
 TDWORDArray = array [0..0] of DWORD;
 PDWORDArray = ^TDWORDArray;

 TImageBaseRelocation = packed record
   VirtualAddress: Cardinal;
   SizeOfBlock: Cardinal;
 end;
 PImageBaseRelocation = ^TImageBaseRelocation;

 TImageImportDescriptor = packed record //(C++:  IMAGE_IMPORT_DESCRIPTOR)
   OriginalFirstThunk: DWORD;//Ранее это поле называлось Characteristics; в целях сохранения
   //совместимости кода это название поддерживается и сейчас, но не
   //отражает содержание поля. Далее мы на нем остановимся подробнее
   TimeDateStamp: DWORD;//0, если импортирование осуществляется без привязки (binding - см. далее)
   //При импортировании с привязкой содержит отметку времени файла, из которого
   // импортируем, но:
   //Если -1, то здесь использовался новый стиль привязки
   ForwarderChain: DWORD;// См. описание импорта с привязкой (далее)
   Name: DWORD;//Виртуальный адрес ASCII-строки с именем файла, из которого импортируем
   FirstThunk: DWORD;//Виртуальный адрес подтаблицы импортируемых символов
 end;
 PImageImportDescriptor = ^TImageImportDescriptor;

var
 LoadedLibs: TList = nil;

function xFreeLibrary(Module: HMODULE): Boolean;
var
 I, J: Integer;
 LibInfo: PLibInfo;

 procedure CallProcessDetach;
 begin
   try
     if @LibInfo.DllProc <> nil then
       LibInfo.DllProc(Module, DLL_PROCESS_DETACH, nil);
   except
   end;
 end;

begin
 Result := False;
 if (Module = 0) or not Assigned(LoadedLibs) then Exit;
 for I := 0 to LoadedLibs.Count - 1 do
 begin
   LibInfo := LoadedLibs[I];
   if LibInfo.ImageBase = Pointer(Module) then
   begin
     LoadedLibs.Delete(I);
     CallProcessDetach;
     for J := 0 to High(LibInfo.LibsUsed) do
       FreeLibrary(LibInfo.LibsUsed[J].Instance);
     Dispose(LibInfo);
     Result := True;
     Break;
   end;
 end;
 VirtualFree(Pointer(Module), 0, MEM_RELEASE);
end;

function GetLibrary(LibInfo: PLibInfo; const DLLName: String): HModule;
var
 I: Integer;
begin
 for I := 0 to High(LibInfo.LibsUsed) do
   if AnsiSameText(LibInfo.LibsUsed[I].Name, DLLName) then
   begin
     Result := LibInfo.LibsUsed[I].Instance;
     Exit;
   end;
 Result := LoadLibrary(PChar(DllName));
 SetLength(LibInfo.LibsUsed, Length(LibInfo.LibsUsed) + 1);
 with LibInfo.LibsUsed[High(LibInfo.LibsUsed)] do
 begin
   Name := DllName;
   Instance := Result;
 end;
end;

function xGetProcAddress(Module: HMODULE; ProcName: PChar): Pointer;
var
 I, J, A: Integer;
 LibInfo: PLibInfo;
 PC: PChar;
 S: String;
begin
 Result := nil;
 if (Module = 0) or not Assigned(LoadedLibs) then Exit;
 for I := 0 to LoadedLibs.Count - 1 do
   if TLibInfo(LoadedLibs[I]^).ImageBase = Pointer(Module) then
   begin
     LibInfo := LoadedLibs[I];
     //Проход по всем символам, экспортированным по имени
     for J := 0 to LibInfo.PExports.NumberOfNames - 1 do
       if StrComp(ProcName, PChar(PDWORDArray(
         Cardinal(LibInfo.PExports.AddressOfNames) +
         Cardinal(LibInfo.ImageBase))^[J] +
         Cardinal(LibInfo.ImageBase))) = 0 then
       begin
         Result := Pointer(PDWORDArray(
           Cardinal(LibInfo.PExports.AddressOfFunctions) +
           Cardinal(LibInfo.ImageBase))^[
           PWordArray(Cardinal(LibInfo.PExports.AddressOfNameOrdinals) +
           Cardinal(LibInfo.ImageBase))^[J]] + Cardinal(LibInfo.ImageBase));
           
         if (PChar(Result) >= PChar(LibInfo.PExports)) and
           (PChar(Result) < PChar(LibInfo.PExports) + LibInfo.BlockSize) then
         begin
           S := PChar(Result);
           Result := nil;
           A := Pos(".", S);
           if A = 0 then Exit;
           if S[A + 1] = "#" then
             PC := Pointer(StrToIntDef(Copy(S, A + 2, MaxInt), -1))
           else
             PC := @S[A + 1];
           Result := GetProcAddress(
             GetLibrary(LibInfo, Copy(S, 1, A - 1)), PC);
           Exit;
         end;
       end;
     Break;
   end;
end;


 
Rouse_ ©   (2011-01-13 19:23) [6]

function XLoadLibrary(Image: Pointer): HMODULE;
var
 ImageBase, SectionBase: Pointer;
 ImageBaseDelta: Integer;
 PEHeader: PImageNtHeaders;
 PSections: ^TSections;
 S: Integer;
 VirtualSectionSize, RawSectionSize, Dummy: Cardinal;
 PNewLibInfo: PLibInfo;

 procedure ProcessRelocs(PRelocs: PImageBaseRelocation);
 var
   PReloc: PImageBaseRelocation;
   P: PWord;
   I: Cardinal;
 begin
   PReloc := PRelocs;
   while Cardinal(PReloc) - Cardinal(PRelocs) <
     PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size do
   begin
     P := Pointer(Cardinal(PReloc) + SizeOf(PReloc^));
     for I := 0 to(PReloc.SizeOfBlock -
       SizeOf(TImageBaseRelocation)) div 2 - 1 do
     begin
       if P^and $F000 <> 0 {//Если тип ссылки - не IMAGE_REL_BASED_ABSOLUTE(=0)} then
         Inc(PDWORD(Cardinal(ImageBase) +
           PReloc.VirtualAddress + (P^ and $0FFF))^, ImageBaseDelta);//Исправляем ссылку
       Inc(P);
     end;
     PReloc := Pointer(P);
   end;
 end;

 procedure ProcessImports(PImport: PImageImportDescriptor);
 var
   PRVA_Import: LPDWORD;
   LibHandle: HModule;
 begin
   while PImport.Name <> 0 do
   begin
     LibHandle :=
       GetLibrary(PNewLibInfo, PChar(Cardinal(PImport.Name) +
         Cardinal(ImageBase)));
     if PImport.TimeDateStamp = 0{//Привязка есть?} then
       PRVA_Import := LPDWORD(pImport.FirstThunk + Cardinal(ImageBase))
     else
       PRVA_Import := LPDWORD(pImport.OriginalFirstThunk + Cardinal(ImageBase));
     while PRVA_Import^ <> 0 do
     begin
       if (PRVA_Import^and $80000000) <> 0 then //Это импортирование по номеру
         PPointer(PRVA_Import)^ :=
           GetProcAddress(LibHandle, PChar(PRVA_Import^ and $FFFF))
       else
         PPointer(PRVA_Import)^ :=
           GetProcAddress(LibHandle, PChar(PRVA_Import^ + DWORD(ImageBase) + 2));
       Inc(PRVA_Import);
     end;
     Inc(PImport);
   end;
 end;
 
 function GetSectionProtection(SC: Cardinal): Cardinal;
   //SC - значение ImageSectionHeader.Characteristics,
   //на выходе - значение флагов доступа для VirtualProtect
 const
   Mapping: array[0..7] of ULONG =
     (
       PAGE_NOACCESS,
       PAGE_EXECUTE,
       PAGE_READONLY,
       PAGE_EXECUTE_READ,
       PAGE_READWRITE,
       PAGE_EXECUTE_READWRITE,
       PAGE_READWRITE,
       PAGE_EXECUTE_READWRITE);
 begin
   Result := Mapping[SC shr 29] or
     DWORD(IfThen((SC and IMAGE_SCN_MEM_NOT_CACHED) <> 0, PAGE_NOCACHE));
 end;
 
begin
 Result := 0;
 try
   PEHeader :=
     Pointer(Int64(Cardinal(Image)) + PImageDosHeader(Image)._lfanew);
   ImageBase :=
     VirtualAlloc(nil, PEHeader.OptionalHeader.SizeOfImage,
       MEM_RESERVE, PAGE_NOACCESS);
   if ImageBase = nil then OutOfMemoryError;
   ImageBaseDelta := DWORD(ImageBase) - PEHeader.OptionalHeader.ImageBase;
   SectionBase :=
     VirtualAlloc(ImageBase, PEHeader.OptionalHeader.SizeOfHeaders,
       MEM_COMMIT, PAGE_READWRITE);
   if SectionBase = nil then OutOfMemoryError;
   Move(Image^, SectionBase^, PEHeader.OptionalHeader.SizeOfHeaders);
   VirtualProtect(SectionBase, PEHeader.OptionalHeader.SizeOfHeaders,
     PAGE_READONLY, Dummy);
   PSections := Pointer(PChar(@(PEHeader.OptionalHeader)) +
     PEHeader.FileHeader.SizeOfOptionalHeader);
   for S := 0 to PEHeader.FileHeader.NumberOfSections - 1 do
   begin
     VirtualSectionSize := PSections[S].Misc.VirtualSize;
     RawSectionSize := PSections[S].SizeOfRawData;
     if VirtualSectionSize < RawSectionSize then
       VirtualSectionSize := PSections[S].SizeOfRawData;
     SectionBase := VirtualAlloc(PSections[S].VirtualAddress +
       PChar(ImageBase), VirtualSectionSize, MEM_COMMIT, PAGE_READWRITE);
     if SectionBase = nil then OutOfMemoryError;
     Move((PChar(Image) + PSections[S].PointerToRawData)^,
       SectionBase^, RawSectionSize);
   end;
   if LoadedLibs = nil then
     LoadedLibs := TList.Create;
   New(PNewLibInfo);
   FillChar(PNewLibInfo^, SizeOf(TLibInfo),0);
   PNewLibInfo^.DllProc :=
     TDllEntryProc(PEHeader.OptionalHeader.AddressOfEntryPoint +
       Cardinal(ImageBase));
   PNewLibInfo^.ImageBase := ImageBase;
   LoadedLibs.Add(PNewLibInfo);
   with PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC] do
     if VirtualAddress <> 0 then
       ProcessRelocs(Pointer(VirtualAddress + Cardinal(ImageBase)));
   with PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] do
     if VirtualAddress <> 0 then
       ProcessImports(Pointer(VirtualAddress + Cardinal(ImageBase)));
   with PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] do
     if VirtualAddress <> 0 then
     begin
       PNewLibInfo^.PExports := Pointer(VirtualAddress+Cardinal(ImageBase));
       PNewLibInfo^.BlockSize := Size;
     end;
   for S := 0 to PEHeader.FileHeader.NumberOfSections - 1 do
     with PSections[S] do
       VirtualProtect(VirtualAddress + PChar(ImageBase),
         Misc.VirtualSize,GetSectionProtection(Characteristics), Dummy);
   if (@PNewLibInfo^.DllProc <> nil) and not
     PNewLibInfo^.DllProc(Cardinal(ImageBase), DLL_PROCESS_ATTACH, nil) then
   begin
     PNewLibInfo^.DllProc := nil;
     XFreeLibrary(Result);
     Result := 0;
   end
   else
     Result := Cardinal(ImageBase);
 except
   VirtualFree(ImageBase, 0, MEM_RELEASE);
 end;
end;

initialization

finalization
 if Assigned(LoadedLibs) then
 begin
   while LoadedLibs.Count > 0 do
     XFreeLibrary(HMODULE(TLibInfo(LoadedLibs.First^).ImageBase));
   FreeAndNil(LoadedLibs);
 end;
end.


 
Leonid Troyanovsky ©   (2011-01-13 21:46) [7]


> Rouse_ ©   (13.01.11 19:22) [5]

Хорошо, что уже три года, как ты с этим делом завязал.

--
Regards, LVT.


 
Rouse_ ©   (2011-01-13 22:24) [8]

С каким? :)


 
Rouse_ ©   (2011-01-13 22:28) [9]

А, ты про 2007 в хидере - так это просто год последней правки исходника :)


 
Leonid Troyanovsky ©   (2011-01-13 22:51) [10]


> Rouse_ ©   (13.01.11 22:28) [9]

> А, ты про 2007 в хидере - так это просто год последней правки
> исходника :)

Что исходнее прижилось это есть только гуд :)
Просто, самоя идея изжилась, и Макс, IMHO, оное принял.

--
Regards, LVT.


 
Германн ©   (2011-01-14 01:50) [11]


> Просто, самоя идея изжилась, и Макс, IMHO, оное принял.

О. Значит и LVT (может быть неявно) участвует в той самой (самой ДМ) фирме.


 
Дмитрий С ©   (2011-01-14 07:26) [12]

Можно вопрос в тему?)
Можно в своем процессе в отдельном потоке запустить другой exe?:)
Например, загрузить модуль и createthread на его точку входа?


 
Leonid Troyanovsky ©   (2011-01-14 08:28) [13]


> Дмитрий С ©   (14.01.11 07:26) [12]

> Например, загрузить модуль и createthread на его точку входа?

Это вряд ли.

См., например,
http://groups.google.com/group/microsoft.public.win32.programmer.kernel/msg/fb58c55a2edd8e88
по-дельфийски
http://groups.google.com/group/fido7.ru.delphi/msg/dbf6083b8b7fbee4

--
Regards, LVT.


 
RWolf ©   (2011-01-14 09:53) [14]


> Приложение юзает функции библиотеки 7z.dll. Проблема, заказчик
> не хочет таскать вместе с исполняемым файлом файл библиотеки.

не надо таскать исполняемый файл, для этого есть дистрибутив.


 
reqyz   (2011-02-22 11:26) [15]

я понимаю, что уже месяц прошёл, и врятли мне ответят, но всё же, блин, какой нафиг поинтер в загрузке библиотеке, и почему он имэйдж, как это юзать вообще?  я вот так попытался, и естественно комп сматерился

rs := TResourceStream.Create(hInstance, "REQ", "STRING");
   hndDLLHandle:=XLoadLibrary(rs);


 
имя   (2011-02-22 11:46) [16]

Удалено модератором



Страницы: 1 вся ветка

Текущий архив: 2011.06.05;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.009 c
15-1298291672
Baks
2011-02-21 15:34
2011.06.05
Дебаггер для разных версий Delphi


1-1255806622
minomorf
2009-10-17 23:10
2011.06.05
Как в TSynEdit сделать подсветку строки (как при ошибке)


2-1298584745
Артём
2011-02-25 00:59
2011.06.05
Деление строки


15-1297848575
DelphiN!
2011-02-16 12:29
2011.06.05
Ошибка в bat файле


2-1298927662
Sashka
2011-03-01 00:14
2011.06.05
Работа с AsyncCall