Module: wine Branch: master Commit: f9f9481b67f7ecddd7cb5ddd308a9338d26445e4 URL: https://gitlab.winehq.org/wine/wine/-/commit/f9f9481b67f7ecddd7cb5ddd308a933...
Author: Yuxuan Shui yshui@codeweavers.com Date: Fri Sep 15 12:32:06 2023 +0100
user32: Add hotpatchable wrapper for GetWindowLongA.
ntlea for some reason expects GetWindowLongA to start with a "push $-2", and will try to skip over this instruction. If we don't anticipate this, it will ended up either skipping over critical instructions, or on a desync address.
---
dlls/user32/win.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 28cf40441d9..7eaaa41e951 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -888,7 +888,28 @@ WORD WINAPI GetWindowWord( HWND hwnd, INT offset ) /********************************************************************** * GetWindowLongA (USER32.@) */ -LONG WINAPI GetWindowLongA( HWND hwnd, INT offset ) + +#ifdef __i386__ + +/* This wrapper is here to workaround a ntlea quirk. First of all, ntlea + * checks whether GetWindowLongA starts with the Win32 hotpatchable prologue, + * if it can find that, it will use a hooking strategy more difficult for us + * to deal with. Secondly, it assumes what follows the prologue is a `pushl $-2`, + * and will try to skip over this instruction when calling `GetWindowLongA`, + * (i.e. it tries to jump to `GetWindowLongA + 7`, 5 bytes for the prologue, 2 + * bytes for the `pushl`.). We have to anticipate that and make sure the result + * of doing this won't be a messed up stack, or a desynced PC. + */ +__ASM_STDCALL_FUNC( GetWindowLongA, 8, + ".byte 0x8b, 0xff, 0x55, 0x8b, 0xec\n" /* Win32 hotpatchable prologue. */ + "pushl $-2\n" + "addl $4, %esp\n" + "popl %ebp\n" + "jmp " __ASM_STDCALL("get_window_longA", 8) ) +LONG WINAPI get_window_longA( HWND hwnd, INT offset ) +#else +LONG WINAPI DECLSPEC_HOTPATCH GetWindowLongA( HWND hwnd, INT offset ) +#endif { switch (offset) {