Freigeben über


Dynamic-Link Library Entry-Point-Funktion

Eine DLL kann optional eine Einstiegspunktfunktion angeben. Wenn vorhanden, ruft das System die Einstiegspunktfunktion auf, wenn ein Prozess oder Thread die DLL lädt oder entlädt. Sie kann verwendet werden, um einfache Initialisierungs- und Bereinigungsaufgaben auszuführen. Beispielsweise kann er den lokalen Threadspeicher einrichten, wenn ein neuer Thread erstellt wird, und es bereinigen, wenn der Thread beendet wird.

Wenn Sie Ihre DLL mit der C-Laufzeitbibliothek verknüpfen, kann sie eine Einstiegspunktfunktion für Sie bereitstellen und eine separate Initialisierungsfunktion bereitstellen. Weitere Informationen finden Sie in der Dokumentation für Ihre Laufzeitbibliothek.

Wenn Sie Ihren eigenen Einstiegspunkt bereitstellen, lesen Sie die funktion DllMain. Der Name DllMain- ist ein Platzhalter für eine benutzerdefinierte Funktion. Sie müssen den tatsächlichen Namen angeben, den Sie beim Erstellen der DLL verwenden. Weitere Informationen finden Sie in der Dokumentation, die in Ihren Entwicklungstools enthalten ist.

Aufrufen der Entry-Point-Funktion

Das System ruft die Einstiegspunktfunktion auf, wenn eines der folgenden Ereignisse eintritt:

  • Ein Prozess lädt die DLL. Bei Prozessen mit dynamischer Ladezeitverknüpfung wird die DLL während der Prozessinitialisierung geladen. Bei Prozessen mit Laufzeitverknüpfung wird die DLL geladen, bevor LoadLibrary oder LoadLibraryEx- zurückgegeben wird.
  • Ein Prozess entlädt die DLL. Die DLL wird entladen, wenn der Prozess die FreeLibrary--Funktion beendet oder aufruft, und die Verweisanzahl wird null. Wenn der Prozess als Ergebnis der TerminateProcess- oder TerminateThread--Funktion beendet wird, ruft das System die DLL-Einstiegspunktfunktion nicht auf.
  • Ein neuer Thread wird in einem Prozess erstellt, der die DLL geladen hat. Sie können die funktion DisableThreadLibraryCalls verwenden, um die Benachrichtigung zu deaktivieren, wenn Threads erstellt werden.
  • Ein Thread eines Prozesses, der die DLL geladen hat, wird normal beendet, ohne TerminateThread- oder TerminateProcess-zu verwenden. Wenn ein Prozess die DLL entlädt, wird die Einstiegspunktfunktion nur einmal für den gesamten Prozess aufgerufen, anstatt einmal für jeden vorhandenen Thread des Prozesses. Sie können DisableThreadLibraryCalls- verwenden, um Benachrichtigungen zu deaktivieren, wenn Threads beendet werden.

Nur jeweils ein Thread kann die Einstiegspunktfunktion aufrufen.

Das System ruft die Einstiegspunktfunktion im Kontext des Prozesses oder Threads auf, der dazu führte, dass die Funktion aufgerufen wurde. Dadurch kann eine DLL ihre Einstiegspunktfunktion zum Zuordnen des Speichers im virtuellen Adressraum des aufrufenden Prozesses oder zum Öffnen von Handles verwenden, die für den Prozess zugänglich sind. Die Einstiegspunktfunktion kann auch Arbeitsspeicher zuordnen, der einem neuen Thread privat ist, indem der lokale Threadspeicher (TLS) verwendet wird. Weitere Informationen zum lokalen Threadspeicher finden Sie unter thread local storage.

Entry-Point Funktionsdefinition

