From d0612e2c9241f7b57891642ae6cda0c93136bc9b Mon Sep 17 00:00:00 2001 From: Asish Kumar <87874775+officialasishkumar@users.noreply.github.com> Date: Fri, 1 May 2026 01:04:45 +0530 Subject: [PATCH] fix: preserve mouse hook handle when UnhookWindowsHookEx fails (#51098) * fix: preserve mouse hook handle when UnhookWindowsHookEx fails NativeWindowViews::SetForwardMouseMessages() installs a low-level mouse hook when mouse forwarding begins and unhooks it once no window needs forwarding. The previous code reset the shared `mouse_hook_` handle to `nullptr` unconditionally after calling UnhookWindowsHookEx, even when the unhook call failed. When unhooking fails, the hook is still installed in the system. Because `mouse_hook_` is nulled out anyway, the next call to SetForwardMouseMessages(true) evaluates `if (!mouse_hook_)` as true and installs a second, duplicate hook via SetWindowsHookEx, so every mouse message is processed by MouseHookProc multiple times. Check the return value of UnhookWindowsHookEx and only null the handle on success. When the call fails, leave `mouse_hook_` pointing at the existing hook so the next activation reuses it rather than stacking a new one on top, and log the failure via PLOG to surface the underlying Windows error. Fixes: #51064 Signed-off-by: Asish Kumar * fix: clear invalid mouse hook handles Signed-off-by: Asish Kumar --------- Signed-off-by: Asish Kumar --- shell/browser/native_window_views_win.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/shell/browser/native_window_views_win.cc b/shell/browser/native_window_views_win.cc index 400d140fd5..e558c7d14b 100644 --- a/shell/browser/native_window_views_win.cc +++ b/shell/browser/native_window_views_win.cc @@ -6,6 +6,7 @@ #include #include +#include "base/logging.h" #include "base/win/atl.h" // Must be before UIAutomationCore.h #include "base/win/registry.h" #include "base/win/scoped_handle.h" @@ -677,8 +678,21 @@ void NativeWindowViews::SetForwardMouseMessages(bool forward) { RemoveWindowSubclass(legacy_window_, SubclassProc, 1); if (forwarding_windows_->empty()) { - UnhookWindowsHookEx(mouse_hook_); - mouse_hook_ = nullptr; + // If UnhookWindowsHookEx fails, the hook is still installed in the + // system. Leave |mouse_hook_| pointing at the existing hook so that a + // subsequent SetForwardMouseMessages(true) reuses it instead of + // installing a duplicate hook. + if (UnhookWindowsHookEx(mouse_hook_)) { + mouse_hook_ = nullptr; + } else { + const DWORD error = ::GetLastError(); + if (error == ERROR_INVALID_HOOK_HANDLE) { + mouse_hook_ = nullptr; + } else { + LOG(WARNING) << "Failed to unhook low-level mouse hook: " + << logging::SystemErrorCodeToString(error); + } + } } } }