难题(100分求助,在线等待),调用DLL文件流中中的函数

zurong 2007-02-09 12:08:30
现在把一个dll作为RES加入到当前的项目中生成一个.exe文件,原.exe本来要调用dll的函数的,但是现在dll作为资源了,不想把这个资源释放到计算机硬盘上,想直接在文件流中使用,不知道有什么好的方法?
由于是第一次做DELPHI项目,还请达人能够稍微说得详细一点,谢谢!!!!
...全文
258 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
ahjoe 2007-08-05
  • 打赏
  • 举报
回复
// 继续
procedure ProcessRelocs(PRelocs:PImageBaseRelocation);
var
PReloc: PImageBaseRelocation;
RelocsSize: cardinal;
Reloc: PWord;
ModCount: cardinal;
RelocLoop: cardinal;
begin
PReloc := PRelocs;
RelocsSize := ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
while cardinal(PReloc) - cardinal(PRelocs) < RelocsSize do
begin
ModCount := (PReloc.SizeOfBlock-Sizeof(PReloc^)) div 2;
Reloc := pointer(cardinal(PReloc)+sizeof(PReloc^));
for RelocLoop := 0 to ModCount - 1 do
begin
if Reloc^ and $f000 <> 0 then
Inc(pdword(cardinal(ImageBase) + PReloc.VirtualAddress + (Reloc^ and $0fff))^, ImageBaseDelta);
Inc(Reloc);
end;
PReloc := pointer(Reloc);
end;
end;

procedure ProcessImports(PImports: PImageImportDescriptor);
var
PImport: PImageImportDescriptor;
Import: LPDword;
PImportedName: pchar;
LibHandle: HModule;
ProcAddress: pointer;
PLibName: pchar;
ImportLoop: integer;

function IsImportByOrdinal(ImportDescriptor: dword; HLib: THandle): boolean;
begin
Result := (ImportDescriptor and IMAGE_ORDINAL_FLAG32) <> 0;
end;

begin
PImport := PImports;
while PImport.Name<>0 do
begin
PLibName := pchar(cardinal(PImport.Name) + cardinal(ImageBase));
if not Find(NewLibInfo.LibsUsed, PLibName, ImportLoop) then
begin
LibHandle := LoadLibrary(PLibName);
Add(NewLibInfo.LibsUsed, PLibName);
end
else
LibHandle := cardinal(NewLibInfo.LibsUsed[ImportLoop]);
if PImport.TimeDateStamp = 0 then
Import := LPDword(pImport.FirstThunk+cardinal(ImageBase))
else
Import := LPDword(pImport.OriginalFirstThunk + cardinal(ImageBase));
while Import^ <> 0 do
begin
if IsImportByOrdinal(Import^, LibHandle) then
ProcAddress := GetProcAddress(LibHandle, pchar(Import^ and $ffff))
else
begin
PImportedName := pchar(Import^ + cardinal(ImageBase) + IMPORTED_NAME_OFFSET);
ProcAddress := GetProcAddress(LibHandle, PImportedName);
end;
PPointer(Import)^ := ProcAddress;
Inc(Import);
end;
Inc(PImport);
end;
end;

begin
ImageNtHeaders := pointer(int64(cardinal(Src)) + PImageDosHeader(Src)._lfanew);
ImageBase := VirtualAlloc(nil, ImageNtHeaders.OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_NOACCESS);
ImageBaseDelta := cardinal(ImageBase) - ImageNtHeaders.OptionalHeader.ImageBase;
SectionBase := VirtualAlloc(ImageBase, ImageNtHeaders.OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE);
Move(Src^, SectionBase^, ImageNtHeaders.OptionalHeader.SizeOfHeaders);
VirtualProtect(SectionBase, ImageNtHeaders.OptionalHeader.SizeOfHeaders, PAGE_READONLY, OldProtect);
PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) + ImageNtHeaders.FileHeader.SizeOfOptionalHeader);
for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
begin
VirtualSectionSize := PSections[SectionLoop].Misc.VirtualSize;
RawSectionSize := PSections[SectionLoop].SizeOfRawData;
if VirtualSectionSize < RawSectionSize then
begin
VirtualSectionSize := VirtualSectionSize xor RawSectionSize;
RawSectionSize := VirtualSectionSize xor RawSectionSize;
VirtualSectionSize := VirtualSectionSize xor RawSectionSize;
end;
SectionBase := VirtualAlloc(PSections[SectionLoop].VirtualAddress + pchar(ImageBase), VirtualSectionSize, MEM_COMMIT, PAGE_READWRITE);
FillChar(SectionBase^, VirtualSectionSize, 0);
Move((pchar(src) + PSections[SectionLoop].PointerToRawData)^, SectionBase^, RawSectionSize);
end;
NewLibInfo.DllProc := TDllEntryProc(ImageNtHeaders.OptionalHeader.AddressOfEntryPoint + cardinal(ImageBase));
NewLibInfo.ImageBase := ImageBase;
SetLength(NewLibInfo.LibsUsed, 0);
if ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress <> 0 then
ProcessRelocs(pointer(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + cardinal(ImageBase)));
if ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress <> 0 then
ProcessImports(pointer(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + cardinal(ImageBase)));
for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
VirtualProtect(PSections[SectionLoop].VirtualAddress + pchar(ImageBase), PSections[SectionLoop].Misc.VirtualSize, GetSectionProtection(PSections[SectionLoop].Characteristics), OldProtect);
if @NewLibInfo.DllProc <> nil then
begin
if not NewLibInfo.DllProc(cardinal(ImageBase), DLL_PROCESS_ATTACH, nil) then
begin
NewLibInfo.DllProc := nil;
xFreeLibrary(Result);
end;
end;
if ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress <> 0 then
ProcessExports(pointer(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + cardinal(ImageBase)), ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size);
Result := NewLibInfo;
end;

