[Bug 42520] Multiple Wargaming.net games crash on startup in Win7+ mode ( XAudio 2.7 'IXAudio2SourceVoice::GetState' called with 'Flags' parameter, causing register corruption) (World of {Tanks, Warships})

wine-bugs at winehq.org wine-bugs at winehq.org
Fri Oct 12 06:45:29 CDT 2018


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

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |focht at gmx.net
            Summary|World of Tanks: crash on    |Multiple Wargaming.net
                   |startup in win7 mode (works |games crash on startup in
                   |in winxp)                   |Win7+ mode (XAudio 2.7
                   |                            |'IXAudio2SourceVoice::GetSt
                   |                            |ate' called with 'Flags'
                   |                            |parameter, causing register
                   |                            |corruption) (World of
                   |                            |{Tanks, Warships})

--- Comment #17 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

refining summary to collect more dupes here.

Trace with some additional diagnostics added:

--- snip ---
$ pwd
/home/focht/wine-games/wineprefix64-wargaming/drive_c/Games/World_of_Warships

$ WINEDEBUG=+seh,+loaddll,+xaudio2 wine ./WorldOfWarships.exe >>log.txt 2>&1
...
0074:trace:loaddll:load_builtin_dll Loaded
L"C:\\windows\\system32\\xaudio2_7.dll" at 0xf59e0000: builtin
0074:trace:xaudio2:DllMain (0xf59e0000, 8, (nil))
0074:trace:xaudio2:DllMain (0xf59e0000, 1, (nil))
0074:trace:xaudio2:DllGetClassObject ({5a508685-a254-4fba-9b82-9a24b00306af},
{00000001-0000-0000-c000-000000000046}, 0x214ff23c)
0074:trace:xaudio2:XAudio2CF_AddRef (0x22797418)->(): Refcount now 1
0074:trace:xaudio2:XAudio2CF_CreateInstance
(0x22797418)->((nil),{8bcf1f58-9fe7-4583-8ac6-e2adc465c8bb},0x214ff238)
0074:trace:xaudio2:IXAudio2Impl_QueryInterface
(0x3c42f2a8)->({8bcf1f58-9fe7-4583-8ac6-e2adc465c8bb}, 0x214ff238)
0074:trace:xaudio2:IXAudio2Impl_AddRef (0x3c42f2a8)->(): Refcount now 1
0074:trace:xaudio2:IXAudio2Impl_StartEngine (0x3c42f2a8)->()
0074:trace:xaudio2:XAudio2CF_CreateInstance Created XAudio version 27:
0x3c42f2a8
0074:trace:xaudio2:XAudio2CF_Release (0x22797418)->(): Refcount now 0
0074:trace:xaudio2:XA27_Initialize (0x3c42f2a8)->(0x0, 0x1)
0074:trace:xaudio2:XA27_CreateMasteringVoice (0x3c42f2a8)->(0x1f9e2d44, 0,
48000, 0x0, 0, (nil))
0074:trace:xaudio2:IXAudio2Impl_CreateMasteringVoice (0x3c42f2a8)->(0x1f9e2d44,
0, 48000, 0x0, L"{0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B}",
(nil), 0x6)
0074:trace:xaudio2:XA27_GetDeviceDetails 0x3c42f2a8, 0, 0x214feed4
0074:trace:xaudio2:IXAudio2Impl_CreateSourceVoice (0x3c42f2a8)->(0x1f9e2d48,
0x214ffb18, 0x0, 1.000000, 0x1f9e2d30, (nil), (nil))
0074:trace:xaudio2:dump_fmt wFormatTag: 0xfffe (WAVE_FORMAT_EXTENSIBLE)
0074:trace:xaudio2:dump_fmt nChannels: 2
0074:trace:xaudio2:dump_fmt nSamplesPerSec: 48000
0074:trace:xaudio2:dump_fmt nAvgBytesPerSec: 384000
0074:trace:xaudio2:dump_fmt nBlockAlign: 8
0074:trace:xaudio2:dump_fmt wBitsPerSample: 32
0074:trace:xaudio2:dump_fmt cbSize: 22
0074:trace:xaudio2:dump_fmt dwChannelMask: 00000003
0074:trace:xaudio2:dump_fmt Samples: 0020
0074:trace:xaudio2:dump_fmt SubFormat: {00000003-0000-0010-8000-00aa00389b71}
0074:trace:xaudio2:XA2SRC_SetOutputVoices 0x3c432b60, (nil)
0074:trace:xaudio2:XA2SRC_SetOutputVoices Outputting to: 0x0, 0x3c42f2ac
0074:trace:xaudio2:IXAudio2Impl_CreateSourceVoice Created source voice:
0x3c432b60
0074:trace:xaudio2:XA2SRC_SetVolume 0x3c432b60, 1.000000, 0x0
0074:trace:xaudio2:IXAudio2Impl_RegisterForCallbacks (0x3c42f2a8)->(0x1f9e2d2c)
0074:trace:xaudio2:XA2SRC_Start 0x3c432b60, 0x0, 0x0
...
007c:trace:xaudio2:do_engine_tick frames available: 1440
007c:trace:xaudio2:do_engine_tick *** (1) src=0x3c432b60, src->cb=0x1f9e2d30,
src->al_src=0x1
007c:trace:xaudio2:do_engine_tick Calling OnVoiceProcessingPassStart with
BytesRequired: 19200
007c:trace:xaudio2:XA2SRC_GetState 0x3c432b60, 0x595efe48, 0x0
007c:trace:xaudio2:XA2SRC_GetState returning 0, queued: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer 0x3c432b60, 0x595efe24, (nil)
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer Flags: 0x0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer AudioBytes: 8192
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer pAudioData: 0x1f9e4da0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer PlayBegin: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer PlayLength: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopBegin: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopLength: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopCount: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer pContext: (nil)
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer 0x3c432b60: queued buffer 0 (8192
bytes), now 1 buffers held
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer 0x3c432b60, 0x595efe24, (nil)
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer Flags: 0x0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer AudioBytes: 8192
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer pAudioData: 0x1f9e6da0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer PlayBegin: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer PlayLength: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopBegin: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopLength: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopCount: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer pContext: (nil)
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer 0x3c432b60: queued buffer 1 (8192
bytes), now 2 buffers held
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer 0x3c432b60, 0x595efe24, (nil)
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer Flags: 0x0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer AudioBytes: 8192
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer pAudioData: 0x1f9e8da0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer PlayBegin: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer PlayLength: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopBegin: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopLength: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopCount: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer pContext: (nil)
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer 0x3c432b60: queued buffer 2 (8192
bytes), now 3 buffers held
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer 0x3c432b60, 0x595efe24, (nil)
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer Flags: 0x0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer AudioBytes: 8192
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer pAudioData: 0x1f9eada0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer PlayBegin: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer PlayLength: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopBegin: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopLength: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer LoopCount: 0
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer pContext: (nil)
007c:trace:xaudio2:XA2SRC_SubmitSourceBuffer 0x3c432b60: queued buffer 3 (8192
bytes), now 4 buffers held
007c:trace:xaudio2:do_engine_tick *** (2) src=(nil)
007c:trace:seh:raise_exception code=c0000005 flags=0 addr=0xf59ef795
ip=f59ef795 tid=007c
007c:trace:seh:raise_exception  info[0]=00000000
007c:trace:seh:raise_exception  info[1]=00000f70
007c:trace:seh:raise_exception  eax=595efd48 ebx=f59ff000 ecx=00000000
edx=595f2b38 esi=f59ff000 edi=00000000
007c:trace:seh:raise_exception  ebp=595efe68 esp=595efd14 cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00010202
007c:trace:seh:call_stack_handlers calling handler at 0x7bca5470 code=c0000005
flags=0 
--- snip ---

