DllMain-toegangspunt

Een optioneel toegangspunt in een DLL (Dynamic Link Library). Wanneer het systeem een proces of thread start of beëindigt, wordt de invoerpuntfunctie aangeroepen voor elke geladen DLL met behulp van de eerste thread van het proces. Het systeem roept ook de invoerpuntfunctie voor een DLL aan wanneer deze wordt geladen of verwijderd met behulp van de functies LoadLibrary en FreeLibrary .

Warning

Er zijn aanzienlijke limieten voor wat u veilig kunt doen in een DLL-toegangspunt. Zie Algemene aanbevolen procedures voor specifieke Windows API's die onveilig zijn om in DllMain aan te roepen. Als u iets anders nodig hebt dan de eenvoudigste initialisatie, doet u dat in een initialisatiefunctie voor het DLL-bestand. U kunt vereisen dat toepassingen de initialisatiefunctie aanroepen nadat DllMain is uitgevoerd en voordat ze andere functies in het DLL-bestand aanroepen.

Voorbeeld

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpvReserved )  // 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:
        
            if (lpvReserved != nullptr)
            {
                break; // do not do cleanup if process termination scenario
            }
            
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

Dit is een voorbeeld uit de Dynamic-Link Library Entry-Point Function.

Syntax

BOOL WINAPI DllMain(
  _In_ HINSTANCE hinstDLL,
  _In_ DWORD     fdwReason,
  _In_ LPVOID    lpvReserved
);

Parameters

hinstDLL [in]

Een ingang naar de DLL-module. De waarde is het basisadres van de DLL. De HINSTANCE van een DLL is hetzelfde als de HMODULE van het DLL-bestand, zodat hinstDLL kan worden gebruikt in aanroepen naar functies waarvoor een modulehandgreep is vereist.

fdwReason [in]

De redencode die aangeeft waarom de DLL-invoerpuntfunctie wordt aangeroepen. Deze parameter kan een van de volgende waarden zijn.

Value Meaning
DLL_PROCESS_ATTACH
1
Het DLL-bestand wordt geladen in de virtuele adresruimte van het huidige proces als gevolg van het starten van het proces of als gevolg van een aanroep naar LoadLibrary. DLL's kunnen deze mogelijkheid gebruiken om instantiegegevens te initialiseren of om de functie TlsAlloc te gebruiken om een TLS-index (Local Storage) voor threads toe te wijzen.
De parameter lpvReserved geeft aan of het DLL-bestand statisch of dynamisch wordt geladen.
DLL_PROCESS_DETACH
0
Het DLL-bestand wordt uit de virtuele adresruimte van het aanroepende proces verwijderd omdat het niet is geladen of het aantal verwijzingen nul heeft bereikt (de processen zijn beëindigd of FreeLibrary één keer genoemd voor elke keer dat het LoadLibrary wordt genoemd).
De parameter lpvReserved geeft aan of het DLL-bestand wordt verwijderd als gevolg van een FreeLibrary-aanroep , een fout bij het laden of beëindigen van het proces.
De DLL kan deze mogelijkheid gebruiken om de functie TlsFree aan te roepen om tls-indexen vrij te maken die zijn toegewezen met behulp van TlsAlloc en om lokale threadgegevens vrij te maken.
Houd er rekening mee dat de thread die de melding DLL_PROCESS_DETACH ontvangt, niet noodzakelijkerwijs dezelfde thread is die de melding DLL_PROCESS_ATTACH heeft ontvangen.
DLL_THREAD_ATTACH
2
Het huidige proces maakt een nieuwe thread. Wanneer dit gebeurt, roept het systeem de ingangspuntfunctie aan van alle DLL's die momenteel aan het proces zijn gekoppeld. De aanroep wordt uitgevoerd in de context van de nieuwe thread. DLL's kunnen deze mogelijkheid gebruiken om een TLS-site voor de thread te initialiseren. Een thread die de DLL-invoerpuntfunctie aanroept met DLL_PROCESS_ATTACH roept de DLL-invoerpuntfunctie niet aan met DLL_THREAD_ATTACH.
Houd er rekening mee dat de invoerpuntfunctie van een DLL alleen met deze waarde wordt aangeroepen door threads die zijn gemaakt nadat het DLL-bestand door het proces is geladen. Wanneer een DLL wordt geladen met behulp van LoadLibrary, roepen bestaande threads de invoerpuntfunctie van de zojuist geladen DLL niet aan.
DLL_THREAD_DETACH
3
Een thread wordt schoon afgesloten. Als het DLL-bestand een aanwijzer heeft opgeslagen voor toegewezen geheugen in een TLS-site, moet deze mogelijkheid worden gebruikt om het geheugen vrij te maken. Het systeem roept de invoerpuntfunctie aan van alle momenteel geladen DLL's met deze waarde. De aanroep wordt uitgevoerd in de context van de afsluitende thread.

