Tratamento de erro e notificação
Se o programa usar DLLs carregadas de atraso, ele deverá tratar os erros de forma robusta, já que falhas que ocorrem enquanto o programa está em execução resultarão em exceções sem tratamento. O tratamento de falhas é composto por duas partes: recuperação por meio de um gancho e relatório por meio de uma exceção.
Para obter mais informações sobre o tratamento de erros e notificação em carga de atraso de DLL, consulte Noções básicas sobre a função auxiliar.
Para obter mais informações sobre funções de gancho, consulte Definições de estrutura e constante.
Recuperação por meio de um gancho
Seu código pode precisar se recuperar em uma falha ou fornecer uma biblioteca ou rotina alternativa. Você pode fornecer um gancho para a função auxiliar que pode fornecer o código alternativo ou corrigir a situação. A rotina do gancho precisa retornar um valor adequado para que o processamento possa continuar (um HINSTANCE
ou FARPROC
). Ou pode retornar 0 para indicar que uma exceção deve ser lançada. Ele também poderia lançar sua própria exceção ou longjmp
fora do gancho. Há ganchos de notificação e ganchos de falha. A mesma rotina pode ser usada para ambos.
Ganchos de notificação
Os ganchos de notificação de carga de atraso são chamados pouco antes da execução das seguintes ações na rotina auxiliar:
O identificador armazenado na biblioteca é verificado para ver se já foi carregado.
LoadLibrary
é chamado para tentar a carga da DLL.GetProcAddress
é chamado para tentar obter o endereço do procedimento.Retorne à conversão da carga de importação de atraso.
O gancho de notificação é habilitado:
Fornecendo uma nova definição do ponteiro
__pfnDliNotifyHook2
inicializado para apontar para sua própria função que recebe as notificações.-ou-
Definindo o ponteiro
__pfnDliNotifyHook2
para sua função de gancho antes de qualquer chamada para a DLL que o programa está atrasando o carregamento.
Se a notificação for dliStartProcessing
, a função de gancho poderá retornar:
NULL
O auxiliar padrão controla o carregamento da DLL. É útil chamá-lo apenas para fins informativos.
um ponteiro de função
Ignore o tratamento padrão de carga de atraso. Isso permite que você forneça seu próprio manipulador de carga.
Se a notificação for dliNotePreLoadLibrary
, a função de gancho poderá retornar:
0, se quiser apenas notificações informativas.
O
HMODULE
para a DLL carregada, se ela tiver carregado a própria DLL.
Se a notificação for dliNotePreGetProcAddress
, a função de gancho poderá retornar:
0, se quiser apenas notificações informativas.
O endereço da função importada, se a função de gancho receber o próprio endereço.
Se a notificação for dliNoteEndProcessing
, o valor retornado da função de gancho será ignorado.
Se esse ponteiro for inicializado (não zero), o auxiliar de carga de atraso invocará a função em determinados pontos de notificação durante a execução. O ponteiro de função tem a seguinte definição:
// 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;
As notificações passam em uma estrutura DelayLoadInfo
para a função de gancho junto com o valor de notificação. Esses dados são idênticos aos dados usados pela rotina do auxiliar de carga de atraso. O valor da notificação será um dos valores definidos em Definições de estrutura e constante.
Ganchos de falha
O gancho de falha está habilitado da mesma maneira que o gancho de notificação. A rotina do gancho precisa retornar um valor adequado para que o processamento possa continuar (um HINSTANCE
ou FARPROC
), ou 0, para indicar que uma exceção deve ser gerada.
A variável de ponteiro que se refere à função definida pelo usuário é:
// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook __pfnDliFailureHook2;
A estrutura DelayLoadInfo
contém todos os dados pertinentes necessários para os relatórios detalhados do erro, incluindo o valor de GetLastError
.
Se a notificação for dliFailLoadLib
, a função de gancho poderá retornar:
0, se não puder lidar com a falha.
Um
HMODULE
, se o gancho de falha tiver corrigido o problema e carregado a própria biblioteca.
Se a notificação for dliFailGetProc
, a função de gancho poderá retornar:
0, se não puder lidar com a falha.
Um endereço proc válido (endereço de função de importação), se o gancho de falha tiver conseguido obter o próprio endereço.
Relatar usando uma exceção
Se tudo o que é necessário para lidar com o erro é anular o procedimento, nenhum gancho é necessário, desde que o código do usuário possa lidar com a exceção.
Códigos de exceção de carregamento de atraso
Códigos de exceção estruturados podem ser gerados quando ocorrem falhas durante uma carga atrasada. Os valores de exceção são especificados usando uma macro VcppException
:
//
// Exception information
//
#define FACILITY_VISUALCPP ((LONG)0x6d)
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
Para uma falha LoadLibrary
, o padrão VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)
é lançado. Para uma falha GetProcAddress
, o erro lançado é VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)
. A exceção passa um ponteiro para uma estrutura DelayLoadInfo
. Ele está no valor LPDWORD
recuperado por GetExceptionInformation
da estrutura EXCEPTION_RECORD
, no campo ExceptionInformation[0]
.
Se os bits incorretos forem definidos no campo grAttrs
, a exceção ERROR_INVALID_PARAMETER
será lançada. Essa exceção é fatal para todas as intenções e finalidades.
Para obter mais informações, consulte Definições de estrutura e constante.