20th Chapter DLL Advanced Technology (1)

Source: Internet
Author: User

20.1 DLL explicit loading and symbolic linking of modules

20.1.1 explicitly loading DLL modules

(1) When building a DLL, if at least one function/variable is exported, the linker generates a. lib file at the same time, but the file is only used when the DLL is implicitly linked (the file is not used when the link is displayed)

(2) function of explicitly loading DLL: LoadLibrary (Ex)

Parameters

Meaning

Pctstr Pszdllpathname

LoadLibrary only this parameter. The function locates the DLL file in the user's computer according to the search algorithm described in chapter 19th and maps to the address space of the process.

HANDLE hfile

This parameter is reserved for future expansions and must be null here

DWORD DwFlags

can be a combination of 0 or the following flags

①dont_resolve_dll_references: Only map the DLL to the process address space. But not calling the DllMain function and not checking other extra DLLs in the DLL import segment, this also means that additional DLLs are not loaded automatically. (You should generally avoid using this flag because the DLL on which your code depends may not have been loaded!)

②load_library_as_datafile: Maps a DLL to a process as a data file. (This flag is typically used when a DLL contains only resources and no functions, or when you want to use a resource contained in an EXE file, and you must use this flag when loading an EXE )

③load_library_as_datafile_exclusive: Similar to the ② flag, the only difference is that the DLL file is opened exclusively to prevent other programs from modifying it.

④load_library_as_image_resource: Similar to the ② flag, but differs in that the relative virtual address (RVA) is repaired when the system loads the DLL. This allows the RVA to be used directly, without having to convert from the memory address loaded by the DLL. (This flag is particularly useful when you need to traverse a DLL to its PE segment)

⑤load_ignore_code_authz_level: Used to turn off UAC to control the privileges that code can have during execution.