Die DLL-Einstiegspunktfunktion muss mit der Standardaufrufkonvention deklariert werden. Wenn der DLL-Einstiegspunkt nicht ordnungsgemäß deklariert wird, wird die DLL nicht geladen, und das System zeigt eine Meldung an, dass der DLL-Einstiegspunkt mit WINAPI deklariert werden muss.

Im Textkörper der Funktion können Sie eine beliebige Kombination der folgenden Szenarien behandeln, in denen der DLL-Einstiegspunkt aufgerufen wurde:

  • Ein Prozess lädt die DLL (DLL_PROCESS_ATTACH).
  • Der aktuelle Prozess erstellt einen neuen Thread (DLL_THREAD_ATTACH).
  • Ein Thread wird normal beendet (DLL_THREAD_DETACH).
  • Ein Prozess entlädt die DLL (DLL_PROCESS_DETACH).

Die Einstiegspunktfunktion sollte nur einfache Initialisierungsaufgaben ausführen. Sie darf die LoadLibrary oder LoadLibraryEx--Funktion (oder eine Funktion, die diese Funktionen aufruft) nicht aufrufen, da dadurch Abhängigkeitsschleifen in der DLL-Ladereihenfolge erstellt werden können. Dies kann dazu führen, dass eine DLL verwendet wird, bevor das System seinen Initialisierungscode ausgeführt hat. Ebenso darf die Einstiegspunktfunktion die FreeLibrary-Funktion (oder eine Funktion, die FreeLibrary) während der Prozessbeendigung aufruft, nicht aufrufen, da dies dazu führen kann, dass eine DLL verwendet wird, nachdem das System seinen Beendigungscode ausgeführt hat.

Da Kernel32.dll garantiert in den Prozessadressraum geladen werden, wenn die Einstiegspunktfunktion aufgerufen wird, führt das Aufrufen von Funktionen in Kernel32.dll nicht dazu, dass die DLL verwendet wird, bevor der Initialisierungscode ausgeführt wurde. Daher kann die Einstiegspunktfunktion Synchronisierungsobjekte wie kritische Abschnitte und Mutexes erstellen und TLS verwenden, da sich diese Funktionen in Kernel32.dllbefinden. Es ist nicht sicher, die Registrierungsfunktionen aufzurufen, z. B. weil sie sich in Advapi32.dllbefinden.

Das Aufrufen anderer Funktionen kann zu Problemen führen, die schwierig zu diagnostizieren sind. Das Aufrufen von Benutzer-, Shell- und COM-Funktionen kann z. B. zu Zugriffsverletzungsfehlern führen, da einige Funktionen in ihren DLLs LoadLibrary- aufrufen, um andere Systemkomponenten zu laden. Umgekehrt kann das Aufrufen dieser Funktionen während der Beendigung zu Zugriffsverletzungsfehlern führen, da die entsprechende Komponente möglicherweise bereits entladen oder nicht initialisiert wurde.

Im folgenden Beispiel wird veranschaulicht, wie die DLL-Einstiegspunktfunktion strukturiert wird.

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.
}

Entry-Point Funktionsrückgabewert

Wenn eine DLL-Einstiegspunktfunktion aufgerufen wird, weil ein Prozess geladen wird, gibt die Funktion TRUE zurück, um den Erfolg anzuzeigen. Bei Prozessen, die eine Ladezeitverknüpfung verwenden, führt ein Rückgabewert von FALSE dazu, dass die Prozessinitialisierung fehlschlägt und der Prozess beendet wird. Bei Prozessen, die die Laufzeitverknüpfung verwenden, bewirkt ein Rückgabewert von FALSE, dass die LoadLibrary oder LoadLibraryEx-Funktion-Funktion NULL-zurückgibt, was auf einen Fehler hinweist. (Das System ruft die Einstiegspunktfunktion sofort mit DLL_PROCESS_DETACH auf und entlädt die DLL.) Der Rückgabewert der Einstiegspunktfunktion wird ignoriert, wenn die Funktion aus irgendeinem anderen Grund aufgerufen wird.