《Windows Via C/C++》读书笔记之dll加载时刻
一、静态加载
1、loader启动exe程序时,扫描exe的import section,加载DLL
2、exe程序退出时,卸载dll
dll加载与卸载由系统控制,生命期横贯进程。
二、动态加载
1、调用LoadLibrary()/LoadLibraryEx加载
2、FreeLibrary()卸载
dll加载卸载由程序员控制,在当前进程的生命期由Load开始,Free结束。
三、钩子DLL加载
1、调用SetWindowsHookEx()设置WH_GETMESSAGE消息钩子
2、调用UnhookWindowsHookEx()卸载消息钩子
*** 调用SetWindowsHookEx()设置WH_GETMESSAGE消息钩子
Hooks的过程:
1、进程B的线程准备派送消息
2、system检查该线程是否安装了WH_GETMESSAGE钩子
3、system检查包含GetMsgProc()的DLL是否映射到了进程B的进程空间
4、如果DLL没有被映射,system加载该DLL,并增加进程B该DLL的引用计数(DLL引用计数是每个进程都维护一个)
5、system检查该DLL的hInstDll是否与进程B加载的一致,如果是则直接调用进程A地址空间上的GetMsgProc(),如果不是,则计算偏移,在进程B的地址空间调用GetMsgProc()
6、system增加进程B中该DLL的引用计数(增加的原因见后面描述)
7、system调用进程B地址空间的GetMsgProc()
8、GetMsgProc()返回后,system减小进程B中该DLL的引用计数
*** 调用UnhookWindowsHookEx()卸载消息钩子
UnhookWindowsHookEx()会对已安装钩子进程中的DLL引用计数减一。当引用计数为0时,DLL会被自动卸载。
注意:在进入GetMsgProc()之前,DLL引用计数会加1,退出之后会减1。这样做的目的是避免内存访问异常。试想一下,在执行GetMsgProc()时,有其他线程调用了Unhook,如果在GetMsgProc()之前没有对引用计数加1,Unhook减小了引用计数,导致DLL卸载。这是GetMsgProc()就会访问已经unmap的内存,导致异常。
钩子DLL由程序员告诉系统某些信息,在系统派送消息时,DLL才被真正加载到当前进程,生命期才开始。