http://bugs.winehq.org/show_bug.cgi?id=58162
Bug ID: 58162 Summary: GetPrivateProfileIntA/W and WritePrivateProfileStringA/W does not detour properly. Product: Wine Version: 10.6 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: kernel32 Assignee: wine-bugs@winehq.org Reporter: hibbsncc1701@gmail.com Distribution: ---
Created attachment 78443 --> http://bugs.winehq.org/attachment.cgi?id=78443 sone_patch's debug log under Windows 10.
When trying to detour a Recettear - An Item Shop's Tale's custom.exe using https://gitlab.com/redpolline/sone_patch, all attempts to update the game's config ini file fail under Wine, but work under Windows.
The game's custom.exe uses the GetPrivateProfileIntA() and WritePrivateProfileStringA() functions to access the game's ini file instead of calling CreateFileA(), ReadFile(), and WriteFile() directly.
I assume that the cause is Wine possibly having GetFullPathNameW() as a statically linked symbol within the context of GetPrivateProfileIntA() and WritePrivateProfileStringA(). (As all three of them are exported by kernel32.dll, and therefore the compiler would not need to search for the symbol at build time.) But I could be wrong here.
What matters is that when sone_patch detours GetFullPathNameA/W(), GetPrivateProfileIntA() and WritePrivateProfileStringA() should be affected by that detour without being detoured themselves.
A good way to see this is by using sone_patch's debug build, as it logs when a detoured function is hit, along with the given arguments.
Under Windows 10, multiple calls to GetFullPathNameA/W() are seen in the log. (But no CreateFileA/W() for the ini file.)
Under Wine, no calls are logged at all for the ini file. The only call to GetFullPathNameW() seen under Wine is for C:\windows\resources\themes\light\light.msstyles. Which isn't present under the Windows log, so that one is Wine specific.)
As a result, the game's button config and display settings cannot be altered by the game's custom.exe. As it gets the original (developer intended) file which is read-only (and owned by another user) on my system. Which sone_patch is supposed to workaround through the detouring of GetFullPathNameA/W() to point custom.exe to an accessible file elsewhere.
http://bugs.winehq.org/show_bug.cgi?id=58162
--- Comment #1 from Patrick Hibbs hibbsncc1701@gmail.com --- Created attachment 78444 --> http://bugs.winehq.org/attachment.cgi?id=78444 sone_patch's debug log under Wine.
http://bugs.winehq.org/show_bug.cgi?id=58162
--- Comment #2 from Alexandre Julliard julliard@winehq.org --- In general we can't support that sort of thing, because the call sequences that Wine makes internally differ from Windows. That's intentional, we don't want to investigate or replicate the internal workings of Windows dlls.
http://bugs.winehq.org/show_bug.cgi?id=58162
--- Comment #3 from Patrick Hibbs hibbsncc1701@gmail.com --- (In reply to Alexandre Julliard from comment #2)
In general we can't support that sort of thing, because the call sequences that Wine makes internally differ from Windows. That's intentional, we don't want to investigate or replicate the internal workings of Windows dlls.
I can understand that Wine doesn't want to be too much like Windows, and that doing so could cause legal issues for Wine.
That being said, current-as-of-this-posting Wine does call GetFullPathNameW() at https://gitlab.winehq.org/wine/wine/-/blob/f7503d0a996ae1243dd6c87b39a914362... Via the call chains: GetPrivateProfileIntA() -> GetPrivateProfileIntW() -> GetPrivateProfileStringW() -> GetPrivateProfileSectionNamesW() -> PROFILE_GetSectionNames() -> PROFILE_Open() -> GetFullPathNameW().
WritePrivateProfileStringA() -> WritePrivateProfileStringW() -> PROFILE_Open() -> GetFullPathNameW().
I don't see how making a call that Wine already performs internally, detourable, is a problem. It's just an IAT lookup, something that depending on your compiler / linker version and settings could be done accidentally already.
I would also be negligent not to point out that there are some things in Wine that solely exist for issues like this, Direct3DShaderValidatorCreate9() (Bug #46735) for example.
If making the existing internal call to GetFullPathNameW() detourable is not acceptable, then what would be the proper solution as far as Wine is concerned?
As I see it, the current options outside of Wine are:
The ideal solution (which would be the game developer fixing their app) is not likely to happen in general. (In this specific case, the developer abandoned the GOG version of Recettear years ago.)
The secondary solution (someone makes a unique patch for the game itself) is less likely given that the third option already exists and works. (And may run afoul of their legal obligations depending where in the world they live.)
The third option was a generic fix. (sone_patch in this case) That already exists and is functional under Windows. It's only Wine that's the problem here. Asking a third party to patch both the upstream proprietary binary blob's API calls *and* the downstream runtime is a bit much. Especially when that downstream fix effectively means detouring every top level Windows API call that has a path argument, or forking the downstream and providing their own patches. (Which only creates further fragmentation of Wine's user base.)
Have I missed something?
http://bugs.winehq.org/show_bug.cgi?id=58162
--- Comment #4 from Alexandre Julliard julliard@winehq.org --- (In reply to Patrick Hibbs from comment #3)
I don't see how making a call that Wine already performs internally, detourable, is a problem. It's just an IAT lookup, something that depending on your compiler / linker version and settings could be done accidentally already.
If it's called already then it should work. GetFullPathNameW is already marked as DECLSPEC_HOTPATCH so it should be detourable. There must be something else going on here.