我有特殊要求,我相信别无他法,
即:检测DLL的卸载。我用Google搜索并发现了
a four-years old SO关于此事。我选择了同样的
解决方案:挂钩FreeLibrary
。
当代码进入MyFreeLibrary
时,我将挂钩入口点
指定的模块以相同的方式(内联挂钩)。并在
MyEntryPoint
,我将首先调用原始入口点
检查reason
参数 - 如果值等于
DLL_PROCESS_DETACH
,这意味着此DLL的清理工作是
刚刚完成,它将从地址空间中卸载。
在这一点上,我有机会完成我的工作。它有效。
这就是它?不幸的是,它还没有完成。非常重要 事情被忽视了:依赖。
例如,a.dll
与b.dll
和c.dll
相关联。当你加载
a.dll
,b.dll
和c.dll
将首先加载(初始化)。这个
是因为b.dll
和c.dll
列在导入表中
a.dll
,它们是a.dll
的依赖项。同样,当你卸载
a.dll
,b.dll
和c.dll
也可以在他们的参考时卸载
计数减少到零。我不知道有关如何的细节
loader找出DLL的依赖关系并卸载它们
FreeLibrary
的{{3}}页面没有谈到这一点,我很高兴
明白这一点,但我找不到这些信息。
所以主要问题是如何检测依赖项的卸载 一个DLL模块。我希望有同样的机会完成我的工作。
可能的解决方案可能是导入表,找出答案 DLL从其导入表中依赖,并找出 依赖项与其导入表的依赖关系等, 找出所有的依赖关系,钩住所有的入口点,我没有 知道,这听起来很疯狂,我在这里需要一些建议。
答案 0 :(得分:1)
我为旧的SO问题提供了答案。你现在写:
在MyEntryPoint中,我将首先调用原始入口点,然后检查reason参数 - 如果值等于DLL_PROCESS_DETACH,则表示此DLL的清理工作刚刚完成,并且将从中卸载地址空间。
你发现这不是真的。但最简单的解决办法是什么?如果你发现原因是DLL_PROCESS_DETACH后,你测试hModule是否仍然有效怎么办?参见:
How can I tell if a Windows module handle is still valid?
您可以跳过挂钩DLL入口点,不检查DLL_PROCESS_DETACH并始终只测试hModule是否仍然有效。这让我意识到,最好在调用原始FreeLibrary之前检查hModule是否有效,然后测试有效到无效的转换:
[esp+28]
我希望这会有所帮助。