[Runner] Harden centralized keyboard hook against stuck/ghost keys#48570
[Runner] Harden centralized keyboard hook against stuck/ghost keys#48570crutkas wants to merge 1 commit into
Conversation
- Tag dummy 0xFF SendInput with dwExtraInfo to prevent cross-hook interference - Skip LLKHF_INJECTED events from OSK/macro tools (dwExtraInfo==0) - Revalidate key state in PressedKeyTimerProc before firing action - Kill pending timers and reset state in Stop() - Make vkCodePressed atomic to fix data race Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@check-spelling-bot Report🔴 Please reviewSee the 📂 files view, the 📜action log, 👼 SARIF report, or 📝 job summary for details.
See ❌ Event descriptions for more information. Some files were automatically ignored 🙈These sample patterns would exclude them: You should consider adding them to: File matching is via Perl regular expressions. To check these files, more of their words need to be in the dictionary than not. You can use To update file exclusions, you could run the following commands... in a clone of the git@github.com:crutkas/autoUpgradeAttempt.git repository curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c/apply.pl' |
perl - 'https://github.com/microsoft/PowerToys/actions/runs/27451218271/attempts/1' &&
git commit -m 'Update check-spelling metadata'Forbidden patterns 🙅 (1)In order to address this, you could change the content to not match the forbidden patterns (comments before forbidden patterns may help explain why they're forbidden), add patterns for acceptable instances, or adjust the forbidden patterns themselves. These forbidden patterns matched content: Should be
|
Summary
Hardens the runner's centralized keyboard hook against stuck and "ghost" key activations — cases where a hotkey action fires after the key was already released, or a pending timer fires after the hook was torn down.
What this changes
vkCodePressedis nowstd::atomic<DWORD>. It is read/written from the low-level hook callback and from the timer/teardown paths; the plainDWORDwas a data race.GetAsyncKeyState(virtualKey) & 0x8000before invoking the action, preventing ghost activations after the user has let go.0xFFkey-up withCENTRALIZED_KEYBOARD_HOOK_DONT_TRIGGER_FLAGso the hook does not reprocess its own synthetic event.Stop()kills all pending pressed-key timers and resetsvkCodePressedbefore unhooking, so a timer can't fire a callback into a half-removed hook.Testing
PowerToys.exe) clean against currentmain.This is one of a small set of related "stuck key" hardening fixes; each stands alone.