Robert Shearman rob@codeweavers.com writes:
ChangeLog: Optimize for the case where a DLL with no path is requested and it is already loaded. This change is correct since RtlDosSearchPath_U did not change the path being looked at - if libname contains no path then file_part will be the same as libname.
Yes, but the current code checks for the full name first and your patch doesn't, so it will change the behavior if we have two modules with the same base name. This will need some test cases.
Alexandre Julliard wrote:
Robert Shearman rob@codeweavers.com writes:
ChangeLog: Optimize for the case where a DLL with no path is requested and it is already loaded. This change is correct since RtlDosSearchPath_U did not change the path being looked at - if libname contains no path then file_part will be the same as libname.
Yes, but the current code checks for the full name first and your patch doesn't, so it will change the behavior if we have two modules with the same base name. This will need some test cases.
What sort of tests do you want? I don't think I'll be able to come up with anything that can be put into the Wine test framework.
Robert Shearman rob@codeweavers.com writes:
What sort of tests do you want? I don't think I'll be able to come up with anything that can be put into the Wine test framework.
Agreed, it's probably not possible to put that in the test framework since it will need native dlls. All we really need is a small test app that we can run on Windows to determine the proper behavior.
Alexandre Julliard wrote:
Robert Shearman rob@codeweavers.com writes:
What sort of tests do you want? I don't think I'll be able to come up with anything that can be put into the Wine test framework.
Agreed, it's probably not possible to put that in the test framework since it will need native dlls. All we really need is a small test app that we can run on Windows to determine the proper behavior.
I performed two tests. One was a control to make sure the assumptions I made were correct and one was to verify the behaviour of the loader when it comes to finding matching modules.
Preparations for both tests: 1. Windows XP SP2 was used for the tests. 2. A test DLL was build that just consisted of the following code: BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: OutputDebugString("Root\n"); / OutputDebugString("System\n"); DisableThreadLibraryCalls(hinstDLL); break; } } 3. Two versions of the DLL were built with different debug strings to be output depending on where the DLL was located (this was to ensure the correct DLL was being loaded for the later tests during the setup of the environment. 4. One DLL (to be known as "Root") was copied to C:\ (which had the debug string of "Root"). 5. Another DLL (to be known as "System") was copied to %SystemRoot%\system32. 6. Both DLLs had the same name of "LoaderTest.dll"
Test 1: Purpose - this test is a control to see whether the assumption was correct that using SetDllDirectory would cause the root directory version of the DLL to be returned from the last DLL loader. The following test code will be used: HMODULE hSystem = NULL; HMODULE hRoot = NULL; HMODULE hModule = NULL; // hSystem = LoadLibrary("LoaderTest.dll"); hRoot = LoadLibraryEx("C:\LoaderTest.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH); SetDllDirectory("C:\"); hModule = LoadLibrary("LoaderTest.dll"); if (hModule == hSystem) printf("Last module load resolved to system directory version of the DLL\n"); else if (hModule == hRoot) printf("Last module load resolved to root directory version of the DLL\n"); else printf("Last module load resolved to neither of the two previous DLL loads\n");
Result - "Last module load resolved to root directory version of the DLL" Conclusion - the test succeeded in verifying that without the system directory version of the DLL loaded then the last DLL load will return C:\LoaderTest.dll.
Test 2: Purpose - this test will see whether loading a DLL by specifying just its basename causes it to be matched using its full name or its base name. The following test code will be used: HMODULE hSystem = NULL; HMODULE hRoot = NULL; HMODULE hModule = NULL; hSystem = LoadLibrary("LoaderTest.dll"); hRoot = LoadLibraryEx("C:\LoaderTest.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH); SetDllDirectory("C:\"); hModule = LoadLibrary("LoaderTest.dll"); if (hModule == hSystem) printf("Last module load resolved to system directory version of the DLL\n"); else if (hModule == hRoot) printf("Last module load resolved to root directory version of the DLL\n"); else printf("Last module load resolved to neither of the two previous DLL loads\n");
Result - "Last module load resolved to system directory version of the DLL" Conclusion - The result shows that the last module load returns the same module as the first (system directory) module load. This can be because of two reasons. The first could be that using a DLL with no path always causes the system directory version of the DLL to be used, but we discounted this possibility with Test 1 above. The second reason is that it could be preferring the first loaded module. However, since the full DLL names are unique and matching any base DLL name would cause bad behaviour, it must be concluded that it is indeed matching on the base DLL name.
I believe that this proves that my patch is correct. If I have overlook something I am happy to perform further tests.
Rob