From: Zhiyi Zhang zzhang@codeweavers.com
Previously, accept_hardware_message() is called after WH_KEYBOARD and WH_CBT HCBT_KEYSKIPPED hooks. So when PeekMessage() gets called in WH_KEYBOARD and WH_CBT HCBT_KEYSKIPPED hooks, the hooks will be called recursively because the message is still in the server message queue.
Fix Toad for Oracle F3 find next function not working properly because its WH_KEYBOARD hook gets called too many times. --- dlls/user32/tests/msg.c | 2 -- dlls/win32u/message.c | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 9f7da2fe5a5..98b1dcc6f99 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -12584,7 +12584,6 @@ static void test_recursive_hook(void) flush_events();
/* Expect the WH_KEYBOARD hook not gets called recursively */ - todo_wine ok(max_hook_depth == 1, "Got expected %d.\n", max_hook_depth);
/* Test a possible recursive WH_CBT HCBT_KEYSKIPPED hook condition */ @@ -12600,7 +12599,6 @@ static void test_recursive_hook(void) while (PeekMessageA(&msg, hook_hwnd, WM_KEYFIRST, WM_KEYLAST, 0)) DispatchMessageA(&msg);
/* Expect the WH_CBT HCBT_KEYSKIPPED hook not gets called recursively */ - todo_wine ok(max_hook_depth == 1, "Got expected %d.\n", max_hook_depth);
UnhookWindowsHookEx(cbt_hook); diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 91f836a60bd..376af30554e 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2384,15 +2384,17 @@ static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter, } }
+ /* if remove is TRUE, remove message first before calling hooks to avoid recursive hook calls */ + if (remove) accept_hardware_message( hw_id ); if (call_hooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE, LOWORD(msg->wParam), msg->lParam, 0 )) { + /* if the message has not been removed, remove it */ + if (!remove) accept_hardware_message( hw_id ); /* skip this message */ call_hooks( WH_CBT, HCBT_KEYSKIPPED, LOWORD(msg->wParam), msg->lParam, 0 ); - accept_hardware_message( hw_id ); return FALSE; } - if (remove) accept_hardware_message( hw_id ); msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
if (remove && msg->message == WM_KEYDOWN)