lpvReserved [in]

Als fdwReasonis DLL_PROCESS_ATTACH, is lpvReservedNULL voor dynamische belastingen en niet-NULL voor statische belastingen.

Als fdwReason is DLL_PROCESS_DETACH, is lpvReservedNULL als FreeLibrary is aangeroepen of de DLL-belasting is mislukt en niet NULL als het proces wordt beëindigd.

Retourwaarde

Wanneer het systeem de DllMain-functie aanroept met de DLL_PROCESS_ATTACH waarde, retourneert de functie TRUE als deze slaagt of ONWAAR als de initialisatie mislukt. Als de retourwaarde FALSE is wanneer DllMain wordt aangeroepen omdat het proces gebruikmaakt van de functie LoadLibrary , retourneert LoadLibrary NULL. (Het systeem roept uw ingangspuntfunctie onmiddellijk aan met DLL_PROCESS_DETACH en verwijdert het DLL-bestand.) Als de retourwaarde FALSE is wanneer DllMain wordt aangeroepen tijdens de initialisatie van het proces, wordt het proces beëindigd met een fout. Als u uitgebreide foutinformatie wilt ophalen, roept u GetLastError aan.

Wanneer het systeem de DllMain-functie aanroept met een andere waarde dan DLL_PROCESS_ATTACH, wordt de retourwaarde genegeerd.

Remarks

DllMain is een tijdelijke aanduiding voor de door de bibliotheek gedefinieerde functienaam. U moet de werkelijke naam opgeven die u gebruikt bij het bouwen van uw DLL. Zie de documentatie die is opgenomen in uw ontwikkelhulpprogramma's voor meer informatie.

Tijdens het opstarten van het eerste proces of na een aanroep naar LoadLibrary scant het systeem de lijst met geladen DLL's voor het proces. Voor elke DLL die nog niet is aangeroepen met de DLL_PROCESS_ATTACH-waarde , roept het systeem de invoerpuntfunctie van het DLL-bestand aan. Deze aanroep wordt uitgevoerd in de context van de thread waardoor de adresruimte van het proces is gewijzigd, zoals de primaire thread van het proces of de thread die LoadLibrary wordt genoemd. Toegang tot het toegangspunt wordt geserialiseerd door het systeem op basis van een proces. Threads in DllMain bevatten de loadervergrendeling, zodat er geen extra DLL's dynamisch kunnen worden geladen of geïnitialiseerd.

Als de invoerpuntfunctie van het DLL ONWAAR retourneert na een DLL_PROCESS_ATTACH melding, ontvangt deze een DLL_PROCESS_DETACH melding en wordt het DLL-bestand onmiddellijk uitgeladen. Als de DLL_PROCESS_ATTACH code echter een uitzondering genereert, ontvangt de invoerpuntfunctie de melding DLL_PROCESS_DETACH niet.

Er zijn gevallen waarin de ingangspuntfunctie wordt aangeroepen voor een afsluitthread, zelfs als de invoerpuntfunctie nooit is aangeroepen met DLL_THREAD_ATTACH voor de thread:

  • De thread was de eerste thread in het proces, dus het systeem noemde de invoerpuntfunctie met de DLL_PROCESS_ATTACH waarde.
  • De thread werd al uitgevoerd toen er een aanroep naar de LoadLibrary-functie werd uitgevoerd, dus het systeem heeft nooit de invoerpuntfunctie voor de thread genoemd.

Wanneer een DLL uit een proces wordt verwijderd als gevolg van een mislukte belasting van het DLL-bestand, beëindiging van het proces of een aanroep naar FreeLibrary, roept het systeem de ingangspuntfunctie van het DLL-bestand niet aan met de DLL_THREAD_DETACH waarde voor de afzonderlijke threads van het proces. Het DLL-bestand wordt alleen een DLL_PROCESS_DETACH melding verzonden. DLL's kunnen deze mogelijkheid gebruiken om alle resources op te schonen voor alle threads die bekend zijn bij het DLL-bestand.

