http://bugs.winehq.org/show_bug.cgi?id=9942
--- Comment #21 from Saulius K. saulius2@gmail.com 2010-06-13 09:49:29 --- (In reply to Bug 14980 comment #15 from Dan Kegel 2009-02-27 13:37:24)
Alexandre suggests in http://www.winehq.org/pipermail/wine-devel/2009-February/073288.html that it would be ok for the loader to check the version of the native dll with the version of the builtin one, and use the native one if higher.
...
hModule = LoadLibraryExW(filename, 0, LOAD_LIBRARY_AS_DATAFILE); hRsrc = FindResourceW(hModule, MAKEINTRESOURCEW(VS_VERSION_INFO), MAKEINTRESOURCEW(VS_FILE_INFO)); len = SizeofResource(hModule, hRsrc); hMem = LoadResource(hModule, hRsrc); buf = LockResource(hMem); vffi = (VS_FIXEDFILEINFO*)VersionInfo32_Value((VS_VERSION_INFO_STRUCT32*)buf); verify that ( vffi->dwSignature == VS_FFI_SIGNATURE ) access vffi->dwFileVersionMS and vffi->dwFileVersionMS FreeResource(hMem);
(And summarizing mails)
On Sun, 18 Oct 2009, Alexandre Julliard wrote:
Jeremy White writes:
Alexandre Julliard wrote:
Dan Kegel writes:
OK, so even on an absolute path, we need to do a version check, and only use the bundled copy if it's newer than builtin? (That's what I thought you meant earlier.)
Yes, and even that may not be enough, it may have to be limited further to some very specific cases.
How do we go about identifying those specific cases? Should we start with a list of dlls (with one entry in the list - riched20)?
Only as a last recourse. We can most likely find better ways of addressing that specific problem, for example by having riched20 itself take care of it instead of doing it in the loader.
So it basically needs to put (pseudo-)code (from the Dan's comment) into the DllMain() for the bug to be fixed, right?
In such case we need to get the full pathname of native dll (to be loaded as builtin) in the DllMain() of the builtin version:
trace:module:load_builtin_dll Trying built-in L"C:\Program Files\Common Files\Microsoft Shared\office12\riched20.dll" warn:module:load_builtin_dll failed to load .so lib for builtin L"C:\Program Files\Common Files\Microsoft Shared\office12\riched20.dll": /usr/src/wine-git/.wine/dosdevices/ trace:module:load_builtin_dll Trying built-in L"riched20.dll" ... trace:module:load_builtin_callback loaded riched20.dll 0x1841b8 0x7dd00000 001c: load_dll( handle=0000, base=7dd00000, name=001841e0, size=303104, dbg_offset=0, dbg_size=0, filename=L"C:\windows\system32\riched20.dll" ) 001c: load_dll() = 0 trace:loaddll:load_builtin_dll Loaded L"C:\windows\system32\riched20.dll" at 0x7dd00000: builtin trace:module:MODULE_InitDLL (0x7dd00000 L"riched20.dll",WINE_PREATTACH,(nil)) - CALL trace:module:MODULE_InitDLL (0x7dd00000,WINE_PREATTACH,(nil)) - RETURN 1 trace:module:load_dll Loaded module L"C:\Program Files\Common Files\Microsoft Shared\office12\riched20.dll" (builtin) at 0x7dd00000 001c: close_handle( handle=014c ) 001c: close_handle() = 0 trace:module:process_attach (L"riched20.dll",(nil)) - START trace:module:MODULE_InitDLL (0x7dd00000 L"riched20.dll",PROCESS_ATTACH,(nil)) - CALL trace:module:GetModuleFileNameW L"C:\windows\system32\riched20.dll" err:richedit:DllMain dll_name: "C:\windows\system32\riched20.dll"
I see load_builtin_dll() saves the full pathname (we need) in a string called "path". Called 1st time the function fails, because "path" is PE image. Called 2nd time it already uses stripped name ("riched20.dll") and ignores "path" so the full pathname is lost in further action. We need to store, probably along with the "C:\windows\system32\riched20.dll".
I am stepping into someone's shoes :) and I fail to see which way is right to go.
Could the "path" be written into WINE_MODREF->ldr.FullDllName so in DllMain() one could check it? Then load_builtin_callback() could be hacked to accept combined names, eg. "C:\windows\system32\riched20.dll;riched20.dll". Or it could strip the name on it's own just by using some additional flag passed. Or w/o a flag, but by rewriting logic in load_dll() also a bit.
Or could PEB_LDR_DATA extended instead to store the "path"? Or maybe WINE_MODREF could go for it?
I didn't investigate further, so the last chapter is my speculation. And the bug belongs to Alexandre, I guess :)