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 <officialasishkumar@gmail.com>

* fix: clear invalid mouse hook handles

Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>

---------

Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
This commit is contained in:
Asish Kumar
2026-05-01 01:04:45 +05:30
committed by GitHub
parent 8f0f08e818
commit d0612e2c92

View File

@@ -6,6 +6,7 @@
#include <shellapi.h>
#include <wrl/client.h>
#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);
}
}
}
}
}