Module: wine
Branch: master
Commit: f9f9481b67f7ecddd7cb5ddd308a9338d26445e4
URL: https://gitlab.winehq.org/wine/wine/-/commit/f9f9481b67f7ecddd7cb5ddd308a93…
Author: Yuxuan Shui <yshui(a)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)
{