diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c index 326a80e9158..340d6462434 100644 --- a/dlls/kernel32/tests/module.c +++ b/dlls/kernel32/tests/module.c @@ -128,6 +128,62 @@ static void testLoadLibraryA(void) FreeLibrary(hModule); } +static void testNestedLoadLibraryA(void) +{ + static const char dllname[] = "shell32.dll"; + char path1[MAX_PATH], path2[MAX_PATH]; + HMODULE hModule1, hModule2, hModule3; + + /* This is not really a Windows conformance test, but more a Wine + * regression test. Wine's builtin dlls can be loaded from multiple paths, + * and this test tries to make sure that Wine does not get confused and + * really unloads the Unix .so file at the right time. Failure to do so + * will result in the dll being unloadable. + * This test must be done with a dll that can be unloaded, which means: + * - it must not already be loaded + * - it must not have a 16-bit counterpart + */ + GetWindowsDirectory(path1, sizeof(path1)); + strcat(path1, "\\system\\"); + strcat(path1, dllname); + hModule1 = LoadLibraryA(path1); + if (!hModule1) + { + /* We must be on Windows NT, so we cannot test */ + return; + } + + GetWindowsDirectory(path2, sizeof(path2)); + strcat(path2, "\\system32\\"); + strcat(path2, dllname); + hModule2 = LoadLibraryA(path2); + if (!hModule2) + { + /* We must be on Windows 9x, so we cannot test */ + ok(FreeLibrary(hModule1), "FreeLibrary() failed\n"); + return; + } + + /* The first LoadLibrary() call may have registered the dll under the + * system32 path. So load it, again, under the '...\system\...' path so + * Wine does not immediately notice that it is already loaded. + */ + hModule3 = LoadLibraryA(path1); + ok(hModule3 != NULL, "LoadLibrary(%s) failed\n", path1); + + /* Now fully unload the dll */ + ok(FreeLibrary(hModule3), "FreeLibrary() failed\n"); + ok(FreeLibrary(hModule2), "FreeLibrary() failed\n"); + ok(FreeLibrary(hModule1), "FreeLibrary() failed\n"); + ok(GetModuleHandle(dllname) == NULL, "%s was not fully unloaded", dllname); + + /* Try to load the dll again, if refcounting is ok, this should work */ + hModule1 = LoadLibraryA(path1); + todo_wine ok(hModule1 != NULL, "LoadLibrary(%s) failed\n", path1); + if (hModule1 != NULL) + ok(FreeLibrary(hModule1), "FreeLibrary() failed\n"); +} + static void testLoadLibraryA_Wrong(void) { HMODULE hModule; @@ -179,6 +235,7 @@ START_TEST(module) testGetModuleFileName_Wrong(); testLoadLibraryA(); + testNestedLoadLibraryA(); testLoadLibraryA_Wrong(); testGetProcAddress_Wrong(); }