Wargaming client 'IXAudio2VoiceCallback::OnVoiceProcessingPassStart' callback
calls at one point 'IXAudio2SourceVoice::GetState' method but with the Flags(!)
parameter passed -> XAudio 2.8+ ABI! Wine implements the old-style XAudio 2.7
ABI and uses binary compatibility interface/method wrappers.

The client's incorrect XAudio 2.7 ABI usage causes one of the callee saved regs
getting corrupted. It's not causing a stack imbalance on return due to the way
the function prolog code is setting up the stack but it causes NULL pointer
exception in the caller (local var -> register).

Disassembly of World of Warships 0.7.x client
'XAudio2VoiceCallback::OnVoiceProcessingPassStart' callback:

--- snip ---
00A32DF0  55               PUSH EBP
00A32DF1  8BEC             MOV EBP,ESP
00A32DF3  83EC 34          SUB ESP,34
00A32DF6  53               PUSH EBX
00A32DF7  56               PUSH ESI
00A32DF8  8B75 08          MOV ESI,DWORD PTR SS:[EBP+8]
00A32DFB  8D55 F0          LEA EDX,DWORD PTR SS:[EBP-10]
00A32DFE  57               PUSH EDI              ; caller local 'src' reg val
00A32DFF  6A 00            PUSH 0                ; flags -> problem!
00A32E01  52               PUSH EDX              ; pVoiceState
00A32E02  8B46 18          MOV EAX,DWORD PTR DS:[ESI+18]
00A32E05  50               PUSH EAX              ; iface
00A32E06  8B08             MOV ECX,DWORD PTR DS:[EAX]
; xaudio2_.XA27SRC_GetState -> compat wrapper!
00A32E08  FF51 64          CALL DWORD PTR DS:[ECX+64] 
00A32E0B  0FB74E 48        MOVZX ECX,WORD PTR DS:[ESI+48] 
00A32E0F  33D2             XOR EDX,EDX
00A32E11  8B45 0C          MOV EAX,DWORD PTR SS:[EBP+C]
00A32E14  33FF             XOR EDI,EDI
00A32E16  F7F1             DIV ECX
00A32E18  8B4E 44          MOV ECX,DWORD PTR DS:[ESI+44]
00A32E1B  8B55 F4          MOV EDX,DWORD PTR SS:[EBP-C]
00A32E1E  8BD8             MOV EBX,EAX
00A32E20  2BCA             SUB ECX,EDX
00A32E22  74 66            JE SHORT WorldOfW.00A32E8A
00A32E24  0FB74E 48        MOVZX ECX,WORD PTR DS:[ESI+48]
00A32E28  33C0             XOR EAX,EAX
00A32E2A  8945 D4          MOV DWORD PTR SS:[EBP-2C],EAX
00A32E2D  8945 CC          MOV DWORD PTR SS:[EBP-34],EAX
00A32E30  8945 D8          MOV DWORD PTR SS:[EBP-28],EAX
00A32E33  8945 DC          MOV DWORD PTR SS:[EBP-24],EAX
00A32E36  8945 E0          MOV DWORD PTR SS:[EBP-20],EAX
00A32E39  8945 E4          MOV DWORD PTR SS:[EBP-1C],EAX
00A32E3C  8945 E8          MOV DWORD PTR SS:[EBP-18],EAX
00A32E3F  8945 EC          MOV DWORD PTR SS:[EBP-14],EAX
00A32E42  0FB705 24165D01  MOVZX EAX,WORD PTR DS:[15D1624]
00A32E49  0FAFC8           IMUL ECX,EAX
00A32E4C  894D D0          MOV DWORD PTR SS:[EBP-30],ECX
00A32E4F  0FB74E 22        MOVZX ECX,WORD PTR DS:[ESI+22]
00A32E53  8B448E 24        MOV EAX,DWORD PTR DS:[ESI+ECX*4+24]
00A32E57  8945 D4          MOV DWORD PTR SS:[EBP-2C],EAX
00A32E5A  8D41 01          LEA EAX,DWORD PTR DS:[ECX+1]
00A32E5D  66:8946 22       MOV WORD PTR DS:[ESI+22],AX
00A32E61  66:83F8 08       CMP AX,8
00A32E65  75 06            JNZ SHORT WorldOfW.00A32E6D
00A32E67  33C0             XOR EAX,EAX
00A32E69  66:8946 22       MOV WORD PTR DS:[ESI+22],AX
00A32E6D  8B46 18          MOV EAX,DWORD PTR DS:[ESI+18]
00A32E70  8D55 CC          LEA EDX,DWORD PTR SS:[EBP-34]
00A32E73  6A 00            PUSH 0
00A32E75  52               PUSH EDX
00A32E76  50               PUSH EAX
00A32E77  8B08             MOV ECX,DWORD PTR DS:[EAX]
; xaudio2_.XA27SRC_SubmitSourceBuffer
00A32E79  FF51 54          CALL DWORD PTR DS:[ECX+54] 
00A32E7C  FF45 F4          INC DWORD PTR SS:[EBP-C]
00A32E7F  47               INC EDI
00A32E80  8B46 44          MOV EAX,DWORD PTR DS:[ESI+44]
00A32E83  8B55 F4          MOV EDX,DWORD PTR SS:[EBP-C]
00A32E86  2BC2             SUB EAX,EDX
00A32E88  75 9A            JNZ SHORT WorldOfW.00A32E24
00A32E8A  8B45 F8          MOV EAX,DWORD PTR SS:[EBP-8]
00A32E8D  0B45 FC          OR EAX,DWORD PTR SS:[EBP-4]
00A32E90  74 12            JE SHORT WorldOfW.00A32EA4
00A32E92  0FB705 24165D01  MOVZX EAX,WORD PTR DS:[15D1624]
00A32E99  0FAFC7           IMUL EAX,EDI
00A32E9C  3BC3             CMP EAX,EBX
00A32E9E  73 04            JNB SHORT WorldOfW.00A32EA4
00A32EA0  C646 4A 01       MOV BYTE PTR DS:[ESI+4A],1
00A32EA4  0FB705 90146B01  MOVZX EAX,WORD PTR DS:[16B1490]
00A32EAB  5F               POP EDI                    ; caller EDI -> NULL
00A32EAC  5E               POP ESI
00A32EAD  5B               POP EBX
00A32EAE  3BD0             CMP EDX,EAX
00A32EB0  73 0E            JNB SHORT WorldOfW.00A32EC0
00A32EB2  8B0D 64126B01    MOV ECX,DWORD PTR DS:[16B1264]
00A32EB8  8D49 4C          LEA ECX,DWORD PTR DS:[ECX+4C]
00A32EBB  E8 1049F8FF      CALL WorldOfW.009B77D0
00A32EC0  8BE5             MOV ESP,EBP
00A32EC2  5D               POP EBP
00A32EC3  C2 0800          RETN 8
--- snip ---

