Question

My directory structure is as follows:

test
  dir
    a.dll  <-- version 1
  a.dll    <-- version 2
  myapp.exe

I expect that by themselves, LoadLibrary("dir\\a.dll") will use version 1 and LoadLibrary("a.dll") will use version 2, while together:

LoadLibrary("dir\\a.dll");
LoadLibrary("a.dll");

Both will refer to version 1, according to the documentation of LoadLibrary.

However, when I try to do that in the application I'm working on, line 1 loads version 1 and line 2 loads version 2.

I've tried to write a small reproducer but in the reproducer it works as expected - so there's something that breaks that in the larger application or in the loaded dll. What can cause that, and how can I solve it?

And to emphasize, the two loads are adjacent in the larger application, there are no system calls between line 1 and 2 (and it's of course the same process). I originally did want to put a lot of code between them, but saw this issue and reproduced it even when they are adjacent.

I've also tried with the following directory structure:

test
  dir
    a.dll  <-- version 1
  myapp.exe
Windows
  System32
    a.dll  <-- version 2

But again, line 1 loads version 1 and line 2 loads version 2.

Was it helpful?

Solution

I managed to find the solution. In fact, it only requires some thought - the answer is obvious in retrospect: such a situation can occur when the dll was already loaded before my first LoadLibrary call. So the 1st call, with the explicit path, loads version 1 - while the 2nd call, without a path, defaults to the first loaded dll (according to the documentation), which happens to be version 2.

This can be fixed by forcefully unloading the library before the first LoadLibrary call:

HMODULE alreadyLoaded = GetModuleHandle("a.dll");
if (alreadyLoaded) {
    FreeLibrary(alreadyLoaded);
}

Although that was enough for me, a more complete solution is to do so in a loop, to handle cases where the dll was loaded multiple times before:

HMODULE alreadyLoaded = GetModuleHandle("a.dll");
while (alreadyLoaded) {
    FreeLibrary(alreadyLoaded);
    alreadyLoaded = GetModuleHandle("a.dll");
}

Of course, this is potentially dangerous - especially if the original HMODULE was stored somewhere, as this renders it invalid.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top