⑥load_with_altered_search_path: The search algorithm used to change LoadLibrary to locate the DLL file.

 a, if Pszdllpathname does not contain the "\" character, uses the standard search path algorithm

 b, if Pszdllpathname contains "\" depending on the full path (network share path) or relative path. (see textbook P557)

 c, you can call setdlldirectory to change the search algorithm to search the specified directory path. (The specific order is: exe directory →setdlldirectory set folder →windows system directory → 16-bit Windows system directory →windows directory →path the directory listed.

return value

The hmodule type, equivalent to HInstance, represents the virtual memory address to which the DLL is mapped. When NULL is returned, indicating that the mapping failed and can be further called GetLastError

(3) Mixed LoadLibrary and LoadLibraryEx loading of the same DLL can cause problems

Scenario 1: There is no problem at this time Hdll1=hdll2=hdll3

Hmodule hDll1 = LoadLibrary (Text ("MyLibrary.dll"= LoadLibraryEx (text ("  MyLibrary.dll"= LoadLibraryEx (TEXT ("MyLibrary.dll" ), null,load_library_as_datafile);

"Scenario 2": Change the order of the above call, then Hdll1≠hdll2≠hdll3, indicating that the DLL is mapped to the address space of the process multiple times.

Hmodule hDll1 = LoadLibraryEx (Text ("MyLibrary.dll"= LoadLibraryEx (text ("  MyLibrary.dll"= LoadLibrary (TEXT ("MyLibrary.dll" ));

"Analysis Reason" when LoadLibraryEx (using Load_library_as_datafile, load_library_as_datafile_exclusive, or Load_library_as_ Image_resource flag), the system detects if the DLL is LoadLibrary (or not using the above flag LoadLibraryEx), and if it has been loaded, then the function returns the address in the space where the DLL was originally mapped. If the DLL is not loaded, the DLL will load the DLL, but it will be considered an incomplete loaded DLL, and if it is then loaded again, it will be mapped to the address space of the process multiple times, resulting in a different address.

20.1.2 explicitly unloading DLL modules

(1) BOOL FreeLibrary (hmodule hinstdll);

(2) VOID freelibraryandexitthread (Hinstdll,dwexitcode);

internal implementation of the ① function (in Kernel32.dll):

VOID freelibraryandexitthread (hmodule hinstdll,dword dwexitcode) {     freelibrary (hinstdll);     ExitThread (Dwexitcode); // Call the line directive at Kernel32.dll}

Why do I need the Freelibraryandexitthread function?

A, if you create a thread in a DLL, when the thread has done some work, call FreeLibrary ExitThread to undo the mapping of the DLL and terminate the thread, there will be a serious problem. Because FreeLibrary immediately revokes the DLL mapping from the address space of the process. When FreeLibrary returns, the thread tries to call ExitThread, and this line of code is in the DLL, and the DLL does not exist, and the thread tries to execute the non-existent code, which throws an access violation and causes the entire process to be terminated.

B, but if you call Freelibraryandexitthread, FreeLibrary and ExitThread are called inside of the function, and the two functions are called inside the Kernel32.dll (not the a DLL). So when a DLL is revoked, the thread can continue to execute exitthread, except that the thread no longer returns a DLL when ExitThread, so there is no error.

(3) Usage count of DLLs

① when LoadLibrary (EX) is incremented using count, the first load uses a count of 1. If a thread in the same process calls LoadLibrary again, the system does not map again but increments the usage count.

②freelibrary or Freelibraryandexitthread decrements the count, but decrements the count to 0 o'clock, and the system revokes the map from the process's address space.

The ③ system maintains a usage count for each DLL for each process . If both processes A and B are loaded with MyLib.dll, the DLL is mapped into the address space of two processes, but the usage count of the DLL in processes A and B is 1. if a thread of process B later LoadLibrary the DLL again, the usage count for this DLL in process B is 2, but still 1 in process a.

(4) Two functions for detecting DLLs

① detects if the DLL is mapped: hmodule getmodulehandle (Pctstr pszmodulename);

A, returns NULL when the representation is not mapped.

B, if a null argument is passed, the handle of the EXE file of the application is returned.

② gets the full path name of the Dll/exe: GetModuleFileName (Hinstmodule,pszpathname,cchpath), where Hinstmodule is a handle to the DLL or EXE.

20.1.3 Show link to export symbol-- get function Address: GetProcAddress

Parameters

Describe

Hmodule hinstDLL

The handle to the DLL, which is the return value when you previously called LoadLibrary (Ex) or GetModuleHandle.

Pcstr Pszsymbolname

The name or ordinal of the function, note that the type here is Pcstr, not pctstr, which means that the function accepts only ANSI strings.

return value

Farproc, the address of the function to be obtained, must be converted to the pointer of the function prototype. A typedef is typically used to declare a pointer to a function prototype to get

20.2 DLL the entry point function

BOOL WINAPI DllMain (hinstance hinstDLL, DWORD fdwreason, PVOID fimpload) {Switch(Fdwreason) { CaseDll_process_attach://DLL is mapped to the address space of the process for the 1th time          Break;  CaseDll_thread_attach://when you create a thread          Break;  CaseDll_thread_detach://when a thread terminates          Break;  CaseDll_process_detach://when a process revokes a DLL mapping          Break; }   return(TRUE);//This return value is useful only for Dll_process_attach notifications, which indicates whether the initialization of the DLL was successful, and if return false indicates that the DLL failed to load, if the system terminates the entire process or revokes a mapping of the DLL. Other notifications, the system ignores this return value. }

20.2.1 Dll_process_attach Notice

(1) the notification is sent only if the DLL is mapped to the process address space for the 1th time . If later a thread calls LoadLibrary (EX) to load the DLL, only the usage count of the DLL is incremented , but the notification is not sent again.

(2) In this notification, it is generally used to perform process-related initialization, such as creating a heap to be used by a generic function in a DLL.

(3) When DllMain handles Dll_process_attach notifications, the return value is used to indicate whether the initialization of the DLL was successful. If return false indicates that the DLL failed to load, the system terminates the entire process (which occurs when the process was just created) or revokes the mapping of the DLL (this happens when you explicitly call LoadLibrary (EX)).

(4) This notification is called by a thread in the process . called by the main thread if a new process has just been created . If a thread calls LoadLibrary to explicitly load the DLL for the 1th time , it is called by this thread to execute the notification, and then the thread continues to perform other tasks normally, if return False indicates that the initialization failed, and the system will undo the mapping of the DLL and let LoadLibrary (EX) return null.

20.2.2 Dll_process_detach Notice

(1) When the system revokes a DLL from the process's address space, the notification is sent. (Note: If you return false when processing Dll_process_attach , you will not receive a dll_process_DETACH notification.) )

(2) If you return false when processing Dll_process_attach, DllMain will not receive a DLL_PROCESS_DETACH notification.

(3) If the DLL mapping is caused by calling ExitProcess , the thread calling the ExitProcess function will be responsible for executing the code of the DllMain function .

(4) If the DLL map is revoked because the thread called FreeLibrary(or Freelibraryandexitthread), the thread executes the code in the DllMain function . The thread will not return from FreeLibrary until it finishes processing Dll_process_detach. Therefore, if the notification is looped, the termination of the thread is blocked, and the process is actually terminated by the operating system only after each DLL has finished processing the notification.

(5) If a thread calls TerminateProcess to terminate the process, the system does not send a Dll_porcess_detach notification . This means that the DLL does not have the opportunity to perform some cleanup of the code. Therefore, you should avoid using the TerminateProcess function when you are not allowed to do so.

20.2.3 Dll_thread_attach Notice

(1) When a process creates a thread, the system sends Dll_thread_attach notifications to all DLLs currently mapped to that process's address space. Tell these DLLs to perform some thread-related initialization. The newly created thread is responsible for executing the relevant code in the DllMain function in all DLLs. The new thread will start executing its thread function only after all DLLs have finished processing the notification.

(2) When a new DLL is mapped to the process address space, threads in the process will not receive dll_thread_attach notifications. ( that is, only DLLs that are mapped to the process address space will receive this notification when a new thread is created )

(3) because the process is created, he ren is mapped to the DLL in the process address space will receive DLL_PROCESS_ATTACH notification, and the main thread is responsible for execution, here can do some related initialization work, so the system will not let the main thread with Dll_thread_ Attach calls the DllMain function ( that is, the main thread receives only Dll_process_attach notifications without receiving Dll_thread_attach notifications ).

20.2.4 Dll_thread_detach Notice

(1) When the thread function returns, the system calls ExitThread to terminate the thread, but before terminating, the thread uses Dll_thread_detach to invoke the DllMain function of all mapped DLLs . Tells the DLL to perform thread-related cleanup operations, such as a block of data for multithreaded applications, which the C + + runtime can release here.

(2) If there is a dead loop in the notification, it will prevent the thread from terminating. The operating system does not actually terminate the thread until each DLL has finished processing the Dll_thread_detach notification.

(3) If a thread calls TerminateThread to terminate the thread, the system will not send a DLL_THREAD_DETACH notification to the thread. This means that the DLL does not have the opportunity to perform any cleanup operations.

(4) If there are other threads (running) When you revoke a DLL mapping, the system does not send Dll_thread_detach to those threads. (That is, these threads do not use Dll_thread_detach to invoke the DLL's DllMain)

"Note" The above rule may occur when a thread in a process calls LoadLibrary to load a DLL, the system uses Dll_process_attach to invoke the DLL's DllMain (but the thread does not get Dll_thread_ Attach notification). Next, the thread that loads the DLL exits, and the thread receives a DLL_THREAD_DETACH notification. For this reason, extreme care must be taken when conducting thread-related cleanup. A generic call to LoadLibrary with a thread calling FreeLibrary should be the same thread.

20.2.5 DllMain the serialized call

(1) The system will serialize calls to the DLL's DllMain function. When the process is created, a lock is created at the same time (critical segment, different processes will not share this lock, this is the key section of the feature!) )

(2) When a thread in a process calls the DllMain of a DLL that is already mapped, the lock is used to synchronize each thread.

(3) The method of preventing the system from sending Dll_thread_attach and Dll_thread_detach to a DLL

BOOL Disablethreadlibrarycall (Hmoudle hinstdll);//Can be written in Dll_process_attach notification

"DllMain Error Call" demonstrates deadlock problems caused by DllMain serialization calls

BOOL WINAPI DllMain (hinstance hinstDLL, DWORD fdwreason,pvoid fimpload) {HANDLE hthread;    DWORD dwThreadID; Switch(Fdwreason) { CaseDll_process_attach://DLL is mapped to the process address space//Creating ThreadsHthread = CreateThread (NULL,0, SomeFunction, NULL,0, &dwThreadID); //suspend our thread (that is, the thread that calls the LoadLibrary function, set to a) until the new thread endsWaitForSingleObject (Hthread, INFINITE);//wait for new thread to end//Note//1. When the new thread (set to B) is created, the system will let the B thread use Dll_thread_attach to invoke all the mappings//to the DLL of the process (including the DllMain of this DLL), when executing this DllMain, because the system will use the critical segment to synchronize each//The thread calls the DllMain (that is, the serialization of the DllMain Call), and the new thread B is suspended to wait for the a thread to finish executing//DllMain, but the a thread at this point hangs to wait for the B thread to execute because it calls WaitForSingleObject.//this creates a "deadlock". //2, even in this DLL call Disablethreadlibrarycall to prohibit the thread execution in this DLL//This deadlock can also occur with Dll_thread_attach. Because when you call the CreateThread function, the inside of this function//The WaitForSingleObject is called and passed into this critical segment of the process, only if the new thread has this critical segment//only use Dll_thread_attach to invoke the DllMain function in each DLL. So when createthread a new thread//This new thread hangs because it cannot get a critical segment (because it is owned by a thread). But the a thread executes the line to waitfor*.//the code will hang itself, so it will still cause a deadlock. //new threads are no longer neededCloseHandle (hthread);  Break;  CaseDll_thread_attach://when a thread is created         Break;  CaseDll_thread_detach://when a thread exits         Break;  CaseDll_process_detach://When you undo a DLL mapping         Break; }    returnTRUE;}

20th Chapter DLL Advanced Technology (1)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.