Функция 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.) Возвращаемое значение функции точки входа игнорируется при вызове функции по любой другой причине.