Функция Entry-Point библиотеки Dynamic-Link

Библиотека DLL может при необходимости указать функцию точки входа. При наличии система вызывает функцию точки входа всякий раз, когда процесс или поток загружает или выгружает библиотеку DLL. Его можно использовать для выполнения простых задач инициализации и очистки. Например, он может настроить локальное хранилище потока при создании нового потока и очистить его при завершении потока.

При связывании библиотеки DLL с библиотекой времени выполнения C она может предоставить функцию точки входа и предоставить отдельную функцию инициализации. Дополнительные сведения см. в документации по библиотеке времени выполнения.

Если вы предоставляете собственную точку входа, см. функцию DllMain . Имя DllMain — это заполнитель для определяемой пользователем функции. Необходимо указать фактическое имя, используемое при сборке библиотеки DLL. Дополнительные сведения см. в документации, включенной в средства разработки.

Вызов функции Entry-Point

Система вызывает функцию точки входа всякий раз, когда происходит одно из следующих событий:

  • Процесс загружает библиотеку DLL. Для процессов, использующих динамическое связывание во время загрузки, библиотека DLL загружается во время инициализации процесса. Для процессов, использующих связывание во время выполнения, библиотека DLL загружается перед возвратом LoadLibrary или LoadLibraryEx .
  • Процесс выгрузит библиотеку DLL. Библиотека DLL выгружается, когда процесс завершает работу или вызывает функцию FreeLibrary , а счетчик ссылок становится нулевым. Если процесс завершается в результате функции TerminateProcess или TerminateThread , система не вызывает функцию точки входа DLL.
  • Новый поток создается в процессе, который загрузил библиотеку DLL. Функцию DisableThreadLibraryCalls можно использовать для отключения уведомлений при создании потоков.
  • Поток процесса, который загрузил библиотеку DLL, завершается нормально, а не с помощью TerminateThread или TerminateProcess. Когда процесс выгружает библиотеку DLL, функция точки входа вызывается только один раз для всего процесса, а не один раз для каждого существующего потока процесса. Отключить уведомления при завершении потоков можно с помощью DisableThreadLibraryCalls .

Только один поток одновременно может вызывать функцию точки входа.

Система вызывает функцию точки входа в контексте процесса или потока, вызвавшего вызов функции. Это позволяет библиотеке DLL использовать функцию точки входа для выделения памяти в виртуальном адресном пространстве вызывающего процесса или открытия дескрипторов, доступных для процесса. Функция точки входа также может выделить память, которая является частной для нового потока, с помощью локального хранилища потока (TLS). Дополнительные сведения о локальном хранилище потоков см. в разделе "Локальный поток" служба хранилища.

Определение функции Entry-Point

Функция точки входа DLL должна быть объявлена с помощью стандартного соглашения о вызовах вызовов. Если точка входа DLL объявлена неправильно, библиотека DLL не загружается, а система отображает сообщение о том, что точка входа DLL должна быть объявлена с помощью WINAPI.

В теле функции можно обрабатывать любое сочетание следующих сценариев, в которых была вызвана точка входа DLL:

  • Процесс загружает библиотеку DLL (DLL_PROCESS_ATTACH).
  • Текущий процесс создает новый поток (DLL_THREAD_ATTACH).
  • Поток обычно завершается (DLL_THREAD_DETACH).
  • Процесс выгружает библиотеку DLL (DLL_PROCESS_DETACH).

Функция точки входа должна выполнять только простые задачи инициализации. Она не должна вызывать функцию LoadLibrary или LoadLibraryEx (или функцию, которая вызывает эти функции), так как это может создавать циклы зависимостей в порядке загрузки DLL. Это может привести к использованию библиотеки DLL до того, как система выполнила свой код инициализации. Аналогичным образом функция точки входа не должна вызывать функцию FreeLibrary (или функцию, которая вызывает FreeLibrary) во время завершения процесса, так как это может привести к использованию библиотеки DLL после того, как система выполнила код завершения.

Так как Kernel32.dll гарантированно загружается в адресное пространство процесса при вызове функции точки входа, вызов функций в Kernel32.dll не приводит к использованию библиотеки DLL до выполнения кода инициализации. Таким образом, функция точки входа может создавать объекты синхронизации , такие как критические разделы и мьютексы, и использовать TLS, так как эти функции находятся в Kernel32.dll. Например, небезопасно вызывать функции реестра, так как они находятся в Advapi32.dll.

Вызов других функций может привести к проблемам, которые трудно диагностировать. Например, вызов функций User, Shell и COM может привести к ошибкам нарушения доступа, так как некоторые функции в библиотеках DLL вызывают LoadLibrary для загрузки других системных компонентов. И наоборот, вызов этих функций во время завершения может привести к ошибкам нарушения доступа, так как соответствующий компонент уже был выгружен или неинициализирован.

В следующем примере показано, как структурировать функцию точки входа 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.
}

Возвращаемое значение функции Entry-Point

При вызове функции точки входа DLL из-за загрузки процесса функция возвращает значение TRUE , чтобы указать успешность. Для процессов, использующих связывание во время загрузки, возвращаемое значение FALSE приводит к сбою инициализации процесса и завершение процесса. Для процессов, использующих связывание во время выполнения, возвращаемое значение FALSE приводит к тому, что функция LoadLibrary или LoadLibraryEx возвращает значение NULL, указывающее на сбой. (Система немедленно вызывает функцию точки входа с DLL_PROCESS_DETACH и выгружает библиотеку DLL.) Возвращаемое значение функции точки входа игнорируется при вызове функции по любой другой причине.