Fehlerbehandlung und Benachrichtigung
Wenn Ihr Programm verzögert geladene DLLs verwendet, muss es Fehler robust behandeln, da Fehler, die auftreten, während das Programm ausgeführt wird, zu unbehandelten Ausnahmen führen. Die Fehlerbehandlung besteht aus zwei Teilen: Wiederherstellung über einen Hook und Berichterstellung über eine Ausnahme.
Weitere Informationen zur DLL-Verzögerung beim Laden von Fehlern und Benachrichtigungen finden Sie unter Grundlegendes zur Hilfsfunktion.
Weitere Informationen zu Hook-Funktionen finden Sie unter Struktur- und Konstantendefinitionen.
Wiederherstellung über einen Hook
Möglicherweise muss Ihr Code bei einem Fehler wiederhergestellt werden oder eine alternative Bibliothek oder Routine bereitstellen. Sie können einen Hook für die Hilfsfunktion bereitstellen, die den alternativen Code bereitstellen oder die Situation beheben kann. Die Hook-Routine muss einen geeigneten Wert zurückgeben, damit die Verarbeitung fortgesetzt werden kann (ein HINSTANCE
oder FARPROC
). Alternativ kann 0 zurückgegeben werden, um anzugeben, dass eine Ausnahme ausgelöst werden soll. Es könnte auch eine eigene Ausnahme oder longjmp
aus dem Haken werfen. Es gibt Benachrichtigungs-Hooks und Fehler-Hooks. Die gleiche Routine kann für beide verwendet werden.
Benachrichtigungshooks
Die Benachrichtigungshaken zum Verzögern des Ladevorgangs werden aufgerufen, bevor die folgenden Aktionen in der Hilfsroutine ausgeführt werden:
Das gespeicherte Handle für die Bibliothek wird überprüft, um festzustellen, ob es bereits geladen wurde.
LoadLibrary
wird aufgerufen, um das Laden der DLL zu versuchen.GetProcAddress
wird aufgerufen, um zu versuchen, die Adresse der Prozedur abzurufen.Kehren Sie zur Verzögerung import load thunk zurück.
Der Benachrichtigungshaken ist aktiviert:
Durch Bereitstellen einer neuen Definition des Zeigers
__pfnDliNotifyHook2
, der initialisiert wird, um auf Ihre eigene Funktion zu verweisen, die die Benachrichtigungen empfängt.Oder
Indem Sie den Zeiger
__pfnDliNotifyHook2
auf Ihre Hook-Funktion festlegen, bevor Aufrufe der DLL ausgeführt werden, die das Programm das Laden verzögert.
Wenn die Benachrichtigung lautet dliStartProcessing
, kann die Hook-Funktion Folgendes zurückgeben:
NULL
Der Standardhilfsprogramm behandelt das Laden der DLL. Es ist nützlich, nur zu Informationszwecken aufzurufen.
Ein Funktionszeiger
Umgehen Sie die standardmäßige Verzögerungsladebehandlung. Damit können Sie Ihren eigenen Ladehandler bereitstellen.
Wenn die Benachrichtigung lautet dliNotePreLoadLibrary
, kann die Hook-Funktion Folgendes zurückgeben:
0, wenn nur Informationsbenachrichtigungen angezeigt werden sollen.
Die
HMODULE
für die geladene DLL, wenn sie die DLL selbst geladen hat.
Wenn die Benachrichtigung lautet dliNotePreGetProcAddress
, kann die Hook-Funktion Folgendes zurückgeben:
0, wenn nur Informationsbenachrichtigungen angezeigt werden sollen.
Die Adresse der importierten Funktion, wenn die Hook-Funktion die Adresse selbst abruft.
Wenn die Benachrichtigung lautet dliNoteEndProcessing
, wird der Rückgabewert der Hook-Funktion ignoriert.
Wenn dieser Zeiger initialisiert ist (nonzero), ruft das Verzögerungsladehilfsprogramm die Funktion während der gesamten Ausführung an bestimmten Benachrichtigungspunkten auf. Der Funktionszeiger weist die folgende Definition auf:
// The "notify hook" gets called for every call to the
// delay load helper. This allows a user to hook every call and
// skip the delay load helper entirely.
//
// dliNotify == {
// dliStartProcessing |
// dliNotePreLoadLibrary |
// dliNotePreGetProc |
// dliNoteEndProcessing}
// on this call.
//
ExternC
PfnDliHook __pfnDliNotifyHook2;
// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook __pfnDliFailureHook2;
Die Benachrichtigungen übergeben eine DelayLoadInfo
Struktur an die Hook-Funktion zusammen mit dem Benachrichtigungswert. Diese Daten sind identisch mit den Daten, die von der Verzögerungsladehilfsroutine verwendet werden. Der Benachrichtigungswert ist einer der werte, die in Struktur- und Konstantendefinitionen definiert sind.
Fehlerhooks
Der Fehlerhaken ist auf die gleiche Weise wie der Benachrichtigungshaken aktiviert. Die Hook-Routine muss einen geeigneten Wert zurückgeben, damit die Verarbeitung fortgesetzt werden kann (ein HINSTANCE
oder FARPROC
), oder 0, um anzugeben, dass eine Ausnahme ausgelöst werden soll.
Die Zeigervariable, die auf die benutzerdefinierte Funktion verweist, lautet:
// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook __pfnDliFailureHook2;
Die DelayLoadInfo
Struktur enthält alle relevanten Daten, die für eine detaillierte Berichterstellung des Fehlers erforderlich sind, einschließlich des Werts von GetLastError
.
Wenn die Benachrichtigung lautet dliFailLoadLib
, kann die Hook-Funktion Folgendes zurückgeben:
0, wenn der Fehler nicht behandelt werden kann.
Ein
HMODULE
, wenn der Fehler-Hook das Problem behoben und die Bibliothek selbst geladen hat.
Wenn die Benachrichtigung lautet dliFailGetProc
, kann die Hook-Funktion Folgendes zurückgeben:
0, wenn der Fehler nicht behandelt werden kann.
Eine gültige Proc-Adresse (Importfunktionsadresse), wenn der Fehlerhaken erfolgreich war, die Adresse selbst zu erhalten.
Melden mithilfe einer Ausnahme
Wenn alles, was zum Behandeln des Fehlers erforderlich ist, die Prozedur abzubrechen, ist kein Hook erforderlich, solange der Benutzercode die Ausnahme behandeln kann.
Verzögertes Laden von Ausnahmecodes
Strukturierte Ausnahmecodes können ausgelöst werden, wenn Fehler während einer verzögerten Auslastung auftreten. Die Ausnahmewerte werden mithilfe eines VcppException
Makros angegeben:
//
// Exception information
//
#define FACILITY_VISUALCPP ((LONG)0x6d)
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
Bei einem LoadLibrary
Fehler wird der Standard VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)
ausgelöst. Bei einem GetProcAddress
Fehler wird VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)
der ausgelöste Fehler zurückgegeben. Die Ausnahme übergibt einen Zeiger an eine DelayLoadInfo
Struktur. Er befindet sich im LPDWORD
Wert, der aus der EXCEPTION_RECORD
Struktur abgerufen GetExceptionInformation
wird, im ExceptionInformation[0]
Feld.
Wenn die falschen Bits im grAttrs
Feld festgelegt sind, wird die Ausnahme ERROR_INVALID_PARAMETER
ausgelöst. Diese Ausnahme ist für alle Absichten und Zwecke tödlich.
Weitere Informationen finden Sie unter Struktur- und Konstantendefinitionen.