DelayedLoading (Delphi)
Contents
Description
This example demonstrates the fine tuning of the delay loading mechanism. Using the provided functionality, you can hook-up various steps in the delay loading process. This example defines three cases, one of which is correct, and two incorrect.
Note: At the XE2 release, the delayed loading mechanism for Delphi was refactored and moved From the System unit into the SysInit unit. For example, System.dliNotification became SysInit.dliNotification, and System.DliNotifyHook became SysInit.DliNotifyHook2. This code example has not yet been revised to use the new delayed loading.
Code
program TestDelayLoad;
{$APPTYPE CONSOLE}
uses
Winapi.Windows,
System.SysUtils;
function GetDesktopWindow: HWND; stdcall; external user32 name 'GetDesktopWindow' delayed;
function GetFooBar: Integer; stdcall; external kernel32 name 'GetFooBar' delayed;
function GetFooBarBar: Integer; stdcall; external 'kernel33' name 'GetFooBarBar' delayed;
var
LOldNotifyHook, LOldFailureHook: TDelayedLoadHook; { for storing the old hook pointers }
{ Utility function to retrieve the name of the imported routine or its ordinal }
function ImportName(const AProc: TDelayLoadProc): String; inline;
begin
if AProc.fImportByName then
Result := AProc.szProcName
else
Result := '#' + IntToStr(AProc.dwOrdinal);
end;
function MyDelayedLoadHook(dliNotify: dliNotification; pdli: PDelayLoadInfo): Pointer; stdcall;
begin
{ Write a message for each dli notification }
case dliNotify of
dliNoteStartProcessing:
WriteLn('Started the delayed load session for "', pdli.szDll, '" DLL');
dliNotePreLoadLibrary:
WriteLn('Starting to load "', pdli.szDll, '" DLL');
dliNotePreGetProcAddress:
WriteLn('Want to get address of "', ImportName(pdli.dlp), '" in "', pdli.szDll, '" DLL');
dliNoteEndProcessing:
WriteLn('Ended the delaay load session for "', pdli.szDll, '" DLL');
dliFailLoadLibrary:
WriteLn('Failed to load "', pdli.szDll, '" DLL');
dliFailGetProcAddress:
WriteLn('Failed to get proc address for "', ImportName(pdli.dlp), '" in "', pdli.szDll, '" DLL');
end;
{ Call the old hooks if they are not nil }
{ This is recommended to do in case the old hook do further processing }
if dliNotify in [dliFailLoadLibrary, dliFailGetProcAddress] then
begin
if Assigned(LOldFailureHook) then
LOldFailureHook(dliNotify, pdli);
end else
begin
if Assigned(LOldNotifyHook) then
LOldNotifyHook(dliNotify, pdli);
end;
Result := nil;
end;
begin
{ Install new delayed loading hooks }
LOldNotifyHook := SetDliNotifyHook2(MyDelayedLoadHook);
LOldFailureHook := SetDliFailureHook2(MyDelayedLoadHook);
{ Calling an existing delayed external routine }
GetDesktopWindow;
try
{ Calling an unexisting delayed external routine in an existing library }
GetFooBar;
except
end;
try
{ Calling an unexisting delayed external routine in an unexisting library }
GetFooBarBar;
except
end;
{ Reset the hooks }
SetDliNotifyHook2(LOldNotifyHook);
SetDliFailureHook2(LOldFailureHook);
Readln;
end.
Uses
- SysInit.TDelayedLoadHook
- SysInit.dliNotification
- SysInit.DelayLoadInfo
- SysInit.TDelayLoadInfo
- SysInit.PDelayLoadInfo
- SysInit.DelayLoadProc
- SysInit.TDelayLoadProc
- SysInit.PDelayLoadProc