I'm trying to load a DLL that was installed with a printer driver in the C:\Windows\System32\ folder with the following code:
LoadLibraryW(L"C:\\Windows\\System32\\MagAPI.dll");
GetLastError()
is reporting that "The specified module could not be found". If I move the DLL outside of the System32 folder (C:\SomeFolder\MagAPI.dll for example) then it will load fine so it doesn't seem like it's a problem with the DLL itself. Is there some weird Windows security feature that might be blocking my application from loading it? That's the only thing I can think of but I can't find any definitive answers.
Here's the debug output from ShowSnaps, which shows where it's failing:
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
Since you mention that your application is 32-bit, the DLL that you're loading must also be 32-bit.
The likely reason
LoadLibrary()
is failing is that you're running a 64-bit edition of Windows, but your printer driver has erroneously installed its 32-bit DLL in question into theSystem32
folder instead of theSysWOW64
folder.Some background: On 64-bit editions of Windows, 64-bit DLLs go in
System32
folder, and 32-bit DLLs go in theSysWOW64
folder. I know it sounds like it should be the other way around, but don't let the names confuse you; the folders are named like that are for backward-compatibility reasons. TheSysWOW64
folder is supposed to be transparent to applications: Windows has a feature called file-system redirection that makes it possible for 32-bit applications to load 32-bit DLLs by specifying theSystem32
folder (just as they always have) even though the DLLs are actually insideSysWOW64
.On the other hand,
LoadLibrary()
will simply refuse to load a DLL that's been placed inside the wrong folder. This is the behavior you're probably seeing.The real solution to your problem is to contact the printer manufacturer and inform them that their driver installer is putting its DLLs into the wrong folder under 64-bit editions of Windows. If they ever fix this, your application will start working correctly without any changes to your existing code.
In the meantime, you should be able to work around your problem by doing this:
%windir%\Sysnative
to some known folder that you have control over. (I suggest that you create a uniquely named folder inside%TEMP%
and copy the DLL into that folder). Note:Sysnative
is a special alias that maps to the native system folder, which isSystem32
under 64-bit editions of Windows.LoadLibrary()
and pass it the path of the copy of the DLL that you made in step 1.The above workaround might not work if you need to support 64-bit Windows XP, since the
Sysnative
alias is documented to work only on Windows Vista or later. An alternative workaround is to manually bypass file-system redirection:Wow64DisableWow64FsRedirection()
. This will allow your application to see what's really inSystem32
.System32
to some known folder that you have control over.Wow64RevertWow64FsRedirection()
.LoadLibrary()
and pass it the path of the copy of the DLL that you made in step 2.Note that if you're thinking of calling
Wow64DisableWow64FsRedirection()
to getLoadLibrary()
to work without having to copy the DLL, don't bother:LoadLibrary()
doesn't pay attention to that setting. (I actually tested it.)More information: File System Redirector