LoadLibrary with Absolute Path returns Incorrect HMODULE with No Error

funseiki picture funseiki · Nov 6, 2012 · Viewed 11.3k times · Source

I have some code which is trying to load a Dll.

I have encountered an odd 'error' with this. When trying to load the dll from an absolute path, I get a Non-Null HMODULE that gives no windows error codes on a GetLastError call (i.e. GetLastError returns '0' or success according to msdn). When calling into a function in this dll, I get incorrect values.

This behavior is peculiar, because if, instead, I switch the current directory to be that of my current dll using SetCurrentDirectory and use a relative path call to LoadLibrary, I get correct values.

Here is a snippet describing the situation:

Using absolute path:

std::string libLoc = get_dll_location(); // Get the directory of this dll
HMODULE myDLL = LoadLibraryA(libLoc.c_str()); // Non-null value
DWORD lastError = GetLastError(); // returns 0

MyObj * value = UseDLL(myDLL); // bad value

Using relative path:

SetCurrentDirectory("c:\\path\\containing\\dll\\"); // hard coded path to dll's folder
HMODULE myDLL = LoadLibrary("myDll.dll");  // Non-null value
MyObj * value = UseDLL(myDLL);  // Good value

I'd really like to avoid having to use SetCurrentDirectory, because the application using this Dll may be multi-threaded and require that the directory stays the same.

Any insight on this issue would be much appreciated. Hopefully, this is just a minor bug on my part.

Update: Using LoadLibraryEx seems to be out of the question, as the LOAD_LIBRARY_SEARCH_* flags don't appear to be available to me (I've already tried installing the KB2533623 update).

Answer

David Heffernan picture David Heffernan · Nov 6, 2012

Most likely the problem is that MyDll.dll has dependencies on other DLLs that reside in the same folder as MyDll.dll. When your application lives in a different folder from MyDll.dll, those dependencies will not be resolved from the folder that contains MyDll.dll. Instead they are resolved by the system DLL search order.

Your use SetCurrentDirectory influences the system DLL search order. And it means that the dependencies of MyDll.dll are resolved from the directory that contains MyDll.dll.

You can test this hypothesis by using, for example, Dependency Walker in profile mode. That will tell you how the dependencies of MyDll.dll are resolved at runtime.

You are right to dislike the use of SetCurrentDirectory. The best solution would be to put all the DLLs in the same directory as the application.

Of course, the other possibility is that the call to UseDLL has a dependency on the working directory. You can rule that out by changing the working directory back to its original value after the call to LoadLibrary.