My Keyboard and Mouse Vanished in Windows, While Linux Was Fine
An input failure caused by a dangling
LowerFiltersvalue under HIDClass
TL;DR
- Symptom: keyboard and mouse completely dead in Windows, while the same machine boots Linux and both work normally.
- Root cause: while migrating Steam from Windows to Linux I deleted some leftover files by hand, and took Steam’s Xbox controller driver
steamxboxwith them. The driver file was gone, but its declaration in three device classes’LowerFiltersstayed behind. On the next boot, every HID device failed to start because of that reference to a driver that no longer exists. - Fix: clear those three stale values. Windows had no usable input at all, so I read, verified and patched the registry offline from Linux, without ever needing Windows to cooperate (section 6 gives the safer WinRE route).
1. The symptom
This machine dual-boots Windows and Linux. One morning I booted Windows and found the keyboard and mouse completely dead: no cursor, no response to any key.
Rebooted into Linux and everything worked. I also moved both devices to a different pair of USB ports at some point; nothing changed in Windows.
That combination is annoying. “Windows is broken” and “the hardware is fine” are true at the same time, which puts the fault outside the hardware and outside the usual missing-driver explanation — otherwise Linux would be broken too. The question is which layer is broken.
2. Ruling out the obvious suspect: Fast Startup
The symptom pattern almost points at one classic explanation: dual boot, keyboard and mouse dead in Windows, everything fine in Linux. That explanation is Windows Fast Startup, which turns “shut down” into hibernating the kernel session (S4) so the next power-on resumes instead of cold-booting. If the resumed session has a broken USB controller state, the input devices stay dead — and Linux never sees it, because Linux cold-boots and re-enumerates every time.
So I mounted the Windows partition read-only from Linux and looked: C:\hiberfil.sys does not exist.
Fast Startup is built on hibernation. No hibernation file means neither hibernation nor Fast Startup is available (it’s the state you get after powercfg /h off). Hypothesis dead.
With the best-looking lead gone, the search had to go deeper.
3. Change of approach: use Linux as the forensic host
Windows being unusable doesn’t mean Windows data is unreadable.
The registry hives (SYSTEM, SOFTWARE), the event logs (.evtx) and the driver install log (setupapi.dev.log) are all ordinary files. Mount that NTFS partition read-only and you can read every one of them from Linux. No booted Windows required, and certainly no keyboard.
I mounted it with ntfs-3g, copied out the interesting files, and parsed the hives with python-registry and the event logs with python-evtx. These are digital-forensics tools; they turned out to be handy for troubleshooting too.
The first step was lining up the timeline. Three independent sources agreed:
| Time | Source | What it tells us |
|---|---|---|
| 11-02 05:10:52 | setupapi.dev.log |
last driver operation (the important one, see below) |
| 11-02 06:10:58 | last write to the SYSTEM / SOFTWARE hives |
last clean shutdown |
| 11-03 04:10:02 | Kernel-General event 12 in System.evtx |
system boot |
| 11-03 04:10:11 | Microsoft-Windows-Winlogon event 7001 in System.evtx |
user logon succeeded |
| after that | — | nothing further in System.evtx |
Two things stood out.
First, Windows did boot and did complete a logon that day. So the symptom was not “boot failure”; the machine reached the desktop and had no input devices. That separates it from the “stuck on the update screen” family of problems.
Second, NTUSER.DAT was last written at 11-02 06:10. That detail misled me for a while: I thought “the logon never happened today”. What actually happened is that I cut the power, so the user hive never got flushed. The 7001 in System.evtx is the more reliable source. When building a timeline, “last write” means different things for different files — worth remembering.
4. The culprit: a log entry written 23 hours earlier
setupapi.dev.log is Windows’ device-installation log: plain text, directly readable. It was only 32 KB. On a healthy machine this log usually grows to several MB, so the size alone says the traceable history is shallow. I went looking for rotated copies (setupapi.dev.*.log) in Inf and found none, so the missing history cannot be recovered. The fact that the decisive section survived at the end of the file is luck, not method. The lesson: this log gets rotated or cleaned up, so collect it early.
The last section of the log is timestamped 11-02 05:10:52, twenty-three hours before the fatal reboot. It records a failed service registration for the steamxbox driver, followed by a rollback cleanup:
!!! inf: Failed to create service 'steamxbox'. Error = 0x00000430
!!! dvi: Error 1072: The specified service has been marked for deletion.
!!! dvi: Error while installing services.
!!! dvi: Cleaning up failed installation
!!! dvs: Failed to install device instance 'ROOT\SYSTEM\0001'
flq: DeleteFile: 'C:\WINDOWS\System32\drivers\steamxbox.sys'
flq: DeleteFile: success
! sto: Reboot required to complete unconfiguration of driver package.
Line by line: creating the service failed (error 1072, “the specified service has been marked for deletion”), setup declared the install failed and started cleaning up, deleted the driver package and steamxbox.sys, and left behind a pending “reboot required to complete unconfiguration”.
The mismatch worth noticing: the file was deleted, but the uninstall never actually finished. A normal uninstall removes the class filter declarations as part of its cleanup. This run took the “failed registration → rollback” path instead (error 1072 means the service had already been marked for deletion), and that path deletes the package and the .sys file but leaves the Control\Class declarations untouched. That inference comes from the log’s behaviour; I don’t have the uninstaller’s source to confirm it, but it matches everything found afterwards.
As for what steamxbox is, and why it disappeared: it is Steam’s Xbox controller support driver (the INF is named steamxbox.inf, and it registers itself into the two controller-related device classes, XboxComposite and XnaComposite). It was deleted by me. The day before, I moved Steam from Windows to Linux and cleaned up the Steam files left on the Windows side; this driver most likely went with them.
So I went back to the registry to see what traces it had left. The check: list every device class’s UpperFilters and LowerFilters, and verify that each referenced name exists under Services. It costs almost nothing and catches a whole family of failures.
There were exactly three, and all three were the same driver:
| Device class | Filter | Does the referenced service exist? |
|---|---|---|
| XboxComposite | LowerFilters = steamxbox |
❌ missing |
| HIDClass | LowerFilters = steamxbox |
❌ missing |
| XnaComposite | LowerFilters = steamxbox |
❌ missing |
| Keyboard | UpperFilters = kbdclass |
✔ |
| Mouse | UpperFilters = mouclass |
✔ |
| USB | UpperFilters = hrdevmon |
✔ |
| DiskDrive / Volume / MEDIA / … | hrdevmon / partmgr / volsnap / … |
✔ all present |
Only three dangling references in the whole registry, all of them steamxbox. Their last-write times were 07-12, 10-05 and 10-16 — the 11-02 cleanup never touched them. The driver file was gone, the service was deregistered, and the statement “attach a filter here” was left sitting in the registry.
5. Mechanism: how a few dangling references kill every keyboard and mouse
Windows device stacks have two kinds of drivers: function drivers, which do the actual work, and filter drivers, which attach above or below and handle something on the side (encryption, monitoring, added features).
Whether a filter is attached, which ones, and where, is declared per device class in the registry:
Keyboard HID device stack (simplified)
kbdclass.sys ← Keyboard class, UpperFilters
↑
kbdhid.sys ← HID keyboard subdriver
↑
┌──────────────────────────────────────────┐
│ HIDClass — LowerFilters = steamxbox │ ← breaks here
└──────────────────────────────────────────┘
↑
hidusb.sys ← HID class driver
↑
usbccgp.sys ← USB composite parent driver
↑
xHCI controller / physical port
When a device starts, the PnP manager loads drivers by walking both filter lists. If any name on the list no longer maps to a service, the whole stack fails to start — the device does not appear at all.
A word on what “device class” means here, because it is easy to get tangled up: a physical keyboard shows up in the device tree as several different “devices” at once —
- its USB composite interfaces (
MI_00–MI_03) belong to the HIDClass layer; - Windows then derives the actual Keyboard class device on top of the HIDClass device (driven by
kbdhid/kbdclass).
What broke was the LowerFilters of HIDClass, the bottom layer. If the parent never starts, no Keyboard or Mouse class device gets created above it — so even though the Keyboard and Mouse classes’ own UpperFilters (kbdclass / mouclass) are perfectly fine, you still have no keyboard and no mouse.
On this machine: Enum\HID listed 16 HID devices (four keyboard interfaces, several mouse collections, one gamepad). None of them could start.
Several observations that made no sense suddenly did:
- Two devices from different brands died together, because they belong to the same device class and share the same filter list.
- Moving to another USB port changed nothing, because the declaration hangs off the device class, not the port.
- The USB layer logs were clean, because the failure happens at the HID class layer, well above where an xHCI controller would report an error. Both controllers and USB enumeration succeeded: the two device instances under
Enum\USBhadService = usbccgpandConfigFlags = 0, all normal. - Linux was unaffected, because “declare filter drivers per device class at runtime” is a Windows device stack mechanism. Linux has no equivalent setting to corrupt.
Why it worked yesterday and broke today is written in the timeline: the driver file was deleted at 11-02 05:10, but the driver was still resident in memory, so the system kept working until a clean shutdown at 06:10. No Windows updates were installed during that window, and no other software changed — between “fully working” and “completely dead”, the only events were that file cleanup and one reboot. The 04:10 boot on 11-03 was the first time this machine started without steamxbox.sys on disk.
Two decoy errors were worth noting:
Service Control Manager 7026, “a boot-start driver failed to load”. It sounds like the culprit, but its argument isdam(Desktop Activity Moderator). This machine doesn’t support Modern Standby, so it reports that on every boot. It appears on every previous boot in the history too, so it is benign.Kernel-PnP 219(\Driver\WUDFRdfailing to load forROOT\DISPLAY\0000) also appears on every boot, and is equally benign.
The test is comparison against the historical baseline, not “an error was logged, so it must be the cause”.
6. The fix: clear those three values from WinRE
The goal: remove steamxbox from the LowerFilters of the three device classes.
Use Windows’ own tools for this — boot into WinRE and edit the offline hive with reg. It is the lowest-risk route, because Windows itself writes the hive to disk: checksums, the dirty flag and transaction log replay all take care of themselves.
One caveat: on some machines USB input doesn’t work in WinRE either. If you hit that, the alternatives are booting the installation media into PE (it also gives you a command prompt), attaching a PS/2 keyboard and mouse (an entirely different driver path), or using a third-party PE image with full USB support.
Step 0: find the drive letter. WinRE often mounts the Windows partition as D:; confirm with dir C:\Windows\System32\config\SYSTEM and dir D:\Windows\System32\config\SYSTEM.
Step 1: load the offline hive and check the current control set.
reg load HKLM\OFF D:\Windows\System32\config\SYSTEM
reg query HKLM\OFF\Select /v Current
If Current returns 0x1, use ControlSet001; 0x2 means ControlSet002. Do not skip this: editing the control set that isn’t in use has no effect after reboot, and you’ll conclude the fix failed.
Also check how many control sets exist. A hive usually holds both ControlSet001 and ControlSet002 (mirrors of each other, used by “Last Known Good Configuration”). If both contain the dangling reference, you have to fix both, otherwise the fault comes back the moment the system falls back to the other one. This machine had a single control set: I scanned the entire hive and ControlSet002 doesn’t exist, and Current / Default / LastKnownGood are all 1, so this didn’t apply. Yours may be different.
Step 2: back up before editing.
reg export "HKLM\OFF\ControlSet001\Control\Class\{745a17a0-74d3-11d0-b6fe-00a0c90f57da}" D:\backup-hidclass.reg /y
Export all three classes (onto a USB stick or a non-system drive if you can). A .reg file can be re-imported by double-clicking, which beats “put it back from memory”. If you want to be thorough, copy SYSTEM, SYSTEM.LOG1 and SYSTEM.LOG2 somewhere else as a set.
Step 3: find out what is in each value. The three device classes:
| Device class | GUID | Notes |
|---|---|---|
| HIDClass | {745a17a0-74d3-11d0-b6fe-00a0c90f57da} |
the HID device class, the direct cause of this failure |
| XboxComposite | {05f5cfe2-4733-4950-a6bb-07aad01a3a84} |
the Xbox controller composite class registered by steamxbox |
| XnaComposite | {d61ca365-5af4-4486-998b-9db4734c6ca3} |
the XNA input composite class |
(Substitute the control set number from step 1 for ControlSet001 below.)
reg query "HKLM\OFF\ControlSet001\Control\Class\{745a17a0-74d3-11d0-b6fe-00a0c90f57da}" /v LowerFilters
reg query "HKLM\OFF\ControlSet001\Control\Class\{05f5cfe2-4733-4950-a6bb-07aad01a3a84}" /v LowerFilters
reg query "HKLM\OFF\ControlSet001\Control\Class\{d61ca365-5af4-4486-998b-9db4734c6ca3}" /v LowerFilters
Step 4: delete only what should be deleted. You may remove the entire value only when it contains nothing but that dead driver name. All three of ours held only steamxbox, so this was safe:
reg delete "HKLM\OFF\ControlSet001\Control\Class\{745a17a0-74d3-11d0-b6fe-00a0c90f57da}" /v LowerFilters /f
reg delete "HKLM\OFF\ControlSet001\Control\Class\{05f5cfe2-4733-4950-a6bb-07aad01a3a84}" /v LowerFilters /f
reg delete "HKLM\OFF\ControlSet001\Control\Class\{d61ca365-5af4-4486-998b-9db4734c6ca3}" /v LowerFilters /f
/f deletes the entire value, unconditionally. If a reg query shows other filters in there that are still valid (registered by software you actually use), do not run the three commands above. You would delete the good entries along with the bad one, fixing one fault and creating another. In that case rewrite the whole value and keep only what you need (reg.exe separates REG_MULTI_SZ strings with \0):
reg add "HKLM\OFF\ControlSet001\Control\Class\{GUID}" /v LowerFilters /t REG_MULTI_SZ /d "keep1\0keep2" /f
Step 5: verify, then unload. reg unload is what actually writes the change back to the file:
reg query "HKLM\OFF\ControlSet001\Control\Class\{745a17a0-74d3-11d0-b6fe-00a0c90f57da}" /v LowerFilters
reg unload HKLM\OFF
The first command should report that the value can’t be found, or show that the target entry is gone. If reg unload complains that the hive is in use (registry editor still open, another reg.exe still running), close whatever holds it and retry; do not reboot until the unload succeeds, or the change may never reach disk.
Then reboot, and the keyboard and mouse come back.
What I did was different: the only working environment during the outage was Linux, so I edited the SYSTEM file directly from there. That route does work, but it bypasses Windows’ own registry writer — checksums, the dirty flag and transaction log replay are all your responsibility, and a mistake can leave the system unable to boot. The WinRE route above takes all of that off your plate, which is why it’s the only one described here.
7. A reusable checklist
Next time a whole class of devices disappears in Windows, start with this tree:
Device doesn't work in Windows
│
├─ Only one device affected?
│ └─ Look at that device: cable, port, power, the device itself
│
└─ A whole class of devices at once (e.g. "every keyboard and mouse")
│
├─ Works after moving to another controller/port?
│ └─ Yes → that controller (driver / resources / firmware)
│
└─ Still dead → the fault is at the class layer, not the port
│
├─ Caps Lock LED toggles (Windows is receiving reports)
│ └─ Not USB: session hang, explorer or display driver crash
│
└─ Caps Lock LED does nothing
│
├─ Scan every device class's UpperFilters / LowerFilters
│ and check whether Services actually contains that name
│ └─ references a missing driver → that's it
│
└─ Filters all resolve → check whether a service's Start
was set to 4 (disabled), check AV HID-protection drivers,
check for an update that broke something on first boot
One thing the tree can’t show, and the handiest trick in this whole post:
The Caps Lock LED works as a probe. That LED is lit by the operating system sending a HID output report; the keyboard doesn’t control it on its own. If the LED toggles, Windows is receiving keystrokes and the problem lies elsewhere. If it never changes, the reports aren’t reaching the system at all.
The other items (using a second OS as the forensic host, checking the timeline with “the first boot without X”, comparing errors against the baseline) are covered in sections 3 and 5. One cheap closing check worth adding: after migrating away from or uninstalling software that installs filter drivers, go back and confirm those declarations were actually cleaned up — especially when setupapi.dev.log says “the specified service has been marked for deletion” and “reboot required to complete unconfiguration”.
8. Afterword
There was no external culprit here. I deleted files by hand while migrating Steam from Windows to Linux and took a driver with them that was still attached beneath three device classes. Windows and the hardware played no part, yet the state left behind was enough to kill every HID device at once.
One detail is worth recording: the evening after the deletion everything still worked, because the driver module was still resident in memory. The dangling declaration in the registry doesn’t get executed until the next device enumeration. So it didn’t blow up when I deleted the file; it blew up on the next reboot — and without that reboot it would have stayed buried longer. “Nothing broke right after the change” is not proof the change was correct; some configuration errors only take effect after a restart.
The investigation itself had no clever trick to it. It was a matter of turning each hypothesis into something data could disprove: Fast Startup died on “hiberfil.sys does not exist”; the USB layer died on “no controller records at all in setupapi, and Enum\USB looks normal”; and then a single cleanup record showed the three dangling declarations. All of it happened while Windows was completely unusable — the data lives on disk, and another operating system can read it just as well.
So if your keyboard and mouse (or disks, or network adapters) ever disappear together in Windows and the hardware checks out, don’t start by replacing parts. Pull up those filter lists first. And one more check that costs the same: after migrating away from or uninstalling software that installs filter drivers, confirm those declarations were really cleaned up.

