錯誤處理和通知
如果您的程式使用延遲載入 DLL,它必須健全地處理錯誤,因為程式執行時發生的失敗會導致未處理的例外狀況。 失敗處理是由兩個部分所組成:透過勾點復原,並透過例外狀況報告。
如需 DLL 延遲載入錯誤處理和通知的詳細資訊,請參閱 瞭解協助程式函式。
如需攔截函式的詳細資訊,請參閱 結構和常數定義。
透過勾點復原
您的程式代碼可能需要在失敗時復原,或提供替代的連結庫或例程。 您可以提供可提供替代程式碼的協助程式函式勾點,或補救情況。 攔截例程需要傳回適當的值,以便處理可以繼續 ( HINSTANCE
或 FARPROC
)。 或者,它可以傳回 0,表示應該擲回例外狀況。 它也可以擲回自己的例外狀況或 longjmp
脫離鉤子。 有通知攔截和失敗攔截。 相同的例程可用於兩者。
通知攔截
在協助程式例程中採取下列動作之前,會呼叫延遲載入通知攔截:
已檢查連結庫的預存句柄,以查看它是否已載入。
LoadLibrary
呼叫 以嘗試載入 DLL。GetProcAddress
呼叫 以嘗試取得程序的位址。返回延遲匯入載入 Thunk。
通知攔截已啟用:
藉由提供初始化的新指標
__pfnDliNotifyHook2
定義,以指向接收通知的您自己的函式。-或-
將指標
__pfnDliNotifyHook2
設定為攔截函式,再呼叫程式延遲載入的 DLL。
如果通知是 dliStartProcessing
,攔截函式可以傳回:
NULL
默認協助程式會處理 DLL 的載入。 僅針對資訊用途呼叫會很有用。
函式指標
略過默認延遲載入處理。 它可讓您提供自己的載入處理程式。
如果通知是 dliNotePreLoadLibrary
,攔截函式可以傳回:
0,如果它只是想要參考通知。
HMODULE
如果載入 DLL 本身,則為載入 DLL 的 。
如果通知是 dliNotePreGetProcAddress
,攔截函式可以傳回:
0,如果它只是想要參考通知。
如果攔截函式取得位址本身,則匯入函式的位址。
如果通知為 dliNoteEndProcessing
,則會忽略攔截函式的傳回值。
如果初始化此指標(非零),延遲載入協助程式會在執行期間在特定通知點叫用函式。 函式指標具有下列定義:
// 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;
通知會將 結構傳入 DelayLoadInfo
連結函式,以及通知值。 此數據與延遲載入協助程式例程所使用的數據相同。 通知值將是 Structure 和常數定義中定義的其中一個值。
失敗攔截
失敗攔截的啟用方式與 通知攔截相同。 攔截例程必須傳回適當的值,以便處理可以繼續 ( HINSTANCE
或 FARPROC
),或 0 表示應該擲回例外狀況。
參考使用者定義函式的指標變數為:
// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook __pfnDliFailureHook2;
結構 DelayLoadInfo
包含錯誤詳細報告所需的所有相關數據,包括 來自 GetLastError
的值。
如果通知是 dliFailLoadLib
,攔截函式可以傳回:
0,如果無法處理失敗則為 。
如果
HMODULE
失敗勾點已修正問題並載入連結庫本身,則為 。
如果通知是 dliFailGetProc
,攔截函式可以傳回:
0,如果無法處理失敗則為 。
如果失敗攔截成功取得位址本身,則為有效的程式位址 (import 函式位址)。
使用例外狀況報告
如果處理錯誤所需的所有專案都是中止程式,只要用戶程式代碼可以處理例外狀況,就不需要攔截。
延遲載入例外狀況代碼
在延遲載入期間發生失敗時,可以引發結構化例外狀況代碼。 例外狀況值是使用 VcppException
巨集來指定:
//
// Exception information
//
#define FACILITY_VISUALCPP ((LONG)0x6d)
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
若發生 LoadLibrary
失敗,則會擲回標準 VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)
。 GetProcAddress
針對失敗,擲回的錯誤為 VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)
。 例外狀況會將指標傳遞至 DelayLoadInfo
結構。 其位於 LPDWORD
欄位中,從 EXCEPTION_RECORD
結構擷取GetExceptionInformation
的值ExceptionInformation[0]
中。
如果欄位中設定 grAttrs
了不正確的位,則會擲回例外狀況 ERROR_INVALID_PARAMETER
。 此例外狀況適用於所有意圖和用途,都是致命的。
如需詳細資訊,請參閱 結構和常數定義。