end.

ahjoe 2007-08-05
  • 打赏
  • 举报
回复
// 内存加载DLL代码,有的EXE使用以下代码会出错

{
DLL Loader by Aphex
http://www.iamaphex.cjb.net
unremote@knology.net

Based on code from gmm@ufacom.ru

function xLoadLibrary(Src: Pointer; Imports: array of TImportItem): TLibInfo;
procedure xFreeLibrary(hModule: TLibInfo);
}

unit DllLoader;

interface

uses
Windows;

type
TImportItem = record
Name: string;
PProcVar: ^Pointer;
end;

TwordArr = array [0..0] of word;
PwordArr = ^TwordArr;
TdwordArr = array [0..0] of dword;
PdwordArr = ^TdwordArr;

PImageImportDescriptor = ^TImageImportDescriptor;
TImageImportDescriptor = packed record
OriginalFirstThunk: dword;
TimeDateStamp: dword;
ForwarderChain: dword;
Name: dword;
FirstThunk: dword;
end;

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

TDllEntryProc = function(hinstDLL: HMODULE; dwReason: dword;
lpvReserved: Pointer): Boolean; stdcall;

TStringArray = array of string;

TLibInfo = record
ImageBase: Pointer;
DllProc: TDllEntryProc;
LibsUsed: TStringArray;
end;

PLibInfo = ^TLibInfo;
PPointer = ^Pointer;

TSections = array [0..100000] of TImageSectionHeader;

const
IMPORTED_NAME_OFFSET = $00000002;
IMAGE_ORDINAL_FLAG32 = $80000000;
IMAGE_ORDINAL_MASK32 = $0000FFFF;

type
TImportItemArr = array of TImportItem;

function xLoadLibrary(Src: Pointer; Imports: TImportItemArr): TLibInfo;
function xFreeLibrary(LoadedLib: TLibInfo): boolean;

implementation

function xFreeLibrary(LoadedLib: TLibInfo): boolean;
var
ObjectLoop: integer;
begin
Result := False;
with LoadedLib do
begin
if @DllProc <> nil then
begin
DllProc(HModule(LoadedLib.ImageBase), DLL_PROCESS_DETACH, nil);
end;
for ObjectLoop := 0 to Length(LibsUsed) - 1 do
begin
if ObjectLoop >= Length(LibsUsed) then Exit;
FreeLibrary(GetModuleHandle(pchar(LibsUsed[ObjectLoop])));
end;
SetLength(LibsUsed, 0);
end;
VirtualFree(LoadedLib.ImageBase, 0, MEM_RELEASE);
Result := True;
end;

function xLoadLibrary(Src: Pointer; Imports: TImportItemArr): TLibInfo;
var
ImageBase: pointer;
ImageBaseDelta: integer;
ImageNtHeaders: PImageNtHeaders;
PSections: ^TSections;
SectionLoop: integer;
SectionBase: pointer;
VirtualSectionSize, RawSectionSize: cardinal;
OldProtect: cardinal;
NewLibInfo: TLibInfo;

function StrToInt(S: string): integer;
begin
Val(S, Result, Result);
end;

procedure Add(Strings: TStringArray; Text: string);
begin
SetLength(Strings, Length(Strings) + 1);
Strings[Length(Strings)-1] := Text;
end;

