为何LoadLibrary()与延迟加载DLL采用不同的DLL搜索路径?
延迟导入DLL时路径计算错误触发ERROR_PROC_NOT_FOUND的原因
当前工作目录发生变化
LoadLibrary调用时的当前工作目录,和延迟导入触发时的目录不一致。比如程序调用LoadLibrary成功后切换了工作目录,等触发延迟导入逻辑时,LdrpComputeLazyDllPath会用新的目录去搜索,自然找不到原来路径下的DLL2.dll。延迟导入与LoadLibrary的搜索规则存在差异
尽管两者都会调用LdrpComputeLazyDllPath,但延迟导入的搜索逻辑受**延迟导入表(Delay Import Table)**的配置约束。如果延迟导入表未指定DLL的完整路径,且LoadLibrary调用后进程的DLL搜索路径(比如PATH环境变量、进程专属DLL搜索目录)发生了变化,就会导致路径计算错误。另外,延迟导入默认不会优先搜索调用模块所在的目录,而LoadLibrary在多数场景下会(比如调用方是EXE程序时)。进程中已加载同名但路径不同的DLL
LoadLibrary是显式加载操作,会将DLL的完整路径记录到进程的模块列表中;但延迟导入属于隐式加载的变种,只有第一次调用延迟导入函数时才会尝试加载DLL。如果此时进程中已经有另一个路径下的DLL2.dll被加载,LdrpComputeLazyDllPath会优先复用这个已加载的模块,但该模块中不存在你需要的FunctionFromDLL1,就会触发127(0x7F)错误。LdrpComputeLazyDllPath的逻辑会根据调用方调整
这个函数的行为并非固定不变:- 被LoadLibrary调用时,会结合调用者的模块路径、当前目录、PATH环境变量等进行全范围搜索;
- 被ResolveDelayLoadedAPI调用时,会优先参考延迟导入表中指定的DLL名称,还可能限制搜索目录范围(比如延迟导入表配置了
LOAD_LIBRARY_SEARCH_SYSTEM32这类标志,就只会搜索系统目录)。如果你的延迟导入表设置了这类限制,而DLL2.dll不在指定目录内,就会加载失败。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

