Соглашения о вызове, параметры и тип возвращаемого значения
Прототип вспомогательной подпрограммы:
FARPROC WINAPI __delayLoadHelper2(
PCImgDelayDescr pidd,
FARPROC * ppfnIATEntry
);
Здесь:
pidd
Указатель const на структуру ImgDelayDescr (см. файл delayimp.h), содержащую смещения различных данных, связанных с импортом, отметку времени для информации о привязке и набор атрибутов, предоставляющих дополнительную информацию о содержимом дескриптора. В настоящее время имеется только один атрибут, dlattrRva, который указывает на то, что адреса в дескрипторе являются относительными виртуальными адресами (в противоположность виртуальным адресам).Определение структуры PCImgDelayDescr см. в статье Определение структуры и константы.
ppfnIATEntry
Указатель на ячейку в таблице адресов импорта (IAT), загружаемого с задержкой, которую необходимо обновить, занеся в нее адрес импортированной функции. Вспомогательная подпрограмма должна сохранить то же самое значение, которое будет возвращено в это место.
Ожидаемые возвращаемые значения
Если функция выполнена успешно, она возвращает адрес импортированной функции.
Если функция завершается с ошибкой, она создает исключение и возвращает 0. Возможны три типа исключений.
Недопустимый параметр. Это исключение создается, если атрибуты в pidd указаны некорректно.
Функции LoadLibrary не удалось загрузить указанную библиотеку DLL.
Ошибка в функции GetProcAddress.
За обработку этих исключений отвечает разработчик.
Примечания
Для вспомогательной функции используется соглашение о вызове __stdcall. Тип возвращаемого значения неважен, поэтому используется тип FARPROC. Для этой функции используется компоновка C.
Возвращаемое значение вспомогательной подпрограммы загрузки с задержкой должно быть сохранено в переданном указателе на функцию, если только подпрограмма не должна использоваться в качестве обработчика уведомлений. В этом случае за поиск необходимого возвращаемого указателя на функцию отвечает пользовательский код. Затем код преобразователя, создаваемый компоновщиком, принимает это возвращаемое значение в качестве действительной цели импорта и переходит непосредственно к ней.
Пример
В приведенном ниже примере показано, как реализовать простейшую функцию-обработчик.
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;
*/