LoadLibraryW()无法在System32中加载DLL

时间:2013-08-29 22:41:22

标签: c++ dll loadlibrary system32

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

LoadLibraryW(L"C:\\Windows\\System32\\MagAPI.dll");

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

1 个答案:

答案 0 :(得分: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是一个特殊的别名,它映射到本机系统文件夹,在64位版本的Windows下为System32
  2. 调用LoadLibrary()并将其传递给您在步骤1中创建的DLL副本的路径。
  3. 当您使用完DLL后,将其卸载并删除您在步骤1中创建的副本。
  4. 如果您需要支持64位Windows XP,则上述解决方法可能无效,因为Sysnative别名记录为仅适用于Windows Vista或更高版本。另一种解决方法是手动绕过文件系统重定向:

    1. 通过调用Wow64DisableWow64FsRedirection()暂时禁用文件系统重定向。这将允许您的应用程序查看System32 的内容。
    2. 将DLL从System32复制到您可以控制的某个已知文件夹。
    3. 通过调用Wow64RevertWow64FsRedirection()重新启用文件系统重定向。
    4. 调用LoadLibrary()并将其传递给您在步骤2中创建的DLL副本的路径。
    5. 当您使用完DLL后,请将其卸载并删除您在步骤2中创建的副本。
    6. 请注意,如果您考虑调用Wow64DisableWow64FsRedirection()以使LoadLibrary()无需复制DLL即可工作,请不要理会:LoadLibrary()不注意设置。 (我实际测试了它。)

      更多信息:File System Redirector