How to properly register a keyboard/device class filter?

I have a Keyboard filter that works if I attach it to a specific device, however I can’t get it to work by making it as a class filter (I want to attach it to all keyboards as I need to identify them).
According to this page: microsoft_kbfltr I need to add my driver name before “kbdclass” in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4D36E96B-E325-11CE-BFC1-08002BE10318}\UpperFilters. I created a service for the driver using OSR Driver Loader and default settings (launch on demand, no load group, type driver), I modified the “UpperFilters” value from “kbdclass” to “KeyboardFilterDriverKMDF kbdclass” (KeyboardFilterDriverKMDF is the name of my driver and it’s service) and then I restarted the target PC. However, after restart, keyboard doesn’t works anymore and taking a look at loaded drivers with devicetree, KeyboardFilterDriverKMDF and kbdclass aren’t started. If I remove my driver from “UpperFilters” and restart the target PC, keyboard works fine again (kbdclass is started with windows).

If I start the service manually and attach the debugger, DeviceEntry get’s called (so the driver loads), however adding an USB device doesn’t call the AddDevice callback.

This is my DriverEntry and how I register my callbacks (Added breakpoints to every callback and none of them gets called):

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
UNREFERENCED_PARAMETER(RegistryPath);

// Set driver unload callback
DriverObject->DriverUnload = KeyboardFilterDriverUnload;

// Set general pass through
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
	DriverObject->MajorFunction[i] = KeyboardFilterIrpPassthrough;
}

// Set AddDevice callback
DriverObject->DriverExtension->AddDevice = KeyboardFilterAddDevice;

// Set read callback
DriverObject->MajorFunction[IRP_MJ_READ] = KeyboardFilterIrpRead;

// Set PnP callback
//DriverObject->MajorFunction[IRP_MJ_PNP] = KeyboardFilterIrpPnP;

return STATUS_SUCCESS;

}

How should the “UpperFilters” registry entry look like?

Upperfilters is a REG_MULTI_SZ, an array of strings, not a REG_SZ.

Don’t write a wdm filter, use KMDF. There is even a kmdf sample you can start with kbdfiltr (there is no real functional difference in the code between a keyboard device and class filter). An upper filter still needs to completely participate in pnp and power, both need to be in place to start the stack (which you get for free in kmdf).

@Mark_Roddy said:
Upperfilters is a REG_MULTI_SZ, an array of strings, not a REG_SZ.

Thanks, fixed my problem, I was writing them as one string with space between them.

@Doron_Holan said:
Don’t write a wdm filter, use KMDF. There is even a kmdf sample you can start with kbdfiltr (there is no real functional difference in the code between a keyboard device and class filter). An upper filter still needs to completely participate in pnp and power, both need to be in place to start the stack (which you get for free in kmdf).

Except the kbdfiltr sample(and the docs) I didn’t really found much stuff on the internet (for a filter driver). I took this approach as I can find a lot more examples and a lot more explanations, forum posts and so on.

The sources on github include a wdf keyboard filter: https://github.com/microsoft/Windows-driver-samples/blob/master/input/kbfiltr

Instead of working with registry directly I think you can use “devcon” to install your filter. Or an INF file maybe.
I’ve done so couple of days ago. I think it prevents mistakes that manually editing registry could cause.

1 Like