Udostępnij za pośrednictwem


Dynamic-Link Library Entry-Point Function

Biblioteka DLL może opcjonalnie określić funkcję punktu wejścia. Jeśli jest obecny, system wywołuje funkcję punktu wejścia za każdym razem, gdy proces lub wątek ładuje lub zwalnia bibliotekę DLL. Może służyć do wykonywania prostych zadań inicjowania i oczyszczania. Można na przykład skonfigurować magazyn lokalny wątku po utworzeniu nowego wątku i wyczyścić go po zakończeniu wątku.

Jeśli łączysz bibliotekę DLL z biblioteką czasu wykonywania języka C, może ona udostępnić funkcję punktu wejścia i umożliwić udostępnienie oddzielnej funkcji inicjowania. Aby uzyskać więcej informacji, zapoznaj się z dokumentacją biblioteki czasu wykonywania.

Jeśli udostępniasz własny punkt wejścia, zobacz funkcję DllMain. Nazwa DllMain jest symbolem zastępczym funkcji zdefiniowanej przez użytkownika. Należy określić rzeczywistą nazwę używaną podczas tworzenia biblioteki DLL. Aby uzyskać więcej informacji, zobacz dokumentację zawartą w narzędziach programistycznych.

Wywoływanie funkcji Entry-Point

System wywołuje funkcję punktu wejścia za każdym razem, gdy wystąpi jedno z następujących zdarzeń:

  • Proces ładuje bibliotekę DLL. W przypadku procesów korzystających z łączenia dynamicznego w czasie ładowania biblioteka DLL jest ładowana podczas inicjowania procesu. W przypadku procesów korzystających z łączenia w czasie wykonywania biblioteka DLL jest ładowana przed zwróceniem loadLibrary lub LoadLibraryEx.
  • Proces zwalnia bibliotekę DLL. Biblioteka DLL jest zwalniana, gdy proces kończy się lub wywołuje funkcję FreeLibrary, a liczba odwołań staje się równa zero. Jeśli proces zakończy się w wyniku TerminateProcess lub TerminateThread funkcji, system nie wywołuje funkcji punktu wejścia dll.
  • Nowy wątek jest tworzony w procesie, który załadował bibliotekę DLL. Możesz użyć funkcji DisableThreadLibraryCalls, aby wyłączyć powiadomienie po utworzeniu wątków.
  • Wątek procesu, który załadował bibliotekę DLL, kończy się normalnie, nie używając TerminateThread lub TerminateProcess. Gdy proces zwalnia bibliotekę DLL, funkcja punktu wejścia jest wywoływana tylko raz dla całego procesu, a nie raz dla każdego istniejącego wątku procesu. Możesz użyć DisableThreadLibraryCalls, aby wyłączyć powiadomienie po zakończeniu wątków.

Tylko jeden wątek jednocześnie może wywołać funkcję punktu wejścia.

System wywołuje funkcję punktu wejścia w kontekście procesu lub wątku, który spowodował wywołanie funkcji. Dzięki temu biblioteka DLL może używać funkcji punktu wejścia do przydzielania pamięci w wirtualnej przestrzeni adresowej procesu wywołującego lub otwierania dojść dostępnych dla tego procesu. Funkcja punktu wejścia może również przydzielić pamięć prywatną do nowego wątku przy użyciu magazynu lokalnego wątku (TLS). Aby uzyskać więcej informacji na temat magazynu lokalnego wątku, zobacz Thread Local Storage.

definicja funkcji Entry-Point

Funkcja punktu wejścia biblioteki DLL musi być zadeklarowana przy użyciu standardowej konwencji wywoływania. Jeśli punkt wejścia biblioteki DLL nie jest poprawnie zadeklarowany, biblioteka DLL nie zostanie załadowana, a system wyświetli komunikat wskazujący, że punkt wejścia biblioteki DLL musi zostać zadeklarowany przy użyciu interfejsu WINAPI.

W treści funkcji można obsłużyć dowolną kombinację następujących scenariuszy, w których punkt wejścia biblioteki DLL został wywołany:

  • Proces ładuje bibliotekę DLL (DLL_PROCESS_ATTACH).
  • Bieżący proces tworzy nowy wątek (DLL_THREAD_ATTACH).
  • Wątek kończy się normalnie (DLL_THREAD_DETACH).
  • Proces zwalnia bibliotekę DLL (DLL_PROCESS_DETACH).

Funkcja punktu wejścia powinna wykonywać tylko proste zadania inicjowania. Nie może wywołać funkcji LoadLibrary lub LoadLibraryEx (lub funkcji wywołującej te funkcje), ponieważ może to spowodować utworzenie pętli zależności w kolejności ładowania bibliotek DLL. Może to spowodować, że biblioteka DLL będzie używana przed wykonaniem przez system kodu inicjowania. Podobnie funkcja punktu wejścia nie może wywoływać funkcji FreeLibrary (lub funkcji, która wywołuje FreeLibrary) podczas kończenia procesu, ponieważ może to spowodować, że biblioteka DLL jest używana po wykonaniu przez system kodu zakończenia.

Ponieważ Kernel32.dll ma gwarancję załadowania w przestrzeni adresowej procesu, gdy wywoływana jest funkcja punktu wejścia, wywoływanie funkcji w Kernel32.dll nie powoduje użycia biblioteki DLL przed wykonaniem kodu inicjowania. W związku z tym funkcja punktu wejścia może tworzyć obiekty synchronizacji , takie jak sekcje krytyczne i muteksy, i używać protokołu TLS, ponieważ te funkcje znajdują się w Kernel32.dll. Nie można bezpiecznie wywołać funkcji rejestru, na przykład dlatego, że znajdują się one w Advapi32.dll.

Wywoływanie innych funkcji może spowodować problemy, które są trudne do zdiagnozowania. Na przykład wywołanie funkcji User, Shell i COM może spowodować błędy naruszenia dostępu, ponieważ niektóre funkcje w ich bibliotekach DLL wywołują LoadLibrary ładowania innych składników systemowych. Z drugiej strony wywoływanie tych funkcji podczas kończenia może spowodować błędy naruszenia dostępu, ponieważ odpowiedni składnik mógł już zostać zwolniony lub niezainicjowany.

W poniższym przykładzie pokazano, jak utworzyć strukturę funkcji punktu wejścia biblioteki 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.
}

wartość zwracana funkcji Entry-Point

Gdy wywoływana jest funkcja punktu wejścia biblioteki DLL, ponieważ proces jest ładowany, funkcja zwraca true, aby wskazać powodzenie. W przypadku procesów korzystających z łączenia w czasie ładowania wartość zwracana FALSE powoduje niepowodzenie inicjowania procesu, a proces kończy się niepowodzeniem. W przypadku procesów korzystających z łączenia w czasie wykonywania wartość FALSE powoduje, że funkcja LoadLibrary lub LoadLibraryEx zwraca nullwskazującą błąd. (System natychmiast wywołuje funkcję punktu wejścia z DLL_PROCESS_DETACH i zwalnia bibliotekę DLL). Wartość zwracana funkcji punktu wejścia jest pomijana, gdy funkcja jest wywoływana z jakiegokolwiek innego powodu.