The Wargaming clients load the XAudio2 variant depending on the Windows
version:

--- snip ---
00A32C30  PUSH EBP
00A32C31  MOV EBP,ESP
00A32C33  SUB ESP,11C
00A32C39  PUSH ESI
00A32C3A  PUSH 100
00A32C3F  LEA EAX,DWORD PTR SS:[EBP-108]
00A32C45  MOV DWORD PTR SS:[EBP-11C],11C
00A32C4F  PUSH 0
00A32C51  PUSH EAX
00A32C52  MOV DWORD PTR SS:[EBP-118],0
00A32C5C  MOV DWORD PTR SS:[EBP-114],0
00A32C66  MOV DWORD PTR SS:[EBP-110],0
00A32C70  MOV DWORD PTR SS:[EBP-10C],0
00A32C7A  CALL <JMP.&VCRUNTIME140.memset>
00A32C7F  MOV ESI,DWORD PTR DS:[<&KERNEL32.VerSetConditionMask>]
00A32C85  ADD ESP,0C
00A32C88  XOR EAX,EAX
00A32C8A  MOV DWORD PTR SS:[EBP-8],EAX
00A32C8D  MOV DWORD PTR SS:[EBP-4],EAX
00A32C90  PUSH 3
00A32C92  PUSH 20
00A32C94  PUSH 3
00A32C96  PUSH 1
00A32C98  PUSH 3
00A32C9A  PUSH 2
00A32C9C  PUSH EAX
00A32C9D  PUSH EAX
00A32C9E  CALL ESI
00A32CA0  PUSH EDX
00A32CA1  PUSH EAX
00A32CA2  CALL ESI
00A32CA4  PUSH EDX
00A32CA5  PUSH EAX
00A32CA6  CALL ESI
00A32CA8  MOVZX ECX,WORD PTR SS:[EBP+8]
00A32CAC  PUSH EDX
00A32CAD  MOV DWORD PTR SS:[EBP-118],ECX
00A32CB3  MOVZX ECX,WORD PTR SS:[EBP+C]
00A32CB7  PUSH EAX
00A32CB8  MOV DWORD PTR SS:[EBP-114],ECX
00A32CBE  LEA EAX,DWORD PTR SS:[EBP-11C]
00A32CC4  MOV CX,WORD PTR SS:[EBP+10]
00A32CC8  PUSH 23
00A32CCA  PUSH EAX
00A32CCB  MOV WORD PTR SS:[EBP-8],CX
00A32CCF  CALL DWORD PTR DS:[<&KERNEL32.VerifyVersionInfoW>]
00A32CD5  NEG EAX
00A32CD7  POP ESI
00A32CD8  SBB EAX,EAX
00A32CDA  NEG EAX
00A32CDC  MOV ESP,EBP
00A32CDE  POP EBP
00A32CDF  RETN
00A32CE0  PUSH EBP
00A32CE1  MOV EBP,ESP
00A32CE3  PUSH ECX
00A32CE4  PUSH ESI
00A32CE5  PUSH 0
00A32CE7  PUSH 0
00A32CE9  PUSH 0A
00A32CEB  MOV DWORD PTR SS:[EBP-4],0
00A32CF2  MOV DWORD PTR DS:[16B275C],0
00A32CFC  CALL WorldOfW.00A32C30
00A32D01  MOV ESI,DWORD PTR DS:[<&KERNEL32.LoadLibraryA>]
00A32D07  ADD ESP,0C
00A32D0A  TEST AL,AL
00A32D0C  JE SHORT WorldOfW.00A32D24
00A32D0E  PUSH WorldOfW.011CDF30          ; ASCII "XAudio2_9.dll"
00A32D13  CALL ESI
00A32D15  MOV DWORD PTR SS:[EBP-4],EAX
00A32D18  MOV DWORD PTR DS:[16B275C],3
00A32D22  JMP SHORT WorldOfW.00A32D27
00A32D24  MOV EAX,DWORD PTR SS:[EBP-4]
00A32D27  TEST EAX,EAX
00A32D29  JNZ SHORT WorldOfW.00A32DA5
00A32D2B  PUSH EAX
00A32D2C  PUSH 2
00A32D2E  PUSH 6
00A32D30  CALL WorldOfW.00A32C30
00A32D35  ADD ESP,0C
00A32D38  TEST AL,AL
00A32D3A  JE SHORT WorldOfW.00A32D52
00A32D3C  PUSH WorldOfW.011CDF40         ; ASCII "XAudio2_8.dll"
00A32D41  CALL ESI
00A32D43  MOV DWORD PTR SS:[EBP-4],EAX
00A32D46  MOV DWORD PTR DS:[16B275C],2
00A32D50  JMP SHORT WorldOfW.00A32D55
00A32D52  MOV EAX,DWORD PTR SS:[EBP-4]
00A32D55  TEST EAX,EAX
00A32D57  JNZ SHORT WorldOfW.00A32DA5
00A32D59  PUSH EAX
00A32D5A  PUSH 1
00A32D5C  PUSH 6
00A32D5E  CALL WorldOfW.00A32C30
00A32D63  ADD ESP,0C
00A32D66  TEST AL,AL
00A32D68  JE SHORT WorldOfW.00A32DA2
00A32D6A  PUSH WorldOfW.011CDF50         ; ASCII "XAudio2_7.dll"
00A32D6F  CALL ESI
00A32D71  CMP BYTE PTR DS:[16B276C],0
00A32D78  MOV DWORD PTR SS:[EBP-4],EAX
00A32D7B  MOV DWORD PTR DS:[16B275C],1
00A32D85  JNZ SHORT WorldOfW.00A32DA5
00A32D87  LEA EAX,DWORD PTR SS:[EBP-4]
00A32D8A  PUSH EAX
00A32D8B  PUSH WorldOfW.011CDF50         ; ASCII "XAudio2_7.dll"
00A32D90  PUSH 1
00A32D92  CALL DWORD PTR DS:[<&KERNEL32.GetModuleHandleExA>]
00A32D98  CMP EAX,1
00A32D9B  SETE BYTE PTR DS:[16B276C]
00A32DA2  MOV EAX,DWORD PTR SS:[EBP-4]
00A32DA5  POP ESI
00A32DA6  MOV ESP,EBP
00A32DA8  POP EBP
00A32DA9  RETN
--- snip---

Wine source:

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/xaudio2_7/xaudio_dll.c#l2400

--- snip ---
2400 static void do_engine_tick(IXAudio2Impl *This)
2401 {
2402     BYTE *buf;
2403     XA2SourceImpl *src;
2404     HRESULT hr;
2405     UINT32 nframes, i, pad;
2406 
2407     /* maintain up to 3 periods in mmdevapi */
2408     hr = IAudioClient_GetCurrentPadding(This->aclient, &pad);
2409     if(FAILED(hr)){
2410         WARN("GetCurrentPadding failed: 0x%x\n", hr);
2411         return;
2412     }
2413 
2414     nframes = This->period_frames * 3 - pad;
2415 
2416     TRACE("frames available: %u\n", nframes);
2417 
2418     if(nframes < This->period_frames)
2419         return;
2420 
2421     if(!nframes)
2422         return;
2423 
2424     for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
2425         IXAudio2EngineCallback_OnProcessingPassStart(This->cbs[i]);
2426 
2427     LIST_FOR_EACH_ENTRY(src, &This->source_voices, XA2SourceImpl, entry){
2428         ALint st = 0;
2429 
2430         EnterCriticalSection(&src->lock);
2431 
2432         if(!src->in_use){
2433             LeaveCriticalSection(&src->lock);
2434             continue;
2435         }
2436 
2437         if(src->cb && This->running){
2438 #if XAUDIO2_VER == 0
2439            
IXAudio20VoiceCallback_OnVoiceProcessingPassStart((IXAudio20VoiceCallback*)src->cb);
2440 #else
2441             UINT32 underrun;
2442             underrun = get_underrun_warning(src);
2443             if(underrun > 0)
2444                 TRACE("Calling OnVoiceProcessingPassStart with
BytesRequired: %u\n", underrun);
2445             IXAudio2VoiceCallback_OnVoiceProcessingPassStart(src->cb,
underrun);
2446 #endif
2447         }
2448 
2449         update_source_state(src);

--- snip ---

'src' is held in EDI register within loop and gets wrong value (NULL) restored
from client provided 'OnVoiceProcessingPassStart' callback due to ABI/compat
mismatch -> line 2449 -> src == NULL.

The compat wrapper (called by callback):

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/xaudio2_7/compat.c#l839

--- snip ---
 839 static void WINAPI XA27SRC_GetState(IXAudio27SourceVoice *iface,
 840         XAUDIO2_VOICE_STATE *pVoiceState)
 841 {
 842     XA2SourceImpl *This = impl_from_IXAudio27SourceVoice(iface);
 843     return IXAudio2SourceVoice_GetState(&This->IXAudio2SourceVoice_iface,
pVoiceState, 0);
 844 }
--- snip ---

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/xaudio2_7/xaudio_dll.c#l743

--- snip ---
 743 static void WINAPI XA2SRC_GetState(IXAudio2SourceVoice *iface,
 744         XAUDIO2_VOICE_STATE *pVoiceState, UINT32 Flags)
 745 {
 746     XA2SourceImpl *This = impl_from_IXAudio2SourceVoice(iface);
 747 
 748     TRACE("%p, %p, 0x%x\n", This, pVoiceState, Flags);
 749 
 750     EnterCriticalSection(&This->lock);
 751 
 752     if(!(Flags & XAUDIO2_VOICE_NOSAMPLESPLAYED))
 753         pVoiceState->SamplesPlayed = This->played_frames;
 754     else
 755         pVoiceState->SamplesPlayed = 0;
 756 
 757     if(This->nbufs)
 758         pVoiceState->pCurrentBufferContext =
This->buffers[This->first_buf].xa2buffer.pContext;
 759     else
 760         pVoiceState->pCurrentBufferContext = NULL;
 761 
 762     pVoiceState->BuffersQueued = This->nbufs;
 763 
 764     LeaveCriticalSection(&This->lock);
 765 
 766     TRACE("returning %s, queued: %u\n",
wine_dbgstr_longlong(pVoiceState->SamplesPlayed), This->nbufs);
 767 }
--- snip ---

Microsoft docs:

https://docs.microsoft.com/en-us/windows/desktop/api/xaudio2/nf-xaudio2-ixaudio2sourcevoice-getstate

--- quote ---
IXAudio2SourceVoice::GetState method

Returns the voice's current cursor position data.
Syntax

void GetState(
  XAUDIO2_VOICE_STATE *pVoiceState,
  UINT32 Flags        X2DEFAULT
);

Parameters

pVoiceState

Pointer to an XAUDIO2_VOICE_STATE structure containing the state of the voice.

X2DEFAULT

TBD
Return Value

This method does not return a value.
Remarks

If a client needs to get the correlated positions of several voices (for
example, to know exactly which sample of a given voice is playing when a given
sample of another voice is playing), it must make GetState calls in an XAudio2
engine callback. This ensures that none of the voices advance while the calls
are being made. See the XAudio2 Callbacks overview for information about using
XAudio2 callbacks.

Note that the DirectX SDK versions of XAUDIO2 do not take the Flags parameter
for GetState.

Platform Requirements

Windows 10 (XAudio2.9); Windows 8, Windows Phone 8 (XAudio 2.8); DirectX SDK
(XAudio 2.7) 
--- quote ---

https://docs.microsoft.com/en-us/windows/desktop/xaudio2/xaudio2-versions

--- snip ---
XAudio 2.7 and earlier (Windows 7)

All previous versions of XAudio2 for use in apps have been provided as
redistributable DLLs in the DirectX SDK. The first version of XAudio2, XAudio2
2.0, shipped in the March 2008 release of the DirectX SDK. The last version to
ship in the DirectX SDK was XAudio2 2.7, available in the last release of the
DirectX SDK in June 2010.

For access to historical versions of XAudio2, download the DirectX SDK from the
Microsoft Download Center. The June 2010 release of the DirectX SDK is
available at:

http://www.microsoft.com/download/en/details.aspx?id=6812

Previous versions of XAudio2 cannot be used to build Windows Store apps for
Windows 8.
--- snip ---

The vendor Wargaming messed this up, calling the DirectX SDK XAudio 2.7 version
of 'IXAudio2SourceVoice::GetState' with the Flags parameter included from the
callback. I havent seen different callback implementations, depending on the
XAudio 2.x version .. but I didn't look very hard.

It just works by chance with native (SDK) XAudio 2.7 because EDI isn't used by
caller(s), corrupting it in callback has no effect.

IMHO 'INVALID' or 'WONTFIX' unless you want to write an assembly wrapper for
invoking the callbacks to fix these broken apps/games.

$ wine --version
wine-3.17-162-gb0c5a77e26

Regards

-- 
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