Like an executable file, a dynamic-link library has its own entry address, which automatically jumps to that address using 3 specific stack parameters when the system or a thread of the current process calls the LoadLibrary function to load or uses FreeLibrary to unload the dynamic link library. The entry function is intended to complete the initialization and aftercare of dynamic link library code, such as the release of resources after unloading.
These three parameters have a special meaning.
BOOL Apientry DllMain (
Hmodule hmodule,
DWORD Ul_reason_for_call,
LPVOID lpreserved
)
The first argument is the instance handle, the so-called handle is actually the image address of the loading process in memory, and note that the process handle and the module handle of the dynamic link library are not the same. For example, if a user wants to use hmodule to load a bitmap resource in the dynamic link library, it will never get results. The module handle of the dynamic link library is attached to the loading process, and the detached process is independent of the dynamic link library in the system space and is meaningless. A dynamic-link library is always loaded into an address in the process, which is the module handle of the dynamic-link library, which differs from the process instance handle, which is an offset from the process ingress address, and can only be addressed to various windows or other resources nested within the dynamic-link library through a module handle.
The Ul_reason_for_call parameter indicates the condition under which the dynamic link library was loaded, that is, the reason for the load. When the user explicitly loads a dynamic-link library with the LoadLibrary (Ex) function, or the library is implicitly loaded by the process itself, the entry function is called, and the entry parameter ul_reason_for_call is equal to Dll_process_attach. The return value of the entry function is the return value of the LoadLibrary function, which is passed through the EAX register. According to the description of the LoadLibrary (Ex) function, this function returns a null value indicating that the load failed. In fact, in the DllMain function, a null value is returned whenever the false,loadlibrary (Ex) function is returned. If the dynamic-link library requires an exclusive call, you can judge the file name of the loading process in the entry point function, or perform other checks of legality, and return false directly in the DllMain function if you do not want to be called by a process. Dll_process_attach branches are often used to implement system initialization, such as establishing database links, creating hook functions, allocating system resources, and saving ingress process instance handles.
Similarly, when a process no longer uses the dynamic-link library, such as calling the ExitProcess function or explicitly invoking the FreeLibrary function, the system uses the Dll_process_detach parameter to perform the related branch. Used to release system resources, disconnect database links, unload hook functions, close files, free memory, and more.
Note: The execution of the Dll_process_detach branch is conditional, the process terminates unexpectedly, and the Dll_process_detach branch statement is not executed, so that the cleanup statements such as closing resources, breaking links, closing files, etc. in the branch cannot be executed. This will result in some potential loss of data. Therefore, do not use the TerminateProcess function to terminate the execution of a process unless it is a last resort.
If the DLL finishes mapping to process space when the thread is created, the system uses Dll_thread_attach to enter the entry point. The Dll_thread_detach branch is executed when the system executes the ExitThread function. The same rules apply to threads, and users do not easily use the TerminateThread function, which can also lead to unpredictable memory leaks or resource releases and data loss.
If users do not care about Dll_thread_detach and Dll_thread_attach notifications and want to improve the performance of creating and revoking threads, you can receive Dll_thread_attach notifications when Call the DisableThreadLibraryCalls function.
Note: In relation to the lpreserved parameter----The two cases are different when static (implicit) loading and the invocation of the Loadlibray function to dynamically (explicitly) load the dynamic library, the value is 0 when dynamically loaded. If the user wants to write the dynamic link library can only be loaded dynamically or can only be statically loaded, can be determined by this parameter to achieve.
code example:
Dllmain.cpp (Generate MyDLL.DLL):
//dllmain.cpp: Defines the entry point for the DLL application. #include"stdafx.h"#include<stdio.h>#include<Psapi.h>#include<Windows.h>typedefvoid(*PFNPTR) (Char*); BOOL apientry DllMain (hmodule hmodule, DWORD ul_reason_for_call, LPVOID lpre Served) {CharSzname[max_path]; if(Lpreserved! =0) { //only allow dynamic loading, static loading will prompt the error and exitMessageBox (NULL,"allow dynamic loading only","Sorry", MB_OK); returnFALSE; } getmodulebasename (GetCurrentProcess (), NULL, Szname,max_path);//gets the base name of the current main process Switch(ul_reason_for_call) { CaseDll_process_attach://deliberately changing the name of the calling process to Test.exe, the dynamic link library will fail to load. if(strcmp (SzName,"Test.exe") ==0) returnFALSE; CaseDll_thread_attach: CaseDll_thread_detach: CaseDll_process_detach: Break; } returnTRUE;}extern "C"{ //The keynote process calls the function, which then calls the Exefn function of the keynote process_declspec (dllexport)intFnimportingdll () {MessageBox (NULL,"Dll Function called!","Mydll", MB_OK); PFNPTR fn= (pfnptr):: GetProcAddress (GetModuleHandle (NULL),"Exefn"); if(FN) fn ("dream back to the trumpet and even camp"); Else{MessageBox (NULL,"It did not work:","From DLL", MB_OK); return-1; } }}
Main.cpp (Generate Console.exe):
#include <iostream>#include<Windows.h>#define_dynamic_#ifndef _dynamic_#pragmaComment (lib, "Mydll.lib")//Static Loadingextern "C"_declspec (dllexport)intFnimportingdll ();#endiftypedefint(*Pfnimportingdll) ();using namespacestd;intMainintargcChar*argv[]) {#ifdef _DYNAMIC_//Dynamic LoadingPfnimportingdll Fnimportingdll =NULL; Hmodule hmodule=::loadlibrary ("MyDLL.DLL"); if(Hmodule = =NULL) {cout<<"Unable to load MyDLL.DLL"<<Endl; return-1; } Fnimportingdll= (Pfnimportingdll) GetProcAddress (hmodule,"Fnimportingdll"); if(Fnimportingdll = =NULL) {cout<<"the Fnimportingdll function could not be found"<<Endl; return-2; }#endifcout<<"I ' m going...\n"; Fnimportingdll (); cout<<"Game over\n"; #ifdef _dynamic_:: FreeLibrary (hmodule);#endif return 0;}extern "C"{ //The function will have a function in the dynamic-link library to invoke the_declspec (dllexport)voidExefn (Char*lpszmessage) {MessageBox (NULL, Lpszmessage,"From Exe", MB_OK); }}
Place the generated Console.exe file and the MyDLL.DLL file in the same folder
Commenting out the _DYNAMIC_ macro loads the MyDLL.DLL statically, so that the popup dialog prompts can only be loaded dynamically, because lpreserved values are checked and judged in DllMain.
Changing the name of Console.exe to Test.exe and then running Test.exe in CMD will show that MyDLL.DLL cannot be loaded.
Windows API Programming-----DLL Programming prohibit loading yourself