Ross wrote: > I didn't know that was possible. I'll investigate.
PE Explorer is probably one of the best tools for this. It's also written in Delphi I believe. You can download a fully functional 30-day trial version. http://www.heaventools.com/download-pe-explorer.htm Alternatively, if you want to point me at the DLL, I can have a look at it's import table for you. Import Address Table (or IAT) patching is a pretty standard albeit 'low-level' technique. If you look for sample code around the web, it's often more involved that it needs to be since it's often written in the context of injecting DLLs into other processes you don't control to patch their main import table. Since you'll be patching the import table of a DLL you've loaded into your own process, it's much simpler. Here's the routine I use. It's using HInstance rather than the module handle for a loaded DLL since I used for patching the main executable's import table. You'll want to pass the module handle of your DLL by calling GetModuleHandle. It returns the current IAT entry so you can easily forward chain. There's a whole bunch of stanard PE table record type definitions this code depends on which I've left out. function InstallWin32Hook(const ModuleName, FuncName: string; HookFunc: Pointer): Pointer; var NTHeader: PImageNTHeaders; ImportDesc: PImageImportDescriptor; Thunk: PImageThunkData; begin Result := GetProcAddress(GetModuleHandle(PChar(ModuleName)), PChar(FuncName)); if Result <> nil then begin NTHeader := PImageNTHeaders(DWord(HInstance) + PImageDosHeader(HInstance).e_lfanew); ImportDesc := PImageImportDescriptor(DWord(HInstance) + NTHeader.OptionalHeader.DataDirectory[ImageDirectoryEntryImport].Virtual Address); while ImportDesc.Name <> 0 do begin if StriComp(PAnsiChar(DWord(HInstance) + ImportDesc.Name), PAnsiChar(AnsiString(ModuleName))) = 0 then begin Thunk := PImageThunkData(DWord(HInstance) + DWord(ImportDesc.FirstThunk)); while Thunk.Funct <> nil do begin if Thunk.Funct = Result then Thunk.Funct := HookFunc; Inc(Thunk) end end; Inc(ImportDesc) end end end; And here's how its used with a sample shim: var OldRaiseException: procedure (dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWord; const lpArguments: DWord); stdcall; OldRaiseException := InstallWin32Hook(Kernel32, 'RaiseException', @HookRaiseException); procedure HookRaiseException(dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWord; const lpArguments: DWord); stdcall; begin { If this is a real Delphi exception and has the arguments as we expect from System._RaiseExcept then we can crack the argument structure and determine if we need to take a stack trace. Note that this may change from version to version of Delphi. } if (dwExceptionCode = cDelphiException) and (lpArguments <> 0) and (nNumberOfArguments = 7) and not InHookRaise then with PDelphiExceptionArguments(lpArguments)^ do try InHookRaise := True; if not IgnoreException(ExceptObject) then HookStackTrace(ExceptAddress, EBP, ESP, False); finally InHookRaise := False; end; if Assigned(OldRaiseException) then OldRaiseException(dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments); end; Cheers, Paul. _______________________________________________ NZ Borland Developers Group - Delphi mailing list Post: delphi@delphi.org.nz Admin: http://delphi.org.nz/mailman/listinfo/delphi Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: unsubscribe