From dcc76a154dec7dd35e4299c0e77a58efdfbf3d8a Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Sun, 8 Sep 2024 19:14:58 +0200 Subject: [PATCH] add experimental WH_GETMESSAGE hook --- inc/mouse.h | 5 +- src/dd.c | 3 + src/dllmain.c | 2 + src/mouse.c | 171 +++++++++++++++++++++++++++++++++++++++++++-- src/winapi_hooks.c | 168 +------------------------------------------- src/wndproc.c | 94 +------------------------ 6 files changed, 179 insertions(+), 264 deletions(-) diff --git a/inc/mouse.h b/inc/mouse.h index 1181ac2..65ef0da 100644 --- a/inc/mouse.h +++ b/inc/mouse.h @@ -1,9 +1,12 @@ #ifndef MOUSE_H #define MOUSE_H +void mouse_hook_init(); +void mouse_hook_exit(); void mouse_lock(); void mouse_unlock(); -LRESULT CALLBACK mouse_hook_proc(int Code, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK mouse_gm_hook_proc(int code, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK mouse_hook_proc(int code, WPARAM wParam, LPARAM lParam); extern BOOL g_mouse_locked; extern HHOOK g_mouse_hook; diff --git a/src/dd.c b/src/dd.c index c61f1cc..b7d535b 100644 --- a/src/dd.c +++ b/src/dd.c @@ -988,6 +988,8 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl g_ddraw.mouse.unscale_y = ((float)(g_ddraw.height - 1) / (g_ddraw.render.viewport.height - 1)); } + TRACE("sdm unscale_x %.6f, y=%.6f\n", g_ddraw.mouse.unscale_x, g_ddraw.mouse.unscale_y); + g_ddraw.mouse.x_adjust = g_ddraw.render.viewport.x; g_ddraw.mouse.y_adjust = g_ddraw.render.viewport.y; @@ -1365,6 +1367,7 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags) g_ddraw.gui_thread_id = GetWindowThreadProcessId(g_ddraw.hwnd, NULL); keyboard_hook_init(); + mouse_hook_init(); if (!g_ddraw.render.hdc) { diff --git a/src/dllmain.c b/src/dllmain.c index 76090f9..fa8e2d1 100644 --- a/src/dllmain.c +++ b/src/dllmain.c @@ -13,6 +13,7 @@ #include "utils.h" #include "versionhelpers.h" #include "keyboard.h" +#include "mouse.h" /* export for cncnet cnc games */ @@ -140,6 +141,7 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) indeo_disable(); timeEndPeriod(1); keyboard_hook_exit(); + mouse_hook_exit(); dinput_hook_exit(); hook_exit(); break; diff --git a/src/mouse.c b/src/mouse.c index 46aca13..cbb976b 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -1,15 +1,45 @@ #include +#include +#include #include "debug.h" #include "winapi_hooks.h" #include "dd.h" #include "hook.h" #include "utils.h" #include "config.h" +#include "mouse.h" BOOL g_mouse_locked; HHOOK g_mouse_hook; HOOKPROC g_mouse_proc; +static HHOOK g_mouse_gm_hook; + +void mouse_hook_init() +{ + if (g_mouse_gm_hook && UnhookWindowsHookEx(g_mouse_gm_hook)) + { + g_mouse_gm_hook = NULL; + } + + if (!g_ddraw.gui_thread_id) + return; + + g_mouse_gm_hook = + real_SetWindowsHookExA( + WH_GETMESSAGE, + mouse_gm_hook_proc, + NULL, + g_ddraw.gui_thread_id); +} + +void mouse_hook_exit() +{ + if (g_mouse_gm_hook) + { + UnhookWindowsHookEx(g_mouse_gm_hook); + } +} void mouse_lock() { @@ -83,15 +113,146 @@ void mouse_unlock() } } -LRESULT CALLBACK mouse_hook_proc(int Code, WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK mouse_gm_hook_proc(int code, WPARAM wParam, LPARAM lParam) +{ + if (code < 0 || !lParam || !g_ddraw.width) + return CallNextHookEx(g_mouse_gm_hook, code, wParam, lParam); + + MSG* msg = (MSG*)lParam; + + if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &msg->pt)) + { + int x = max(msg->pt.x - g_ddraw.mouse.x_adjust, 0); + int y = max(msg->pt.y - g_ddraw.mouse.y_adjust, 0); + + if (g_config.adjmouse) + { + x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); + y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); + } + + msg->pt.x = min(x, g_ddraw.width - 1); + msg->pt.y = min(y, g_ddraw.height - 1); + } + else + { + msg->pt.x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0); + msg->pt.y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0); + } + + if (msg->hwnd != g_ddraw.hwnd) + return CallNextHookEx(g_mouse_gm_hook, code, wParam, lParam); + + switch (LOWORD(msg->message)) + { + /* button up messages reactivate cursor lock */ + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + { + if (!g_config.devmode && !g_mouse_locked) + { + int x = GET_X_LPARAM(msg->lParam); + int y = GET_Y_LPARAM(msg->lParam); + + if (x > g_ddraw.render.viewport.x + g_ddraw.render.viewport.width || + x < g_ddraw.render.viewport.x || + y > g_ddraw.render.viewport.y + g_ddraw.render.viewport.height || + y < g_ddraw.render.viewport.y) + { + x = g_ddraw.width / 2; + y = g_ddraw.height / 2; + } + else + { + x = (DWORD)((x - g_ddraw.render.viewport.x) * g_ddraw.mouse.unscale_x); + y = (DWORD)((y - g_ddraw.render.viewport.y) * g_ddraw.mouse.unscale_y); + } + + x = min(x, g_ddraw.width - 1); + y = min(y, g_ddraw.height - 1); + + InterlockedExchange((LONG*)&g_ddraw.cursor.x, x); + InterlockedExchange((LONG*)&g_ddraw.cursor.y, y); + + mouse_lock(); + + msg->message = MAKELONG(WM_NULL, HIWORD(msg->message)); + return 0; + } + /* fall through for lParam */ + } + /* down messages are ignored if we have no cursor lock */ + case WM_XBUTTONDBLCLK: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: + case WM_MOUSEWHEEL: + case WM_MOUSEHOVER: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_MOUSEMOVE: + { + if (!g_config.devmode && !g_mouse_locked) + { + msg->message = MAKELONG(WM_NULL, HIWORD(msg->message)); + return 0; + } + + if (LOWORD(msg->message) == WM_MOUSEWHEEL) + { + POINT pt = { GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam) }; + real_ScreenToClient(g_ddraw.hwnd, &pt); + msg->lParam = MAKELPARAM(pt.x, pt.y); + } + + int x = max(GET_X_LPARAM(msg->lParam) - g_ddraw.mouse.x_adjust, 0); + int y = max(GET_Y_LPARAM(msg->lParam) - g_ddraw.mouse.y_adjust, 0); + + if (g_config.adjmouse) + { + if (g_config.vhack && !g_config.devmode) + { + POINT pt = { 0, 0 }; + fake_GetCursorPos(&pt); + + x = pt.x; + y = pt.y; + } + else + { + x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); + y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); + } + } + + x = min(x, g_ddraw.width - 1); + y = min(y, g_ddraw.height - 1); + + InterlockedExchange((LONG*)&g_ddraw.cursor.x, x); + InterlockedExchange((LONG*)&g_ddraw.cursor.y, y); + + msg->lParam = MAKELPARAM(x, y); + + break; + } + } + + return CallNextHookEx(g_mouse_gm_hook, code, wParam, lParam); +} + +LRESULT CALLBACK mouse_hook_proc(int code, WPARAM wParam, LPARAM lParam) { if (!g_ddraw.ref) - return g_mouse_proc(Code, wParam, lParam); + return g_mouse_proc(code, wParam, lParam); - if (Code < 0 || (!g_config.devmode && !g_mouse_locked)) - return CallNextHookEx(g_mouse_hook, Code, wParam, lParam); + if (code < 0 || (!g_config.devmode && !g_mouse_locked)) + return CallNextHookEx(g_mouse_hook, code, wParam, lParam); fake_GetCursorPos(&((MOUSEHOOKSTRUCT*)lParam)->pt); - return g_mouse_proc(Code, wParam, lParam); + return g_mouse_proc(code, wParam, lParam); } diff --git a/src/winapi_hooks.c b/src/winapi_hooks.c index 68dc9dd..b51731b 100644 --- a/src/winapi_hooks.c +++ b/src/winapi_hooks.c @@ -612,146 +612,12 @@ HHOOK WINAPI fake_SetWindowsHookExA(int idHook, HOOKPROC lpfn, HINSTANCE hmod, D return result; } -BOOL HandleMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) -{ - if (g_ddraw.ref && g_ddraw.width) - { - switch (lpMsg->message) - { - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - { - if (!g_config.devmode && !g_mouse_locked) - { - int x = GET_X_LPARAM(lpMsg->lParam); - int y = GET_Y_LPARAM(lpMsg->lParam); - - if (x > g_ddraw.render.viewport.x + g_ddraw.render.viewport.width || - x < g_ddraw.render.viewport.x || - y > g_ddraw.render.viewport.y + g_ddraw.render.viewport.height || - y < g_ddraw.render.viewport.y) - { - x = g_ddraw.width / 2; - y = g_ddraw.height / 2; - } - else - { - x = (DWORD)((x - g_ddraw.render.viewport.x) * g_ddraw.mouse.unscale_x); - y = (DWORD)((y - g_ddraw.render.viewport.y) * g_ddraw.mouse.unscale_y); - } - - InterlockedExchange((LONG*)&g_ddraw.cursor.x, x); - InterlockedExchange((LONG*)&g_ddraw.cursor.y, y); - - mouse_lock(); - //return FALSE; - } - /* fall through for lParam */ - } - /* down messages are ignored if we have no cursor lock */ - case WM_XBUTTONDBLCLK: - case WM_XBUTTONDOWN: - case WM_XBUTTONUP: - case WM_MOUSEWHEEL: - case WM_MOUSEHOVER: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_MOUSEMOVE: - { - if (!g_config.devmode && !g_mouse_locked) - { - // Does not work with 'New Robinson' - //return FALSE; - } - - if (lpMsg->message == WM_MOUSEWHEEL) - { - POINT pt = { GET_X_LPARAM(lpMsg->lParam), GET_Y_LPARAM(lpMsg->lParam) }; - real_ScreenToClient(g_ddraw.hwnd, &pt); - lpMsg->lParam = MAKELPARAM(pt.x, pt.y); - } - - int x = max(GET_X_LPARAM(lpMsg->lParam) - g_ddraw.mouse.x_adjust, 0); - int y = max(GET_Y_LPARAM(lpMsg->lParam) - g_ddraw.mouse.y_adjust, 0); - - if (g_config.adjmouse) - { - if (g_config.vhack && !g_config.devmode) - { - POINT pt = { 0, 0 }; - fake_GetCursorPos(&pt); - - x = pt.x; - y = pt.y; - } - else - { - x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); - y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); - } - } - - x = min(x, g_ddraw.width - 1); - y = min(y, g_ddraw.height - 1); - - InterlockedExchange((LONG*)&g_ddraw.cursor.x, x); - InterlockedExchange((LONG*)&g_ddraw.cursor.y, y); - - lpMsg->lParam = MAKELPARAM(x, y); - - lpMsg->pt.x = x; - lpMsg->pt.y = y; - - break; - } - - } - } - - return TRUE; -} - BOOL WINAPI fake_GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) { if (g_ddraw.ref && (!hWnd || hWnd == g_ddraw.hwnd)) g_ddraw.last_msg_pull_tick = timeGetTime(); - BOOL result = real_GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); - - if (result && lpMsg && g_ddraw.ref && g_ddraw.hwnd && g_ddraw.width && !g_config.fixmousehook) - { - if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &lpMsg->pt)) - { - int x = max(lpMsg->pt.x - g_ddraw.mouse.x_adjust, 0); - int y = max(lpMsg->pt.y - g_ddraw.mouse.y_adjust, 0); - - if (g_config.adjmouse) - { - x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); - y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); - } - - lpMsg->pt.x = min(x, g_ddraw.width - 1); - lpMsg->pt.y = min(y, g_ddraw.height - 1); - } - else - { - lpMsg->pt.x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0); - lpMsg->pt.y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0); - } - - if (g_config.hook_getmessage) - { - HandleMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); - } - } - - return result; + return real_GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); } BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) @@ -759,37 +625,7 @@ BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT w if (g_ddraw.ref && (!hWnd || hWnd == g_ddraw.hwnd)) g_ddraw.last_msg_pull_tick = timeGetTime(); - BOOL result = real_PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); - - if (result && lpMsg && g_ddraw.ref && g_ddraw.hwnd && g_ddraw.width && !g_config.fixmousehook) - { - if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &lpMsg->pt)) - { - int x = max(lpMsg->pt.x - g_ddraw.mouse.x_adjust, 0); - int y = max(lpMsg->pt.y - g_ddraw.mouse.y_adjust, 0); - - if (g_config.adjmouse) - { - x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); - y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); - } - - lpMsg->pt.x = min(x, g_ddraw.width - 1); - lpMsg->pt.y = min(y, g_ddraw.height - 1); - } - else - { - lpMsg->pt.x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0); - lpMsg->pt.y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0); - } - - if (g_config.hook_peekmessage) - { - HandleMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); - } - } - - return result; + return real_PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } BOOL WINAPI fake_GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT* lpwndpl) diff --git a/src/wndproc.c b/src/wndproc.c index 0d65fce..030751e 100644 --- a/src/wndproc.c +++ b/src/wndproc.c @@ -22,7 +22,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam if (uMsg != WM_MOUSEMOVE && uMsg != WM_NCMOUSEMOVE && uMsg != WM_NCHITTEST && uMsg != WM_SETCURSOR && uMsg != WM_KEYUP && uMsg != WM_KEYDOWN && uMsg != WM_CHAR && uMsg != WM_DEADCHAR && uMsg != WM_INPUT && uMsg != WM_UNICHAR && uMsg != WM_IME_CHAR && uMsg != WM_IME_KEYDOWN && uMsg != WM_IME_KEYUP && uMsg != WM_TIMER && - uMsg != WM_D3D9DEVICELOST) + uMsg != WM_D3D9DEVICELOST && uMsg != WM_NULL) { TRACE( " uMsg = %s (%d), wParam = %08X (%d), lParam = %08X (%d, LO=%d HI=%d)\n", @@ -42,6 +42,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam switch (uMsg) { + case WM_NULL: case WM_MOVING: case WM_NCLBUTTONDOWN: case WM_NCLBUTTONUP: @@ -780,97 +781,6 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam { break; } - /* button up messages reactivate cursor lock */ - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - { - if (!g_config.devmode && !g_mouse_locked) - { - int x = GET_X_LPARAM(lParam); - int y = GET_Y_LPARAM(lParam); - - if (x > g_ddraw.render.viewport.x + g_ddraw.render.viewport.width || - x < g_ddraw.render.viewport.x || - y > g_ddraw.render.viewport.y + g_ddraw.render.viewport.height || - y < g_ddraw.render.viewport.y) - { - x = g_ddraw.width / 2; - y = g_ddraw.height / 2; - } - else - { - x = (DWORD)((x - g_ddraw.render.viewport.x) * g_ddraw.mouse.unscale_x); - y = (DWORD)((y - g_ddraw.render.viewport.y) * g_ddraw.mouse.unscale_y); - } - - x = min(x, g_ddraw.width - 1); - y = min(y, g_ddraw.height - 1); - - InterlockedExchange((LONG*)&g_ddraw.cursor.x, x); - InterlockedExchange((LONG*)&g_ddraw.cursor.y, y); - - mouse_lock(); - return 0; - } - /* fall through for lParam */ - } - /* down messages are ignored if we have no cursor lock */ - case WM_XBUTTONDBLCLK: - case WM_XBUTTONDOWN: - case WM_XBUTTONUP: - case WM_MOUSEWHEEL: - case WM_MOUSEHOVER: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_MOUSEMOVE: - { - if (!g_config.devmode && !g_mouse_locked) - { - return 0; - } - - if (uMsg == WM_MOUSEWHEEL) - { - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - real_ScreenToClient(g_ddraw.hwnd, &pt); - lParam = MAKELPARAM(pt.x, pt.y); - } - - int x = max(GET_X_LPARAM(lParam) - g_ddraw.mouse.x_adjust, 0); - int y = max(GET_Y_LPARAM(lParam) - g_ddraw.mouse.y_adjust, 0); - - if (g_config.adjmouse) - { - if (g_config.vhack && !g_config.devmode) - { - POINT pt = { 0, 0 }; - fake_GetCursorPos(&pt); - - x = pt.x; - y = pt.y; - } - else - { - x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); - y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); - } - } - - x = min(x, g_ddraw.width - 1); - y = min(y, g_ddraw.height - 1); - - InterlockedExchange((LONG*)&g_ddraw.cursor.x, x); - InterlockedExchange((LONG*)&g_ddraw.cursor.y, y); - - lParam = MAKELPARAM(x, y); - - break; - } case WM_PARENTNOTIFY: { switch (LOWORD(wParam))