function Find(Strings: array of string; Text: string; var Index: integer): boolean;
var
StringLoop: integer;
begin
Result := False;
for StringLoop := 0 to Length(Strings) - 1 do
begin
if lstrcmpi(pchar(Strings[StringLoop]), pchar(Text)) = 0 then
begin
Index := StringLoop;
Result := True;
end;
end;
end;

function GetSectionProtection(ImageScn: cardinal): cardinal;
begin
Result := 0;
if (ImageScn and IMAGE_SCN_MEM_NOT_CACHED) <> 0 then
begin
Result := Result or PAGE_NOCACHE;
end;
if (ImageScn and IMAGE_SCN_MEM_EXECUTE) <> 0 then
begin
if (ImageScn and IMAGE_SCN_MEM_READ)<> 0 then
begin
if (ImageScn and IMAGE_SCN_MEM_WRITE)<> 0 then
Result := Result or PAGE_EXECUTE_READWRITE
else
Result := Result or PAGE_EXECUTE_READ
end
else
if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
Result := Result or PAGE_EXECUTE_WRITECOPY
else
Result := Result or PAGE_EXECUTE
end
else
if (ImageScn and IMAGE_SCN_MEM_READ)<> 0 then
begin
if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
Result := Result or PAGE_READWRITE
else
Result := Result or PAGE_READONLY
end
else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
Result := Result or PAGE_WRITECOPY
else
Result := Result or PAGE_NOACCESS;
end;

procedure ProcessExports(PExports: PImageExportDirectory; BlockSize: cardinal);
var
ExportLoop: byte;
ImportedFn: cardinal;
PFnName: pchar;
FnIndex: dword;

function IsForwarderString(Data: pchar): boolean;
begin
Result := Data > PExports;
if Result then
Result := cardinal(Data - PExports) < BlockSize;
end;

function GetForwardedSymbol(ForwarderString: pchar):pointer;
var
sForwarderString, DllName: string;
ForwarderLoop: integer;
LibHandle: HModule;
begin
sForwarderString := ForwarderString;
while ForwarderString^ <> '.' do
begin
Inc(ForwarderString);
end;
DllName := Copy(sForwarderString, 1, pos('.', sForwarderString) - 1);
if not Find(NewLibInfo.LibsUsed, DllName, ForwarderLoop) then
begin
LibHandle := LoadLibrary(pchar(DllName));
Add(NewLibInfo.LibsUsed, DllName);
end
else
LibHandle := cardinal(NewLibInfo.LibsUsed[ForwarderLoop]);
if ForwarderString^ = '#' then
ForwarderString := pointer(StrToInt((ForwarderString + 1)));
Result := GetProcAddress(LibHandle, ForwarderString);
end;

begin
for ExportLoop := 0 to PExports.NumberOfNames - 1 do
begin
PFnName := pchar(PdwordArr(cardinal(PExports.AddressOfNames) + cardinal(ImageBase))^[ExportLoop] + cardinal(ImageBase));
for ImportedFn := low(Imports) to high(Imports) do
begin
if Imports[ImportedFn].Name = PFnName then
begin
FnIndex := PwordArr(cardinal(PExports.AddressOfNameOrdinals) + cardinal(ImageBase))^[ExportLoop];
Imports[ImportedFn].PProcVar^ := pointer(PdwordArr(cardinal(PExports.AddressOfFunctions) + cardinal(ImageBase))^[FnIndex] + cardinal(ImageBase));
if IsForwarderString(Imports[ImportedFn].PProcVar^)then
Imports[ImportedFn].PProcVar^ := GetForwardedSymbol(Imports[ImportedFn].PProcVar^);
end;
end;
end;
end;
zurong 2007-02-09
  • 打赏
  • 举报
回复
就是调用的入口点应该设在哪里???
wlp555ren 2007-02-09
  • 打赏
  • 举报
