Функция DllMain


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

DllMain - имя - заместитель для определяемого библиотекой имени функции. Вы должны задать действительное имя, которое используете, когда формируйте вашу DLL. Дополнительную информацию, см. в документации, включенной в ваши инструментальные средства разработки.

Синтаксис

BOOL WINAPI DllMain(
  HINSTANCE hinstDLL,  // дескриптор модуля DLL
  DWORD fdwReason,     // причина вызова функции
  LPVOID lpvReserved   // зарезервированный
);

Параметры

hinstDLL

[in] Дескриптор модуля DLL. Это значение - базовый адрес DLL. HINSTANCE DLL является  тем же самым что и HMODULE DLL, так что hinstDLL может использоваться при вызове функции, которые требуют дескриптора модуля.

fdwReason

[in] Указывает, почему DLL вызывает функцию точки входа. Этим параметром может быть одно из ниже перечисленных значений.

 

Значение Предназначение
DLL_PROCESS_ATTACH DLL загружается в виртуальное адресное пространство текущего процесса в результате операции запуска или в результате вызова LoadLibrary. DLLs могут использовать эту возможность, чтобы инициализировать любые данные экземпляра или использовать функцию TlsAlloc, чтобы назначить индекс локальной памяти потока (TLS).
DLL_THREAD_ATTACH Текущий процесс создает новый поток. Когда это происходит, система вызывает функцию точки входа всех DLLs, в текущий момент связанных с процессом. Вызов делается в контексте нового потока. DLLs могут использовать эту возможность, чтобы инициализировать область памяти, занимаемую страницей  TLS для потока. Поток, вызывающий  функцию точки входа в DLL с DLL_PROCESS_ATTACH не вызывает функцию точки входа в DLL  с  флажком DLL_THREAD_ATTACH.
Обратите внимание! на то,  что функция точки входа  в DLL вызывается с этим значением только созданными потоками после того, как DLL загружена процессом. Когда DLL загружается, используя LoadLibrary, существующие потоки не вызывают функцию точки входа недавно загруженной DLL.
DLL_THREAD_DETACH Поток выходит чисто. Если DLL сохранила указатель на распределенную память в слоте TLS, она должна использовать эту возможность, чтобы освободить память. Система вызывает функцию точки входа всех текущих загруженных DLLs  с этим значением. Вызов делается в контексте выхода из потока.
DLL_PROCESS_DETACH DLL выгружается из виртуального адресного пространства вызывающего процесса в результате неудачной загрузки DLL, завершения работы процесса или вызова функции FreeLibrary. DLL может использовать эту возможность, чтобы вызвать функцию TlsFree, чтобы освободить любые индексы TLS, распределенные при помощи использования TlsAlloc и освободить любые данные потока.
Обратите внимание! на то, что поток, который получает уведомление DLL_PROCESS_DETACH - не обязательно тот же самый поток, который получил уведомление DLL_PROCESS_ATTACH.
 

lpvReserved

[in] Если fdwReason - DLL_PROCESS_ATTACH, lpvReserved - ПУСТО (NULL) для динамических загрузок и не ПУСТО (NULL) для статических загрузок.

Если fdwReason - DLL_PROCESS_DETACH, lpvReserved - ПУСТО (NULL), если DllMain вызвалась, используя FreeLibrary и не ПУСТО (NULL), если DllMain вызвалась в ходе завершение работы процесса.

Возвращаемые значения

Когда система вызывает функцию DllMain со значением DLL_PROCESS_ATTACH, функция возвращает значение ИСТИНА (TRUE), если она завершается успешно или ЛОЖЬ (FALSE), если инициализация завершается ошибкой. Если возвращаемое значение - ЛОЖЬ (FALSE), когда вызывается DllMain, потому что процесс использует функцию LoadLibrary, LoadLibrary возвращает ПУСТО (NULL). (Система немедленно вызывает вашу функцию точки входа с DLL_PROCESS_DETACH и выгружает DLL.) Когда DllMain вызывается в ходе инициализации процесса, если возвращаемое значение - ЛОЖЬ (FALSE),  процесс заканчивается с ошибкой. Чтобы получить дополнительную информацию об ошибке, вызовите GetLastError.

Когда система вызывает функцию DllMain с каким-либо значением, а не DLL_PROCESS_ATTACH, возвращаемое значение игнорируется.

Замечания

В ходе запуска начального процесса или после вызова функции LoadLibrary, система просматривает список загружаемых DLLs для процесса. Для каждой DLL, которая еще не не вызвалась со значением DLL_PROCESS_ATTACH, система вызывает функцию точки входа DLL. Этот вызов делается в контексте потока, который заставил  измениться адресное пространство процесса, типа первичного потока процесса или потока, который вызвал LoadLibrary. Доступ к точке входа преобразуется в последовательную форму системой на основании всего процесса.

Есть случаи в которых, функция точки входа вызывается для завершающегося потока, даже если функция точки входа никогда не вызывалась DLL_THREAD_ATTACH для потока:

Когда DLL выгружается из процесса в результате неудачной загрузки DLL, завершение работы процесса или вызова FreeLibrary, система не вызывает функцию точки входа DLL со значением DLL_THREAD_DETACH для отдельных потоков процесса. DLL отправляет только уведомление DLL_PROCESS_DETACH. DLLs могут воспользоваться этой возможностью, чтобы очистить все ресурсы для всех потоков, известных DLL. Однако, если DLL успешно не завершает работу по уведомлению  DLL_PROCESS_ATTACH, она не получает или уведомление DLL_THREAD_DETACH, или DLL_PROCESS_DETACH .

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

Безопасно вызывать другие функции из Kernel32.dll, потому что эта DLL гарантированно будет загружена в адресное пространство процесса, когда вызывается функция точки входа. Это широко употребляется для функции точки входа, которая создает объекты синхронизации такие как критические секции и мьютексы и использует TLS. Не вызывайте функции системного реестра, потому что они расположены в Advapi32.dll. Если Вы динамически связаны с C-библиотекой программ этапа исполнения, не вызывайте malloc; вместо этого, вызовите HeapAlloc.

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

Чтобы предоставить более сложную инициализацию, создайте процедуру инициализации для DLL. Вы можете потребовать, чтобы приложения вызывали эту процедуру инициализации перед вызовом любых других  процедур в DLL. В противном случае, Вы можете иметь процедуру инициализации, которая создает именованный мьютекс и имеет процедуру для каждой DLL, которые вызывают процедуру инициализации, если мьютекс не существует.

Код примера

Пример, см. в статье Функция точки входа динамически-подключаемой библиотеки (DLL).

Смотри также

Обзор Динамически подключаемые библиотеки (DLL), Функции, используемые DLLFreeLibrary, GetModuleFileName, LoadLibrary, TlsAlloc, TlsFree

Размещение и совместимость DllMain

Windows. NET Server

Да

Windows XP

Да

Windows 2000

Да

Windows NT

Да версии 3.1  и выше

Windows Me

Да

Windows 98

Да

Windows 95

Да

Используемая библиотека

-

Заголовочный файл

 

- объявлено в

-

- включено в

-

Unicode

Нет

Замечания по платформе

Не имеется

 

Назад в оглавление
На главную страницу
На оглавление справки

Hosted by uCoz