DelayedLoading (Delphi)

From RAD Studio Code Examples
Jump to: navigation, search

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

See Also