70,039
社区成员
发帖
与我相关
我的任务
分享
1、应用程序自己使用了DLL redirection(.loacl文件)或者使用了manifest文件控制dll载入目录
2、应用程序已经载入了一个同名dll模块,不论它的路径在哪,都不会再继续搜索dll(载入是指已在程序的虚拟空间中)
3、dll是已知dll,或者任何已知dll的依赖dll(所谓已知dll在注册表中列出:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.)
当不满足上面的条件时,应用程序才会按照标准搜索顺序搜索dll:
搜索顺序分两种,取决于安全搜索模式是否开启(默认开启,可通过注册表关闭或通过调用 SetDllDirectory关闭)。
如果安全搜索模式开启,则顺序如下:
1、应用程序所在目录
2、系统目录.
3、16位系统目录.
4、Windows目录.
5、当前目录.
6、环境变量PATH指定的目录
如果安全搜索模式关闭,则顺序如下:
1、应用程序所在目录
2、当前目录.
3、系统目录.
4、16位系统目录.
5、Windows目录.
6、环境变量PATH指定的目录
另外还有高级搜索模式,通过使用LOAD_WITH_ALTERED_SEARCH_PATH调用 LoadLibraryEx开启,具体自己去看上面其他人发的那个链接吧。
注意!上面的规则都是以一个应用程序实例的视角来说的,不用应用程序实例是互不影响的,所以你说的:
这个问题的答案,对你想知道的结果来说,没有任何意义。不管系统是否会重复载入同一个dll到物理内存,都能满足上面所说的一个应用程序实例看到的规则。
说白了,就是因为你不知道已知DLL(known DLL)的概念,导致你想的太多了。。
最后给你捋一下,对于同一个应用程序实例来说!!!
错!! 只判断名字!!
对!!known DLL
真的非常感谢!


麻烦您了!!!
前面关于LoadLibrary那个,是我将调用LoadLibrary后直到它返回期间的行为统称为LoadLibrary的行为,其实应该也可以这样看吧,总得有代码去判断。
我说的这个判断是指对于已经加载到物理内存(加载后到未从物理内存释放期间,包含了换出到硬盘)后,如果已经加载到物理内存,判断到这一行为后,直接将其映射到进程的虚拟空间,而不是再去加载
你们都说判断DLL是根据全路径的,但我测试过程中发现一些奇怪的事
首先我要确定加载目录先于system32,除了通过微软的文档,也将两个同名不同内容的DLL放到system32和程序同目录,根据DllMain的输出可以确定,优先加载的是程序所在目录的DLL
确定了这点后,将程序所在目录的DLL命名为gdi32.dll,写如下代码
HMODULE h0 = GetModuleHandleA( "gdi32.dll" );
printf("h0=%p\n", h0 );
HMODULE h1 = LoadLibrary( "gdi32.dll" );
printf("h=%p\n", h1 );
前两行通过输出可以肯定没有加载gdi32.dll,第三行加载gdi32.dll的时候,没有输出预先设置在DllMain中的字符串,说明此时加载的是system32下的gdi32.dll,而不是程序所在目录自定义的gdi32.dll。(为确保自己的gdi32.dll有正确的输出行为,加载时指定.\\gdi32.dll,能得到预期的结果)
这里就有问题了,它并没有按我期望的加载当前目录的DLL
我推测是内存中已经加载过gdi32.dll了,因为出现同名DLL,所以直接映射过来了,这个行为看起来还是根据文件名来的
但又做了测试,结果又不同
程序A加载A.dll不退出,程序B和它是不同文件夹,它也加载一个不同内容的A.dll,根据输出来看,最终加载的是程序B同目录的A.dll
程序A的A.dll仍在内存中,说明这里又没完全根据名称来,而是确实做了搜索工作的
这么说的话,是官方的DLL有特殊性?
其实最开始的问题主要是想知道,当物理内存中已经有一个同名DLL时,此时加载该名称的DLL是重新找还是直接映射到虚拟内存。
现在根据你们的解惑,算上完整路径的话,当找到的DLL和物理内存中的DLL的完整路径相同(即同一文件),那么直接从物理内存中映射过来;
如果找到的DLL和内存中同文件名的DLL(一个或多个)的路径不同,那么还是会将其加载到物理内存,并映射到当前程序的虚拟内存中
是这样的吧?我是这样理解的。
只不过,刚刚的gdi32.dll的测试并不完全符合这一行为。
