https://bugs.winehq.org/show_bug.cgi?id=37512
Bug ID: 37512 Summary: Unreal Engine 4 Elemental benchmark demo crashes on startup ('K32GetPerformanceInfo' must not pass 'PERFORMANCE_INFORMATION' directly to 'NtQuerySystemInformation') Product: Wine Version: 1.7.30 Hardware: x86 OS: Linux Status: NEW Severity: normal Priority: P2 Component: kernel32 Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
as the summary says.
Prerequisite:
--- snip --- err:module:import_dll Library MSVCP120.dll (which is needed by L"Z:\home\focht\Downloads\Elemental\Binaries\Win32\Elemental.exe") not found --- snip ---
bug 37511 -> 'winetricks -q vcrun2013'
--- snip --- err:module:import_dll Library X3DAudio1_7.dll (which is needed by L"Z:\home\focht\Downloads\Elemental\Binaries\Win32\Elemental.exe") not found err:module:import_dll Library XAPOFX1_5.dll (which is needed by L"Z:\home\focht\Downloads\Elemental\Binaries\Win32\Elemental.exe") not found --- snip ---
bug 36844 -> 'winetricks -q xact_jun2010'
--- snip --- $ WINEDEBUG=+tid,+seh,+relay,+ntdll wine ./Elemental.exe >>log.txt 2>&1 ... 0033:Call KERNEL32.GlobalMemoryStatusEx(01e1fcfc) ret=00504c14 0033:trace:ntdll:NtQuerySystemInformation (0x00000001,0x1e1fabc,0x0000000c,(nil)) 0033:Ret KERNEL32.GlobalMemoryStatusEx() retval=00000001 ret=00504c14 0033:Call KERNEL32.K32GetPerformanceInfo(01e1fd3c,00000038) ret=00504c39 0033:trace:ntdll:NtQuerySystemInformation (0x00000002,0x1e1fd3c,0x00000038,(nil)) 0033:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION 0033:Ret KERNEL32.K32GetPerformanceInfo() retval=00000000 ret=00504c39 ... <lots of unrelated stuff> ... 0033:trace:seh:raise_exception code=c0000094 flags=0 addr=0x10046a4 ip=010046a4 tid=0033 0033:trace:seh:raise_exception eax=00000001 ebx=00000000 ecx=00000000 edx=00000000 esi=ffffffff edi=0014b758 0033:trace:seh:raise_exception ebp=00000000 esp=01e1fd44 cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00010246 0033:trace:seh:call_stack_handlers calling handler at 0x100404d code=c0000094 flags=0 0033:Call KERNEL32.GetLastError() ret=1000f728 0033:Ret KERNEL32.GetLastError() retval=00000018 ret=1000f728 0033:trace:seh:call_stack_handlers handler at 0x100404d returned 1 0033:trace:seh:call_stack_handlers calling handler at 0x7bc9e4cb code=c0000094 flags=0 0033:Call KERNEL32.UnhandledExceptionFilter(01e1f824) ret=7bc9e505 wine: Unhandled division by zero at address 0x10046a4 (thread 0033), starting debugger... ... Unhandled exception: divide by zero in 32-bit code (0x010046a4). Register dump: CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b EIP:010046a4 ESP:01e1fd44 EBP:00000000 EFLAGS:00010246( R- -- I Z- -P- ) EAX:00000001 EBX:00000000 ECX:00000000 EDX:00000000 ESI:ffffffff EDI:0014b758 ... Backtrace: =>0 0x010046a4 in elemental (+0xc046a4) (0x00000000) 0x010046a4: divl %ecx,%eax Modules: Module Address Debug info Name (97 modules) PE 240000- 2b1000 Deferred msvcp120 PE 2c0000- 2c7000 Deferred x3daudio1_7 PE 2d0000- 2e4000 Deferred xapofx1_5 PE 400000- 1942000 Export elemental PE 10000000-100ee000 Deferred msvcr120 ELF 7b800000-7ba64000 Deferred kernel32<elf> -PE 7b810000-7ba64000 \ kernel32 ELF 7bc00000-7bcef000 Deferred ntdll<elf> -PE 7bc10000-7bcef000 \ ntdll ... Threads: process tid prio (all id:s are in hex) ... 00000032 (D) Z:\home\focht\Downloads\Elemental\Binaries\Win32\Elemental.exe 00000033 0 <== --- snip ---
The division by zero is a late symptom of an earlier API fault. Basically the client code tries to figure out memory constraints, making use of 'GetPerformanceInfo' to query for page size etc.
Unfortunately Wine 'K32GetPerformanceInfo' implementation incorrectly passes the structure/input buffer untranslated to 'NtQuerySystemInformation( SystemPerformanceInformation, ...)'.
Source: http://source.winehq.org/git/wine.git/blob/62f22dd4e3ab4f4b21f8e6b571fd7f9ba...
PERFORMANCE_INFORMATION structure layout is not compatible with SYSTEM_PERFORMANCE_INFORMATION, leading to buffer-too-short failure on native API call.
The app code doesn't validate the error code and uses the default buffer value (0) which ought to be the real page size.
PERFORMANCE_INFORMATION -> http://msdn.microsoft.com/en-us/library/windows/desktop/ms684824%28v=vs.85%2...
SYSTEM_PERFORMANCE_INFORMATION -> http://source.winehq.org/git/wine.git/blob/9a806d0f1c10289241500519beda73f1a...
The app code:
--- snip --- ... 00504C2D 8D4424 40 LEA EAX,DWORD PTR SS:[ESP+40] 00504C31 6A 38 PUSH 38 00504C33 50 PUSH EAX 00504C34 E8 A923B000 CALL <JMP.&PSAPI.GetPerformanceInfo> 00504C39 8B4C24 08 MOV ECX,DWORD PTR SS:[ESP+8] 00504C3D 8B4424 28 MOV EAX,DWORD PTR SS:[ESP+28] 00504C41 A3 9C3E5C01 MOV DWORD PTR DS:[15C3E9C],EAX 00504C46 8B4424 68 MOV EAX,DWORD PTR SS:[ESP+68] 00504C4A A3 A03E5C01 MOV DWORD PTR DS:[15C3EA0],EAX ; page size ... --- snip ---
To fill out the structure with reasonable values you would need to call 'NtQuerySystemInformation' multiple times with different information classes.
--- snip --- typedef struct _PERFORMANCE_INFORMATION { DWORD cb; SIZE_T CommitTotal; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T CommitLimit; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T CommitPeak; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T PhysicalTotal; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T PhysicalAvailable; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T SystemCache; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T KernelTotal; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T KernelPaged; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T KernelNonpaged; // SYSTEM_PERFORMANCE_INFORMATION SIZE_T PageSize; // SYSTEM_BASIC_INFORMATION DWORD HandleCount; // SYSTEM_PROCESS_INFORMATION DWORD ProcessCount; // SYSTEM_PROCESS_INFORMATION DWORD ThreadCount; // SYSTEM_PROCESS_INFORMATION } PERFORMANCE_INFORMATION, *PPERFORMANCE_INFORMATION; --- snip ---
$ sha1sum UE4_Elemental_Demo.rar a09206fecdb2bf7de2c69a4490329a6c61b1d3c7 UE4_Elemental_Demo.rar
$ du -sh UE4_Elemental_Demo.rar 998M UE4_Elemental_Demo.rar
$ wine --version wine-1.7.30-58-g9e4590f
Regards