Partilhar via


Função Entry-Point Biblioteca Dynamic-Link

Uma DLL pode, opcionalmente, especificar uma função de ponto de entrada. Se presente, o sistema chama a função de ponto de entrada sempre que um processo ou thread carrega ou descarrega a DLL. Ele pode ser usado para executar tarefas simples de inicialização e limpeza. Por exemplo, ele pode configurar o armazenamento local de thread quando um novo thread é criado e limpá-lo quando o thread é encerrado.

Se você estiver vinculando sua DLL com a biblioteca de tempo de execução C, ela pode fornecer uma função de ponto de entrada para você e permitir que você forneça uma função de inicialização separada. Consulte a documentação da sua biblioteca de tempo de execução para obter mais informações.

Se você estiver fornecendo seu próprio ponto de entrada, consulte a função DllMain. O nome DllMain é um espaço reservado para uma função definida pelo usuário. Você deve especificar o nome real que você usa quando você cria sua DLL. Para obter mais informações, consulte a documentação incluída com suas ferramentas de desenvolvimento.

Chamando a função Entry-Point

O sistema chama a função de ponto de entrada sempre que ocorre qualquer um dos seguintes eventos:

  • Um processo carrega a DLL. Para processos que usam vinculação dinâmica em tempo de carregamento, a DLL é carregada durante a inicialização do processo. Para processos que usam vinculação em tempo de execução, a DLL é carregada antes que LoadLibrary ou LoadLibraryEx retorne.
  • Um processo descarrega a DLL. A DLL é descarregada quando o processo termina ou chama a funçãoFreeLibrary e a contagem de referência torna-se zero. Se o processo for encerrado como resultado do TerminateProcess ou função de TerminateThread, o sistema não chamará a função de ponto de entrada DLL.
  • Um novo thread é criado em um processo que carregou a DLL. Você pode usar a funçãoDisableThreadLibraryCalls para desabilitar a notificação quando threads são criados.
  • Um thread de um processo que carregou a DLL termina normalmente, não usando TerminateThread ou TerminateProcess. Quando um processo descarrega a DLL, a função de ponto de entrada é chamada apenas uma vez para todo o processo, em vez de uma vez para cada thread existente do processo. Você pode usar DisableThreadLibraryCalls para desabilitar a notificação quando os threads forem encerrados.

Apenas um thread de cada vez pode chamar a função de ponto de entrada.

O sistema chama a função de ponto de entrada no contexto do processo ou thread que fez com que a função fosse chamada. Isso permite que uma DLL use sua função de ponto de entrada para alocar memória no espaço de endereço virtual do processo de chamada ou para abrir identificadores acessíveis ao processo. A função de ponto de entrada também pode alocar memória privada para um novo thread usando armazenamento local de thread (TLS). Para obter mais informações sobre armazenamento local de thread, consulte Thread Local Storage.

Definição de função Entry-Point

A função de ponto de entrada DLL deve ser declarada com a convenção de chamada padrão. Se o ponto de entrada DLL não for declarado corretamente, a DLL não será carregada e o sistema exibirá uma mensagem indicando que o ponto de entrada DLL deve ser declarado com WINAPI.

No corpo da função, você pode manipular qualquer combinação dos seguintes cenários em que o ponto de entrada DLL foi chamado:

  • Um processo carrega a DLL (DLL_PROCESS_ATTACH).
  • O processo atual cria um novo thread (DLL_THREAD_ATTACH).
  • Um fio sai normalmente (DLL_THREAD_DETACH).
  • Um processo descarrega a DLL (DLL_PROCESS_DETACH).

A função de ponto de entrada deve executar apenas tarefas simples de inicialização. Ele não deve chamar o LoadLibrary ou função LoadLibraryEx (ou uma função que chama essas funções), porque isso pode criar loops de dependência na ordem de carregamento da DLL. Isso pode resultar em uma DLL sendo usada antes que o sistema tenha executado seu código de inicialização. Da mesma forma, a função de ponto de entrada não deve chamar a função FreeLibrary (ou uma função que chama FreeLibrary) durante o encerramento do processo, porque isso pode resultar em uma DLL sendo usada depois que o sistema executou seu código de terminação.

Como é garantido que Kernel32.dll seja carregado no espaço de endereço do processo quando a função de ponto de entrada é chamada, chamar funções no Kernel32.dll não resulta no uso da DLL antes que seu código de inicialização tenha sido executado. Portanto, a função de ponto de entrada pode criar objetos de sincronização como seções críticas e mutexes, e usar TLS, porque essas funções estão localizadas em Kernel32.dll. Não é seguro chamar as funções do registro, por exemplo, porque eles estão localizados em Advapi32.dll.

Chamar outras funções pode resultar em problemas difíceis de diagnosticar. Por exemplo, chamar funções User, Shell e COM pode causar erros de violação de acesso, porque algumas funções em suas DLLs chamam LoadLibrary para carregar outros componentes do sistema. Por outro lado, chamar essas funções durante o término pode causar erros de violação de acesso porque o componente correspondente pode já ter sido descarregado ou não inicializado.

O exemplo a seguir demonstra como estruturar a função de ponto de entrada DLL.

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

Valor de retorno da função Entry-Point

Quando uma função de ponto de entrada DLL é chamada porque um processo está carregando, a função retorna TRUE para indicar sucesso. Para processos que usam vinculação de tempo de carregamento, um valor de retorno de FALSE faz com que a inicialização do processo falhe e o processo seja encerrado. Para processos que usam vinculação em tempo de execução, um valor de retorno de FALSE faz com que a função LoadLibrary ou LoadLibraryEx retorne NULL , indicando falha. (O sistema chama imediatamente sua função de ponto de entrada com DLL_PROCESS_DETACH e descarrega a DLL.) O valor de retorno da função de ponto de entrada é desconsiderado quando a função é chamada por qualquer outro motivo.