检测DLL的卸载

我有一个特殊的要求,我相信没有其他办法,那就是:检测DLL的卸载。 我search了一下,发现了一个四年的SO 。 我select了相同的解决scheme:钩免费库。

当代码进入MyFreeLibrary ,我将以同样的方式挂钩指定模块的入口点(内联钩子)。 而在MyEntryPoint ,我将首先调用原始入口点,然后检查reason参数 – 如果值等于DLL_PROCESS_DETACH ,则意味着该DLL的清理工作刚刚完成,并且将从地址空间中卸载。 在这一点上,我有机会做我的工作。 有用。

就是这样了 ? 不幸的是,它还没有完成。 一个非常重要的事情被忽视:依赖。

例如, a.dll链接对b.dllc.dll 。 加载a.dllb.dllc.dll将首先被加载(被初始化)。 这是因为b.dllc.dllc.dll的导入表中a.dll ,它们是a.dll依赖关系。 同样,卸载a.dll ,如果引用计数减less到零, b.dllc.dll也可能会被卸载。 我不知道有关加载程序如何发现DLL的依赖关系并将其卸载的详细信息, FreeLibrary的MSDN页面没有提到这一点,我很高兴明白这一点,但是我没有find信息。

所以主要的问题是如何检测卸载DLL模块的依赖关系。 我想有同样的机会去做我的工作。

一个可能的解决scheme可能是导入表,从它的导入表中找出一个DLL的依赖关系,并从它们的导入表中找出依赖关系的依赖关系,找出所有依赖关系,钩住所有入口点,不知道,这听起来很疯狂,我需要一些build议。

我为旧的SO问题提供了答案。 你现在写:

而在MyEntryPoint中,我将首先调用原始入口点,然后检查原因参数 – 如果值等于DLL_PROCESS_DETACH,则意味着该DLL的清理工作刚刚完成,并且将从地址空间中卸载。

你已经发现这是不正确的。 但最简单的解决方法是什么? 如果在找到原因是DLL_PROCESS_DETACH之后,你会测试hmodulee是否仍然有效? 看到:

如何判断Windows模块句柄是否仍然有效?

您可能可以跳过钩入DLL入口点,而不是检查DLL_PROCESS_DETACH,并且总是测试hmodulee是否仍然有效。 这让我意识到,最好在调用原始FreeLibrary之前检查hmodulee是否有效,然后再测试一个有效的无效转换:

 if (moduleWasValid && !moduleStillValid) { // process module unloaded } 

我希望这有帮助。