Función Entry-Point Library Dynamic-Link

Opcionalmente, un archivo DLL puede especificar una función de punto de entrada. Si está presente, el sistema llama a la función de punto de entrada cada vez que un proceso o subproceso carga o descarga el archivo DLL. Se puede usar para realizar tareas sencillas de inicialización y limpieza. Por ejemplo, puede configurar el almacenamiento local del subproceso cuando se crea un nuevo subproceso y limpiarlo cuando finaliza el subproceso.

Si va a vincular el archivo DLL con la biblioteca en tiempo de ejecución de C, puede proporcionar una función de punto de entrada para usted y permitirle proporcionar una función de inicialización independiente. Consulte la documentación de la biblioteca en tiempo de ejecución para obtener más información.

Si va a proporcionar su propio punto de entrada, consulte la función DllMain . El nombre DllMain es un marcador de posición para una función definida por el usuario. Debe especificar el nombre real que use al compilar el archivo DLL. Para obtener más información, consulte la documentación incluida con las herramientas de desarrollo.

Llamar a la función Entry-Point

El sistema llama a la función de punto de entrada cada vez que se produce cualquiera de los siguientes eventos:

  • Un proceso carga el archivo DLL. Para los procesos que usan la vinculación dinámica en tiempo de carga, el archivo DLL se carga durante la inicialización del proceso. Para los procesos que usan la vinculación en tiempo de ejecución, el archivo DLL se carga antes de que se devuelva LoadLibrary o LoadLibraryEx .
  • Un proceso descarga el archivo DLL. El archivo DLL se descarga cuando el proceso finaliza o llama a la función FreeLibrary y el recuento de referencias se convierte en cero. Si el proceso finaliza como resultado de la función TerminateProcess o TerminateThread , el sistema no llama a la función de punto de entrada DLL.
  • Se crea un nuevo subproceso en un proceso que ha cargado el archivo DLL. Puede usar la función DisableThreadLibraryCalls para deshabilitar la notificación cuando se crean subprocesos.
  • Un subproceso de un proceso que ha cargado el archivo DLL finaliza normalmente, no mediante TerminateThread o TerminateProcess. Cuando un proceso descarga el archivo DLL, se llama a la función de punto de entrada solo una vez para todo el proceso, en lugar de una vez para cada subproceso existente del proceso. Puede usar DisableThreadLibraryCalls para deshabilitar la notificación cuando finalizan los subprocesos.

Solo un subproceso a la vez puede llamar a la función de punto de entrada.

El sistema llama a la función de punto de entrada en el contexto del proceso o subproceso que provocó que se llamara a la función. Esto permite que un archivo DLL use su función de punto de entrada para asignar memoria en el espacio de direcciones virtuales del proceso de llamada o abrir identificadores accesibles para el proceso. La función de punto de entrada también puede asignar memoria privada a un nuevo subproceso mediante el almacenamiento local de subprocesos (TLS). Para obtener más información sobre el almacenamiento local de subprocesos, consulte Almacenamiento local de subprocesos.

Definición de función Entry-Point

La función de punto de entrada dll debe declararse con la convención de llamada a llamada estándar. Si el punto de entrada dll no se declara correctamente, el archivo DLL no se carga y el sistema muestra un mensaje que indica que el punto de entrada dll debe declararse con WINAPI.

En el cuerpo de la función, puede controlar cualquier combinación de los escenarios siguientes en los que se ha llamado al punto de entrada dll:

  • Un proceso carga el archivo DLL (DLL_PROCESS_ATTACH).
  • El proceso actual crea un nuevo subproceso (DLL_THREAD_ATTACH).
  • Un subproceso sale normalmente (DLL_THREAD_DETACH).
  • Un proceso descarga el archivo DLL (DLL_PROCESS_DETACH).

La función de punto de entrada solo debe realizar tareas de inicialización sencillas. No debe llamar a la función LoadLibrary o LoadLibraryEx (o una función que llama a estas funciones), ya que esto puede crear bucles de dependencia en el orden de carga de DLL. Esto puede dar lugar a que se use un archivo DLL antes de que el sistema haya ejecutado su código de inicialización. Del mismo modo, la función de punto de entrada no debe llamar a la función FreeLibrary (o una función que llama a FreeLibrary) durante la finalización del proceso, ya que esto puede dar lugar a que se use un archivo DLL después de que el sistema haya ejecutado su código de finalización.

Dado que se garantiza que Kernel32.dll se cargan en el espacio de direcciones del proceso cuando se llama a la función de punto de entrada, llamar a funciones en Kernel32.dll no da lugar a que se use el archivo DLL antes de que se haya ejecutado su código de inicialización. Por lo tanto, la función de punto de entrada puede crear objetos de sincronización , como secciones críticas y exclusión mutua, y usar TLS, ya que estas funciones se encuentran en Kernel32.dll. No es seguro llamar a las funciones del Registro, por ejemplo, porque se encuentran en Advapi32.dll.

Llamar a otras funciones puede dar lugar a problemas difíciles de diagnosticar. Por ejemplo, llamar a funciones User, Shell y COM puede provocar errores de infracción de acceso, ya que algunas funciones de sus DLL llaman a LoadLibrary para cargar otros componentes del sistema. Por el contrario, llamar a esas funciones durante la finalización puede provocar errores de infracción de acceso porque es posible que el componente correspondiente ya se haya descargado o no inicializado.

En el ejemplo siguiente se muestra cómo estructurar la función de punto 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 devuelto de función Entry-Point

Cuando se llama a una función de punto de entrada DLL porque se carga un proceso, la función devuelve TRUE para indicar que se ha realizado correctamente. En el caso de los procesos que usan la vinculación en tiempo de carga, un valor devuelto de FALSE hace que se produzca un error en la inicialización del proceso y el proceso finalice. En el caso de los procesos que usan la vinculación en tiempo de ejecución, un valor devuelto de FALSE hace que la función LoadLibrary o LoadLibraryEx devuelva NULL, lo que indica un error. (El sistema llama inmediatamente a la función de punto de entrada con DLL_PROCESS_DETACH y descarga el archivo DLL). El valor devuelto de la función de punto de entrada se omite cuando se llama a la función por cualquier otro motivo.