[Bug 48229] Regression on Automobilista. A lot of cars and tracks are not shown on Game menu

WineHQ Bugzilla wine-bugs at winehq.org
Thu Jan 16 16:15:19 CST 2020


https://bugs.winehq.org/show_bug.cgi?id=48229

Paul Gofman <gofmanp at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |gofmanp at gmail.com

--- Comment #4 from Paul Gofman <gofmanp at gmail.com> ---
Created attachment 66256
  --> https://bugs.winehq.org/attachment.cgi?id=66256
Test program

I've tested the game.

The game hooks kernel32.CreateFileW() and expects calls to
kernel32.CreateFileA() to be routed to the kernel32.CreateFileW() where it is
supposed to meet the hook. The hook does some trickery to open the actual data
file while the files directly requested in CreateFile call do not exist.

Funny thing is that the reason why it breaks on commit bisected above is not
the same as the reason why it doesn't work in the current git.

At the moment of the switch to no-PIC build (commit bisected above) both
CreateFilaA() and CreateFileW() were implemented in kernel32.dll.so. Switch to
no-PIC build triggered some different behaviour of gcc compiler which started
for some reason creating a copy of CreateFileW() function so the calls from
within kernel32 went to this function instead of the one which was referenced
through the import table (maybe it was partially inlined though I did not
analyze that disassembly thoroughly). The proof of concept fix which let me to
fix the issue in Wine 4.8 source was adding __attribute__((noinline)) to
CreateFileW(). I should also note that with my 4.7 or 4.8 source builds with
default flags the game was crashing right away, I worked that around by
compiling kernel32.dll.so with -O0 flag. Fortunately this sort of issue is not
reproducible on the current git.

Later CreateFile{A|W}() were moved to kernelbase, and their availability in
kernel32.dll is now provided by the following spec entries:

@ stdcall -import CreateFileA(str long long ptr long long long)
@ stdcall -import CreateFileW(wstr long long ptr long long long)

So both CreateFileA() and CreateFileW() are now routed directly from their
import thunks to kernelbase, and hooking kernel32.CreateFileW() has no effect
on CreateFileA().

The most straightforward change which fixes the issue is to define the
functions in kernel32 spec file like this:

@ stdcall CreateFileA(str long long ptr long long long) kernelbase.CreateFileA
@ stdcall CreateFileW(wstr long long ptr long long long) kernelbase.CreateFileW

But this appears to be not quite correct. With these functions directly
forwarded to kernelbase GetProcAddress(GetModuleHandle("kernel32.dll"),
"CreateFileW") returns the address of the function in kernelbase (same address
as for GetProcAddress(GetModuleHandle("kernelbase.dll"), "CreateFileW"). This
appears to be not the case in my testing on Windows 7, where GetProcAddress
return different addresses each in the corresponding module.

I am attaching the test program here which prints these function pointers and
emulates such sort of hooking. The hook function is called when calling
CreateFileA() on Windows 7 but not under Wine currently. So the correct fix
seems to route kernel32.CreateFileA() to kernel32.CreateFileW() instead of
kernelbase.CreateFileW().

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list