Bij het verwerken van DLL_PROCESS_DETACH moet een DLL alleen resources vrij maken, zoals heap-geheugen als het DLL-bestand dynamisch wordt verwijderd (de parameter lpvReserved is NULL). Als het proces wordt beëindigd (de parameter lpvReserved is niet-NULL), zijn alle threads in het proces, behalve de huidige thread, al afgesloten of zijn expliciet beëindigd door een aanroep naar de functie ExitProcess , waardoor sommige procesresources, zoalsaps, in een inconsistente status kunnen blijven. In dit geval is het niet veilig voor het DLL-bestand om de resources op te schonen. In plaats daarvan moet het DLL-bestand het besturingssysteem toestaan om het geheugen vrij te maken.

Als u een proces beëindigt door TerminateProcess of TerminateJobObject aan te roepen, ontvangen de DLL's van dat proces geen DLL_PROCESS_DETACH meldingen. Als u een thread beëindigt door TerminateThread aan te roepen, ontvangen de DLL's van die thread geen DLL_THREAD_DETACH meldingen.

De invoerpuntfunctie mag alleen eenvoudige initialisatie- of beëindigingstaken uitvoeren. Het mag de functie LoadLibrary of LoadLibraryEx (of een functie die deze functies aanroept) niet aanroepen, omdat hiermee afhankelijkheidslussen in de DLL-laadvolgorde kunnen worden gemaakt. Dit kan ertoe leiden dat een DLL wordt gebruikt voordat het systeem de initialisatiecode heeft uitgevoerd. Op dezelfde manier mag de ingangspuntfunctie de FreeLibrary-functie (of een functie die FreeLibrary aanroept) niet aanroepen tijdens het beëindigen van het proces, omdat dit kan resulteren in een DLL die wordt gebruikt nadat het systeem de beëindigingscode heeft uitgevoerd.

Omdat Kernel32.dll gegarandeerd wordt geladen in de adresruimte van het proces wanneer de invoerpuntfunctie wordt aangeroepen, resulteert het aanroepen van functies in Kernel32.dll niet in het DLL-bestand dat wordt gebruikt voordat de initialisatiecode is uitgevoerd. Daarom kan de invoerpuntfunctie functies aanroepen in Kernel32.dll die geen andere DLL's laden. DllMain kan bijvoorbeeld synchronisatieobjecten maken, zoals kritieke secties en mutexes, en TLS gebruiken. Helaas is er geen uitgebreide lijst met veilige functies in Kernel32.dll.

Het aanroepen van functies waarvoor andere DLL's dan Kernel32.dll zijn vereist, kunnen leiden tot problemen die moeilijk te diagnosticeren zijn. Als u bijvoorbeeld gebruikers-, Shell- en COM-functies aanroept, kan dit leiden tot schendingsfouten, omdat sommige functies andere systeemonderdelen laden. Omgekeerd kunnen aanroepende functies zoals deze tijdens beëindiging fouten veroorzaken omdat het bijbehorende onderdeel mogelijk al is uitgepakt of niet geïnitialiseerd.

Omdat DLL-meldingen worden geserialiseerd, mogen toegangspuntfuncties niet proberen te communiceren met andere threads of processen. Impasses kunnen zich voordoen als gevolg hiervan.

Zie aanbevolen procedures voor dynamische koppelingsbibliotheek voor informatie over aanbevolen procedures bij het schrijven van een DLL.

Als uw DLL is gekoppeld aan de C-runtimebibliotheek (CRT), roept het toegangspunt van de CRT de constructors en destructors aan voor globale en statische C++-objecten. Deze beperkingen voor DllMain zijn daarom ook van toepassing op constructors en destructors en alle code die ermee wordt aangeroepen.

Overweeg om DisableThreadLibraryCalls aan te roepen wanneer u DLL_PROCESS_ATTACH ontvangt, tenzij uw DLL is gekoppeld aan een statische C-runtimebibliotheek (CRT).

Requirements

Requirement Value
Minimaal ondersteunde client
Windows XP [alleen desktop-apps]
Minimaal ondersteunde server
Windows Server 2003 [alleen desktop-apps]
Koptekst
Process.h

Zie ook

Dynamic-Link Library Entry-Point, functie

Dynamic-Link bibliotheekfuncties

FreeLibrary

GetModuleFileName

LoadLibrary

TlsAlloc

TlsFree

DisableThreadLibraryCalls