summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alf/alfbutton.cpp28
1 files changed, 22 insertions, 6 deletions
diff --git a/alf/alfbutton.cpp b/alf/alfbutton.cpp
index 6b0974b..292c913 100644
--- a/alf/alfbutton.cpp
+++ b/alf/alfbutton.cpp
@@ -707,12 +707,30 @@ ALF_NtButton_Create(HWND win, WORD id, int x, int y, const TCHAR *text)
typedef struct {
WNDPROC origWndProc;
BOOL isDefault;
+ BYTE thunk[12];
} ALFClassicButtonPriv;
+static LRESULT CALLBACK
+ALF_ClassicButton_WndProc(ALFClassicButtonPriv *priv, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
static ALFClassicButtonPriv *
ALF_ClassicButton_InitializePriv(void)
{
- return ALF_New(ALFClassicButtonPriv, 1);
+ ALFClassicButtonPriv *priv = ALF_New(ALFClassicButtonPriv, 1);
+
+ // HACK! use thunk since we want to leave GWLP_USERDATA to the control user
+ // this doesn't work on non-x86 and also doesn't work with DEP,
+ // but it's ok since that code is only running on Win9x and NT4
+ priv->thunk[0] = 0x58; // pop eax
+ priv->thunk[1] = 0x68; // push ptr
+ DWORD privptr = (DWORD)(ULONG_PTR)priv;
+ CopyMemory(&priv->thunk[2], &privptr, 4);
+ priv->thunk[6] = 0x50; // push eax
+ priv->thunk[7] = 0xe9; // jmp
+ DWORD procptr = (DWORD)((ULONG_PTR)ALF_ClassicButton_WndProc - ((ULONG_PTR)priv->thunk + sizeof(priv->thunk)));
+ CopyMemory(&priv->thunk[8], &procptr, 4);
+
+ return priv;
}
static void
@@ -819,9 +837,8 @@ ALF_ClassicButton_Paint(HWND hwnd, ALFClassicButtonPriv *priv, DRAWITEMSTRUCT *d
}
static LRESULT CALLBACK
-ALF_ClassicButton_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ALF_ClassicButton_WndProc(ALFClassicButtonPriv *priv, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- ALFClassicButtonPriv *priv = (ALFClassicButtonPriv *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (!priv)
return DefWindowProc(hwnd, uMsg, wParam, lParam);
@@ -851,7 +868,6 @@ ALF_ClassicButton_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
} else if (uMsg == WM_DESTROY) {
WNDPROC o = priv->origWndProc;
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)o);
- SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
ALF_ClassicButton_FreePriv(priv);
return CallWindowProc(o, hwnd, uMsg, wParam, lParam);
}
@@ -873,8 +889,8 @@ ALF_ClassicButton_Create(HWND win, WORD id, int x, int y, const TCHAR *text)
NULL);
ALFClassicButtonPriv *priv = ALF_ClassicButton_InitializePriv();
- SetWindowLongPtr(hwndButton, GWLP_USERDATA, (LONG_PTR)priv);
- priv->origWndProc = (WNDPROC)SetWindowLongPtr(hwndButton, GWLP_WNDPROC, (LONG_PTR)ALF_ClassicButton_WndProc);
+ priv->origWndProc = (WNDPROC)GetWindowLongPtr(hwndButton, GWLP_WNDPROC);
+ SetWindowLongPtr(hwndButton, GWLP_WNDPROC, (LONG_PTR)priv->thunk);
ALF_AddWidget(win, x, y, hwndButton, 5625, 1725, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT);