LoadLibraryW()无法在System32中加载DLL

Jus*_*n G 3 c++ dll loadlibrary system32

我正在尝试使用以下代码加载在C:\ Windows\System32 \文件夹中安装了打印机驱动程序的DLL:

LoadLibraryW(L"C:\\Windows\\System32\\MagAPI.dll");
Run Code Online (Sandbox Code Playgroud)

GetLastError()报告"无法找到指定的模块".如果我将DLL移动到System32文件夹之外(例如C:\ SomeFolder\MagAPI.dll),那么它将加载正常,因此它似乎不是DLL本身的问题.是否有一些奇怪的Windows安全功能可能阻止我的应用程序加载它?这是我唯一能想到的,但我找不到任何明确的答案.

这是ShowSnaps的调试输出,它显示了它失败的地方:

1a8c:1fd4 @ 19006756 - LdrLoadDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpLoadDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpLoadDll - INFO: Loading DLL C:\Windows\system32\MagAPI.dll from path C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpFindOrMapDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpSearchPath - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpResolveFileName - ENTER: DLL name: C:\Windows\system32\MagAPI.dll
1a8c:1fd4 @ 19006756 - LdrpResolveFileName - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpSearchPath - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpFindOrMapDll - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpLoadDll - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrLoadDll - RETURN: Status: 0xc0000135
Run Code Online (Sandbox Code Playgroud)

Spi*_*ire 6

由于您提到您的应用程序是32位,因此您加载的DLL也必须是32位.

LoadLibrary()失败的可能原因是您运行的是64位版本的Windows,但是您的打印机驱动程序错误地将其32位DLL安装到System32文件夹而不是SysWOW64文件夹中.

一些背景知识:在64位版本的Windows上,64位DLL进入System32文件夹,32位DLL进入该SysWOW64文件夹.我知道这听起来应该是另一种方式,但不要让名字让你感到困惑; 这些文件夹的名称是出于向后兼容的原因.该SysWOW64文件夹应该对应用程序透明:Windows具有称为文件系统重定向的功能,使32位应用程序可以通过指定System32文件夹(就像它们始终具有的那样)加载32位DLL,即使DLL是实际里面SysWOW64.

另一方面,LoadLibrary()将简单地拒绝加载已放置在错误文件夹中的DLL.这是你可能会看到的行为.

您的问题的真正解决方案是联系打印机制造商并告知他们他们的驱动程序安装程序将其DLL放入64位版本的Windows下的错误文件夹中.如果他们解决了这个问题,您的应用程序将开始正常工作,而无需更改现有代码.

在此期间,您应该能够通过这样做来解决您的问题:

  1. 在尝试加载DLL之前,请将DLL复制%windir%\Sysnative到您可以控制的某个已知文件夹.(我建议你在里面创建一个唯一命名的文件夹%TEMP%并将DLL复制到该文件夹​​中).注意:Sysnative是一个特殊的别名,它映射到本机系统文件夹,该文件夹System32位于64位版本的Windows下.
  2. 调用LoadLibrary()并传递您在步骤1中创建的DLL副本的路径.
  3. 当您使用完DLL后,卸载它并删除您在步骤1中创建的副本.

如果您需要支持64位Windows XP,则上述解决方法可能不起作用,因为该Sysnative别名记录为仅适用于Windows Vista或更高版本.另一种解决方法是手动绕过文件系统重定向:

  1. 通过调用暂时禁用文件系统重定向Wow64DisableWow64FsRedirection().这将允许您的应用程序查看真正的内容System32.
  2. 将DLL复制System32到您可以控制的某个已知文件夹.
  3. 通过调用重新启用文件系统重定向Wow64RevertWow64FsRedirection().
  4. 调用LoadLibrary()并传递您在步骤2中创建的DLL副本的路径.
  5. 当您使用完DLL后,将其卸载并删除您在步骤2中创建的副本.

请注意,如果你想打电话的Wow64DisableWow64FsRedirection()获得LoadLibrary()而无需复制DLL,不要刻意去上班:LoadLibrary()不留意该设置.(我实际测试过它.)

更多信息:文件系统重定向器