天天看點

DLL的入口點函數

一、基本介紹

系統在不同的時候調用這個入口點函數,這些調用是通知性質的,

用來執行一些與程序或者線程有關的清理工作。如果DLL需要這些通知,則需要在源代碼

中實作這個入口點函數。

注意函數名區分大小寫 DllMain

函數原型

BOOL WINAPI DllMain(
In HINSTANCE hinstDLL,
In DWORD fdwReason,
In LPVOID lpvReserved
 );hinstDLL 是包含這個DLL執行個體的句柄
 fdwReason 調用函數入口點的原因,後面詳細介紹
 lpvReserved:為零表示隐式載入,不為零表示顯示載入      

注意:

為了避免産生循環依賴,Dllmain中,避免調用從其他dll中導入的函數,以及LoadLibrary(Ex),和Freelibrary

套接字函數,COM、ODBC等

另外,如果建立全局或者靜态C++對象,也會存在同樣的問題,因為這些對象的構造函數和析構函數也會被調用

二、相關參數

1、DLL_PROCESS_ATTACH 通知

當系統第一次将一個DLL映射到程序的位址空間中的時候,會調用DllMain,并且傳入1、DLL_PROCESS_ATTACH,

之後線程再調用LoadLibrary的時候,隻是遞增這個DLL的引用計數,不會再傳入DLL_PROCESS_ATTACH來調用DllMain函數

DLL處理DLL_PROCESS_ATTACH的時候,根據需要進行初始化

關于傳回值,如果傳入參數是(DLL_THREAD_ATTACH或者DLL_THREAD_DETACH)的時候,系統将忽略DllMain傳回值

關于程式調用,如果隐式調用失敗,系統直接無法啟動

在顯示調用中,如果DLLMain函數傳回為false,也就是初始化不成功,系統會從程序位址空間中撤銷對DLL的映射,并讓LoadLibrary傳回NULL

2、DLL_PROCESS_DETACH 通知

當系統将一個DLL從程序的位址空間中撤銷映射時,會調用DLL的DLLMain函數,并傳入參數DLL_PROCESS_DETACH 。

DLL處理這個通知的時候,應該執行與程序相關的清理工作,比如調用HeapDestory來銷毀堆。

撤銷映射有兩種方式,1、程序終止,2、某個線程調用了FreeLibrary或者FreeLibraryAndExitThread,如果調用的FreeLibrary,那麼在

DLLMain處理完 DLL_PROCESS_DETACH通知之前,線程不會從調用中傳回

需要注意的時候,DLL可能會阻礙程序的終止,當DLLMain收到DLL_PROCESS_DETACH通知的時候,隻有每個DLL都處理完DLL_PROCESS_DETACH

的通知之後,作業系統才會真正地終止程序