Obsługa błędów oraz powiadomienia

Jeśli program używa bibliotek DLL ładowanych z opóźnieniem, musi obsługiwać błędy niezawodnie, ponieważ błędy występujące podczas działania programu spowodują nieobsługiwane wyjątki. Obsługa błędów składa się z dwóch części: odzyskiwanie za pośrednictwem haka i raportowanie za pośrednictwem wyjątku.

Aby uzyskać więcej informacji na temat obsługi błędów i powiadomień o opóźnieniu ładowania bibliotek DLL, zobacz Omówienie funkcji pomocnika.

Aby uzyskać więcej informacji na temat funkcji haka, zobacz Struktura i stałe definicje.

Odzyskiwanie za pomocą haka

Może być konieczne odzyskanie kodu po awarii lub udostępnienie alternatywnej biblioteki lub procedury. Możesz podać hak do funkcji pomocnika, która może dostarczyć alternatywny kod lub rozwiązać problem. Procedury haka muszą zwrócić odpowiednią wartość, aby przetwarzanie może kontynuować (an HINSTANCE lub FARPROC). Może też zwrócić wartość 0, aby wskazać, że powinien zostać zgłoszony wyjątek. Może również zgłosić własny wyjątek lub longjmp z haka. Istnieją zaczepienia powiadomień i zaczepienia błędów. Ta sama rutyna może być używana w obu tych przypadkach.

Punkty zaczepienia powiadomień

Przypinanie powiadomień o opóźnieniu obciążenia jest wywoływane tuż przed wykonaniem następujących akcji w procedurze pomocniczej:

  • Zapisana dojście do biblioteki jest sprawdzana, aby sprawdzić, czy została już załadowana.

  • LoadLibrary jest wywoływana w celu podjęcia próby załadowania biblioteki DLL.

  • GetProcAddress jest wywoływana, aby spróbować uzyskać adres procedury.

  • Wróć do opóźnionego ładowania importu thunk.

Element zaczepienia powiadomień jest włączony:

  • Po podać nową definicję wskaźnika __pfnDliNotifyHook2 , który jest inicjowany, aby wskazać własną funkcję, która odbiera powiadomienia.

    — lub —

  • Ustawiając wskaźnik __pfnDliNotifyHook2 na funkcję haka przed wywołaniami biblioteki DLL, którą program opóźnia ładowanie.

Jeśli powiadomienie to dliStartProcessing, funkcja hook może zwrócić:

  • NULL

    Domyślny pomocnik obsługuje ładowanie biblioteki DLL. Warto wywołać je tylko w celach informacyjnych.

  • wskaźnik funkcji

    Pomiń domyślną obsługę opóźniania obciążenia. Umożliwia ona dostarczanie własnej procedury obsługi obciążenia.

Jeśli powiadomienie to dliNotePreLoadLibrary, funkcja hook może zwrócić:

  • 0, jeśli chce tylko powiadomienia informacyjne.

  • Element HMODULE dla załadowanego biblioteki DLL, jeśli załadował samą bibliotekę DLL.

Jeśli powiadomienie to dliNotePreGetProcAddress, funkcja hook może zwrócić:

  • 0, jeśli chce tylko powiadomienia informacyjne.

  • Adres zaimportowanych funkcji, jeśli funkcja hook pobiera sam adres.

Jeśli powiadomienie to dliNoteEndProcessing, zwracana wartość funkcji hook jest ignorowana.

Jeśli ten wskaźnik jest inicjowany (niezerowy), pomocnik ładowania opóźnienia wywołuje funkcję w określonych punktach powiadomień w trakcie wykonywania. Wskaźnik funkcji ma następującą definicję:

// 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;

Powiadomienia są przekazywane w DelayLoadInfo strukturze do funkcji hook wraz z wartością powiadomienia. Te dane są identyczne z danymi używanymi przez procedurę pomocnika opóźniania ładowania. Wartość powiadomienia będzie jedną z wartości zdefiniowanych w definicji struktury i stałych.

Punkty zaczepienia błędów

Punkt zaczepienia awarii jest włączony w taki sam sposób, jak w przypadku zaczepienia powiadomień. Procedury haka muszą zwrócić odpowiednią wartość, aby przetwarzanie może kontynuować (lub HINSTANCEFARPROC), lub 0, aby wskazać, że wyjątek powinien zostać zgłoszony.

Zmienna wskaźnika, która odwołuje się do funkcji zdefiniowanej przez użytkownika, to:

// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook   __pfnDliFailureHook2;

Struktura DelayLoadInfo zawiera wszystkie istotne dane niezbędne do szczegółowego raportowania błędu, w tym wartość z GetLastError.

Jeśli powiadomienie to dliFailLoadLib, funkcja hook może zwrócić:

  • 0, jeśli nie może obsłużyć błędu.

  • Element HMODULE, jeśli hak awarii rozwiązał problem i załadował samą bibliotekę.

Jeśli powiadomienie to dliFailGetProc, funkcja hook może zwrócić:

  • 0, jeśli nie może obsłużyć błędu.

  • Prawidłowy adres proc (adres funkcji importu), jeśli punkt zaczepienia błędu zakończył się powodzeniem w uzyskaniu samego adresu.

Zgłaszanie przy użyciu wyjątku

Jeśli wszystko, co jest wymagane do obsługi błędu, to przerwanie procedury, nie jest konieczne hak, o ile kod użytkownika może obsłużyć wyjątek.

Opóźnianie kodów wyjątków ładowania

Kody wyjątków strukturalnych można zgłaszać, gdy wystąpią błędy podczas opóźnionego ładowania. Wartości wyjątku są określane przy użyciu makra VcppException :

//
// Exception information
//
#define FACILITY_VISUALCPP  ((LONG)0x6d)
#define VcppException(sev,err)  ((sev) | (FACILITY_VISUALCPP<<16) | err)

LoadLibrary W przypadku awarii jest zgłaszany standardVcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND). GetProcAddress W przypadku niepowodzenia zgłaszany błąd to VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND). Wyjątek przekazuje wskaźnik do DelayLoadInfo struktury. LPDWORD Jest to wartość pobierana przez GetExceptionInformationEXCEPTION_RECORD strukturę w ExceptionInformation[0] polu .

Jeśli w polu ustawiono grAttrs niepoprawne bity, zgłaszany jest wyjątek ERROR_INVALID_PARAMETER . Ten wyjątek dotyczy wszystkich intencji i celów krytycznych.

Aby uzyskać więcej informacji, zobacz Struktura i stałe definicje.

Zobacz też

Obsługa konsolidatora dla bibliotek DLL ładowanych z opóźnieniem