回复
不是有个DLLPROC可以来设置DLL的入口函数吗??
C#如何在后台捕捉按键 [此问题的推荐答案] API别忘了 using System.Runtime.InteropServices; [DllImport("user32.dll")] public static extern UInt32 RegisterHotKey(IntPtr hWnd, UInt32 id, UInt32 fsModifiers, UInt32 vk); //API public Form1() { InitializeComponent(); RegisterHotKey(this.Handle, 247696411, 0, (UInt32)Keys.F10); //注册热键 } //重写消息循环 protected override void WndProc(ref Message m) { const int WM_HOTKEY = 0x0312; // m.WParam.ToInt32() 要和 注册热键时的第2个参数一样 if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 247696411) //判断热键 { //写上你的代码 } base.WndProc(ref m); } 写上代码后 只要 在程序运行时按F10就可以触发热键更改按键可以在 注册时改 RegisterHotKey(this.Handle, 247696411, 0, (UInt32)Keys.***); http://baike.baidu.com/view/1080084.html?tp=0_10 这里有RegisterHotKey 的介绍 RegisterHotKey 函数功能:该函数定义一个系统范围的热键。 函数原型:BOOL RegisterHotKey(HWND hWnd,intid,UINT fsModifiers,UINT vk); 参数: hWnd:接收热键产生WM_HOTKEY消息的窗口句柄。若该参数NULL,传递给调用线程的WM_HOTKEY消息必须在消息循环进行处理。 id:定义热键的标识符。调用线程的其他热键不能使用同样的标识符。应用功能程序必须定义一个0X0000-0xBFFF范围的值。一个共享的动态链接库(DLL)必须定义一个0xC000-0xFFFF范围的值伯GlobalAddAtom函数返回该范围)。为了避免与其他动态链接库定义的热键冲突,一个DLL必须使用GlobalAddAtom函数获得热键的标识符。 fsModifoers:定义为了产生WM_HOTKEY消息而必须与由nVirtKey参数定义的键一起按下的键。该参数可以是如下值的组合: MOD_ALT:按下的可以是任一Alt键。MOD_CONTROL:按下的可以是任一Ctrl键。 MOD_SHIFT:按下的可以是任一Shift键。 MOD_WIN:按下的可以是任一Windows按键。这些键可以用Microsoft Windows日志记录下来。 vk:定义热键的虚拟键码。 返回值:若函数调用成功,返回一个非O值。若函数调用失败,则返回值为0。若要获得更多的错误信息,可以调用GetLastError函数。 本贴来自ZDNetChina文社区 http://bbs.zdnet.com.cn ,本贴地址:http://bbs.zdnet.com.cn/viewthread.php?tid=93775 RegisterHotKey   函数功能:该函数定义一个系统范围的热键。   函数原型:BOOL RegisterHotKey(HWND hWnd,intid,UINT fsModifiers,UINT vk);   参数:   hWnd:接收热键产生WM_HOTKEY消息的窗口句柄。若该参数NULL,传递给调用线程的WM_HOTKEY消息必须在消息循环进行处理。   id:定义热键的标识符。调用线程的其他热键不能使用同样的标识符。应用功能程序必须定义一个0X0000-0xBFFF范围的值。一个共享的动态链接库(DLL)必须定义一个0xC000-0xFFFF范围的值伯GlobalAddAtom函数返回该范围)。为了避免与其他动态链接库定义的热键冲突,一个DLL必须使用GlobalAddAtom函数获得热键的标识符。   fsModifoers:定义为了产生WM_HOTKEY消息而必须与由nVirtKey参数定义的键一起按下的键。该参数可以是如下值的组合:   MOD_ALT:按下的可以是任一Alt键。MOD_CONTROL:按下的可以是任一Ctrl键。   MOD_SHIFT:按下的可以是任一Shift键。   MOD_WIN:按下的可以是任一Windows按键。这些键可以用Microsoft Windows日志记录下来。   vk:定义热键的虚拟键码。   返回值:若函数调用成功,返回一个非O值。若函数调用失败,则返回值为0。若要获得更多的错误信息,可以调用GetLastError函数。   备注:当某键被接下时,系统在所有的热键寻找匹配者。一旦找到一个匹配的热键,系统将把WM_HOTKEY消息传递给登记了该热键的线程的消息队列。该消息被传送到队列头部,因此它将在下一轮消息循环被移去。该函数不能将热键同其他线程创建的窗口关联起来。   若为一热键定义的击键己被其他热键所定义,则RegisterHotKey函数调用失败。   若hWnd参数标识的窗口已用与id参数定义的相同的标识符登记了一个热键,则参数fsModifiers和vk的新值将替代这些参数先前定义的值。   Windows CE:Windows CE 2.0以上版本对于参数fsModifiers支持一个附加的标志位。叫做MOD_KEYUP。   若设置MOD_KEYUP位,则当发生键被按下或被弹起的事件时,窗口将发送WM_HOTKEY消息。   RegisterHotKey可以被用来在线程之间登记热键。   速查:Windows NT:3.1及以上版本;Windows:95及以上版本;Windows CE:不支持;头文件:winuser.h;库文件:user32.lib

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