diff options
Diffstat (limited to 'alf/alfbutton.cpp')
| -rw-r--r-- | alf/alfbutton.cpp | 28 |
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); |
