https://bugs.winehq.org/show_bug.cgi?id=49178
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |focht@gmx.net Component|-unknown |wtsapi32 Summary|Spitfire Audio crashes on |Spitfire Audio 3.x crashes |start |on start due to | |'WTSQuerySessionInformation | |A' stub not initializing | |out parameters
--- Comment #17 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming. The app doesn't care about WTSQuerySessionInformationA() API return value but rather looks at out parameters. Wine's WTSQuerySessionInformationA() is a stub that doesn't do anything in contrast to WTSQuerySessionInformationW() which implements WTSUserName info class.
The app working with Wine built with CFLAGS="-O0" is just coincidence, the "out" buffer parameter is NULL before + after return (different stack layout / init values).
Relevant app disassembly:
--- snip --- ... 00959F50 | push ebp | 00959F51 | mov ebp,esp | 00959F53 | sub esp,410 | 00959F59 | mov eax,dword ptr ds:[12B8474] | 00959F5E | xor eax,ebp | 00959F60 | mov dword ptr ss:[ebp-4],eax | 00959F63 | push esi | 00959F64 | lea eax,dword ptr ss:[ebp-40C] | 00959F6A | mov dword ptr ss:[ebp-410],0 | 00959F74 | push eax | &BytesReturned 00959F75 | lea eax,dword ptr ss:[ebp-408] | 00959F7B | mov esi,ecx | 00959F7D | push eax | &Buffer 00959F7E | push 5 | WTSInfoClass 00959F80 | push FFFFFFFF | SessionId 00959F82 | mov dword ptr ss:[ebp-40C],esi | 00959F88 | push 0 | hServer 00959F8A | mov dword ptr ss:[ebp-40C],0 | 00959F94 | call dword ptr ds:[<&WTSQuerySessionInformationA>] | 00959F9A | push dword ptr ss:[ebp-408] | Buffer 00959FA0 | mov edx,dword ptr ss:[ebp-40C] | BytesReturned 00959FA6 | mov ecx,esi | 00959FA8 | call spitfire audio.68EBB0 | ... 0068EBB0 | push ebp | 0068EBB1 | mov ebp,esp | 0068EBB3 | sub esp,8 | 0068EBB6 | mov eax,dword ptr ss:[ebp+8] | Buffer 0068EBB9 | mov dword ptr ss:[ebp-8],ecx | 0068EBBC | push esi | 0068EBBD | mov esi,edx | BytesReturned 0068EBBF | test eax,eax | Buffer != NULL? 0068EBC1 | je spitfire audio.68EC50 | 0068EBC7 | cmp byte ptr ds:[eax],0 | Buffer[0] != '\0'? 0068EBCA | je spitfire audio.68EC50 | 0068EBD0 | test esi,esi | 0068EBD2 | je spitfire audio.68EC50 | --- snip ---
Stack layout/values before API call
--- snip --- 0031F804 00000000 hServer 0031F808 FFFFFFFF SessionId 0031F80C 00000005 WTSInfoClass 0031F810 0031F824 &Buffer 0031F814 0031F820 &BytesReturned 0031F818 0031FC40 0031F81C 00000000 0031F820 00000000 BytesReturned 0031F824 00000002 Buffer (garbage) <-- will cause crash on deref 0031F828 00000060 0031F82C 00000000 0031F830 00000000 0031F834 00000000 0031F838 00000000 ... --- snip ---
Wine source:
https://source.winehq.org/git/wine.git/blob/ba920246e502afe7bc664c1881d528a2...
--- snip --- 287 /************************************************************ 288 * WTSQuerySessionInformationA (WTSAPI32.@) 289 */ 290 BOOL WINAPI WTSQuerySessionInformationA( 291 HANDLE hServer, 292 DWORD SessionId, 293 WTS_INFO_CLASS WTSInfoClass, 294 LPSTR* Buffer, 295 DWORD* BytesReturned) 296 { 297 /* FIXME: Forward request to winsta.dll::WinStationQueryInformationA */ 298 FIXME("Stub %p 0x%08x %d %p %p\n", hServer, SessionId, WTSInfoClass, 299 Buffer, BytesReturned); 300 301 return FALSE; 302 } 303 304 /************************************************************ 305 * WTSQuerySessionInformationW (WTSAPI32.@) 306 */ 307 BOOL WINAPI WTSQuerySessionInformationW( 308 HANDLE hServer, 309 DWORD SessionId, 310 WTS_INFO_CLASS WTSInfoClass, 311 LPWSTR* Buffer, 312 DWORD* BytesReturned) 313 { 314 /* FIXME: Forward request to winsta.dll::WinStationQueryInformationW */ 315 FIXME("Stub %p 0x%08x %d %p %p\n", hServer, SessionId, WTSInfoClass, 316 Buffer, BytesReturned); 317 318 if (WTSInfoClass == WTSUserName) 319 { 320 WCHAR *username; 321 DWORD count = 0; 322 323 GetUserNameW(NULL, &count); 324 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; 325 if (!(username = heap_alloc(count * sizeof(WCHAR)))) return FALSE; 326 GetUserNameW(username, &count); 327 *Buffer = username; 328 *BytesReturned = count * sizeof(WCHAR); 329 return TRUE; 330 } 331 return FALSE; 332 } --- snip ---
Possible options:
(1) just zero-init out parameters but don't implement anything
(2) duplicate the code for WTSUserName info class handling from WTSQuerySessionInformationW() but as ANSI
(3) make WTSQuerySessionInformationA() call WTSQuerySessionInformationW() with W->A conversion of buffer
(4) combination of (1) and (2) or (3) to ensure other buggy apps don't crash as well when querying for other unimplemented info classes, looking at out parameters without checking BOOL return value first.
Depending on the solution taken, the ticket summary should be adapted before release. Currently it refers to (1).
$ sha1sum SpitfireAudioWinSetup-3.2.6.exe c3c36a977c3c85d65b60c28de6074539a95da12c SpitfireAudioWinSetup-3.2.6.exe
$ du -sh SpitfireAudioWinSetup-3.2.6.exe 4.2M SpitfireAudioWinSetup-3.2.6.exe
$ wine --version wine-5.9-23-gba920246e5
Regards