您的位置:首页 > 其它

Windows DLL搜索顺序

2015-11-28 15:14 447 查看
原文:http://m.blog.csdn.net/blog/SR0ad/8180019

Windows程序直接或间接通过LoadLibrary/LoadLibraryEx加载一个DLL时,Windows会按照一定的顺序去系统中搜索指定的DLL,这个顺序称之为DLL搜索顺序。

下面举例A.exe调用B.dll的情况:

一、系统环境影响

1.如果在LoadLibrary/LoadLibraryEx调用时B.dll被指定了路径而该路径下并不存在B.dll,LoadLibrary/LoadLibraryEx会直接失败。

2.如果B.dll这个模块已经存在于内存中,系统只作manifest检查和redirection检查,而不管指定的B.dll路径是否与内存中的B.dll一致,并且系统不会再试图搜索B.dll。

3.KnownDlls,注册表中的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs 登记了所谓KnownDlls的名称和它们的路径。如果B.dll存在于该键下,系统会加载该注册表项指定路径的B.dll,而不管它在LoadLibrary/LoadLiraryEx被指定的路径。

4.如果被加载的B.dll依赖于其他的DLL,这些被依赖的DLL会按照B.dll没有指定路径时的相同方式加载。(假如B.dll依赖于它相同目录下的DepDll.dll,搜索DepDll.dll时并不会从B.dll所在目录开始)

二、标准的DLL搜索顺序

不附加任何其他条件时,标准的DLL搜索顺序如下:

1.应用程序的加载目录:D:\SR0ad

2.当前目录(默认为程序加载目录,可以通过SetCurrentDirectory修改,通过GetCurrentDirectory获取)

3.系统目录(32位系统下通常是,C:\Windows\System32,可以通过GetSystemDirectory获取)

4.16位系统目录(忽略)

5.Windows目录(通常是,C:\Windows,可以通过GetWindowsDirectory获取)

6.PATH环境变量中列出的所有路径

三、DLL重定向

DLL重定向用来解决系统中存在并且同时需要同一个DLL的多个版本的问题。当系统中已经存在B.dll,而A需要自己的B.dll时,就要用到DLL重定向。

在应用程序安装目录下建立应用程序名+.local后缀的重定向文件D:\SR0ad\A.exe.local,B.dll必须安装在D:\SR0ad\目录下。

不管重定向文件A.exe.local的内容如何,使用LoadLibrary/LoadLibraryEx加载B.dll时,只要D:\SR0ad\B.dll存在,系统都会加载D:\SR0ad\B.dll,而不管LoadLibrary/LoadLibraryEx是否为它指定全路径。

如果A.exe.local是个目录,并且D:\SR0ad\A.exe.local\B.dll存在,系统则会加载D:\SR0ad\A.exe.local\B.dll,同样不管为LoadLibrary/LoadLibraryEx是否为它指定全路径。

PS:DLL重定向有两个例外,KnownDLLs不能被重定向;如果应用程序存在manifest,.local文件会被忽略。

参考文章:Dynamic-Link Library Search Order,http://msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx

下面通过一个例子,来测试一下Win7下,具体的搜索路径是什么。

#include <Windows.h>
#include <iostream>
using namespace std;

BOOL APIENTRY DllMain(HMODULE hModule,
DWORD  ul_reason_for_call,
LPVOID lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:

char szDllPath[MAX_PATH] = {0};
GetModuleFileNameA(hModule, szDllPath, MAX_PATH);
cout<<"DLL PATH:"<<szDllPath<<endl;
break;
}

return TRUE;
}
dll会获得自身的路径并输出,然后将dll放在各各路径,之后运行exe,通过LoadLibrary("SR0adDLL.dll");加载便可看到dll处于什么路径下。

#include <Windows.h>
#include <iostream>
using namespace std;

int main()
{
HMODULE hDll = LoadLibrary("SR0adDLL.dll");
if (!hDll)
{
cout<<"SR0adDLL.dll Load Error\n"<<endl;
}
return 0;
}




分别在一下路径放了生成的dll文件,之后运行exe,显示那个dll路径,删除掉继续运行,直至找不到dll文件为止。



至此也算是验证了搜索路径,至于安全搜索模式,就当忽略吧。

更多参考:http://blog.csdn.net/magictong/article/details/6931520

海风月影:神奇的马甲dll
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  windows