https://bugs.winehq.org/show_bug.cgi?id=53682
--- Comment #9 from Kevin Puetz PuetzKevinA@JohnDeere.com --- Created attachment 73343 --> https://bugs.winehq.org/attachment.cgi?id=73343 patch adding TRACE(...) of the stack pointer
Here's a patch adding some additional TRACE() calls as you requested, but beware this changes the scenario (same bug, but manifests at a different stack):
WINEDEBUG=trace+seh wineboot now shows
0040:trace:seh:KeUserModeCallback sp=0x21f500, syscall_frame=0x21f540 0040:trace:seh:KiUserCallbackDispatcher sp=000000000011F660 0040:trace:seh:NtUserCallOneParam sp=0x21f500
1. So we can see that syscall_frame is not at the bottom of the stack in KeUserModeCallback 2. KiUserCallbackDispatcher is called back on the user stack, but the func it's invoking is a syscall, so we go back through _wine_syscall_dispatcher and a 3. By the time the syscall machinery gets to win32u!NtUserCallOneParam, we are back on the original (syscall) stack, with exactly the same sp==syscall_frame. NtUserCallOneParam's prologue pushes its callee-save stuff, (same amount as KeUserModeCallback), and we enter the C body with the same sp as KeUserModeCallback's body, having trashed the values it saved with those of .
*with* these traces executing, basically the same thing happens, but earlier - ntdll!__wine_dbg_write is *also* a -syscall, so now the first corruption now happens during the TRACE() call added to KiUserCallbackDispatcher, as the prologue of __wine_dbg_write now does the smashing. But it uses fewer registers and so it only smashes 0x21f530...0x21f53f, rather than the whole thing. its call to __GI___libc_write smashes the rest.