调用约定、参数和返回类型
Helper 例程的原型是:
FARPROC WINAPI __delayLoadHelper2(
PCImgDelayDescr pidd,
FARPROC * ppfnIATEntry
);
其中:
pidd
指向 ImgDelayDescr(请参见 delayimp.h)的 const 指针,其中包含与导入相关的各种数据的偏移量、绑定信息的时间戳和提供有关描述符内容的更多信息的特性集。 当前只有一个特性,即 dlattrRva,它指示描述符中的地址是相对虚拟地址(相对于虚拟地址)。有关 PCImgDelayDescr 结构的定义,请参见结构和常数定义。
ppfnIATEntry
指向延迟加载导入地址表 (IAT) 中的槽的指针,该地址表将用导入函数的地址更新。 Helper 例程需要存储它将要返回到该位置的同一值。
需要的返回值
如果函数运行成功,则返回导入函数的地址。
如果函数运行失败,将引发异常,并且返回 0。 引发的异常有三种类型:
无效参数,发生在 pidd 中的特性未正确指定时。
LoadLibrary 在指定的 DLL 上失败。
GetProcAddress 失败。
由您负责处理这些异常。
备注
Helper 函数的调用约定是 __stdcall。 返回值的类型不相关,所以使用 FARPROC。 该函数具有 C 链接。
除非要将 Helper 例程用作通知挂钩,否则延迟加载 Helper 的返回值需要存储在已传入函数指针的位置。 在这种情况下,由您的代码负责查找要返回的适当函数指针。 链接器生成的 thunk 代码然后将该返回值用作导入的实目标并直接跳转到该目标。
示例
下面的代码显示如何实现一个简单的挂钩函数。
FARPROC WINAPI delayHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
switch (dliNotify) {
case dliStartProcessing :
// If you want to return control to the helper, return 0.
// Otherwise, return a pointer to a FARPROC helper function
// that will be used instead, thereby bypassing the rest
// of the helper.
break;
case dliNotePreLoadLibrary :
// If you want to return control to the helper, return 0.
// Otherwise, return your own HMODULE to be used by the
// helper instead of having it call LoadLibrary itself.
break;
case dliNotePreGetProcAddress :
// If you want to return control to the helper, return 0.
// If you choose you may supply your own FARPROC function
// address and bypass the helper's call to GetProcAddress.
break;
case dliFailLoadLib :
// LoadLibrary failed.
// If you don't want to handle this failure yourself, return 0.
// In this case the helper will raise an exception
// (ERROR_MOD_NOT_FOUND) and exit.
// If you want to handle the failure by loading an alternate
// DLL (for example), then return the HMODULE for
// the alternate DLL. The helper will continue execution with
// this alternate DLL and attempt to find the
// requested entrypoint via GetProcAddress.
break;
case dliFailGetProc :
// GetProcAddress failed.
// If you don't want to handle this failure yourself, return 0.
// In this case the helper will raise an exception
// (ERROR_PROC_NOT_FOUND) and exit.
// If you choose you may handle the failure by returning
// an alternate FARPROC function address.
break;
case dliNoteEndProcessing :
// This notification is called after all processing is done.
// There is no opportunity for modifying the helper's behavior
// at this point except by longjmp()/throw()/RaiseException.
// No return value is processed.
break;
default :
return NULL;
}
return NULL;
}
/*
and then at global scope somewhere
PfnDliHook __pfnDliNotifyHook2 = delayHook;
*/