I want to create a USB lower filter, that can identify mouse and keyboards or all hid devices and delay all the input data from them by 1 second. I am mainly using ChatGPT to write my code, which I am sure is probably not working. The AI recommended some stuff to read, but I dont trust it. I will read anything, if I can make this project, but I dont know what to read and where it is.
`driver.c
#include "Driver.h"
#include <wdfusb.h>
#include <hidusage.h>
#include <hidsdi.h>
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAdd);
config.DriverPoolTag = 'HIDF';
status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
return status;
}
NTSTATUS
EvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
UNREFERENCED_PARAMETER(Driver);
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES attributes;
WDFDEVICE device;
PDEVICE_CONTEXT deviceContext;
WDF_IO_QUEUE_CONFIG queueConfig;
WdfFdoInitSetFilter(DeviceInit);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if (!NT_SUCCESS(status))
{
return status;
}
deviceContext = GetDeviceContext(device);
deviceContext->Device = device;
deviceContext->DelayMs = 1000; // Set the default delay to 1 second
// Configure the I/O queue and read completion routine
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential);
queueConfig.EvtIoRead = ReadCompletionRoutine;
// Get the WDFUSBDEVICE handle
WDF_USB_DEVICE_CREATE_CONFIG createParams;
WDF_USB_DEVICE_CREATE_CONFIG_INIT(&createParams, USBD_CLIENT_CONTRACT_VERSION_602);
status = WdfUsbTargetDeviceCreateWithParameters(device, &createParams, WDF_NO_OBJECT_ATTRIBUTES, &deviceContext->UsbDevice);
if (!NT_SUCCESS(status))
{
KdPrint(("WdfUsbTargetDeviceCreateWithParameters failed 0x%x\n", status));
return status;
}
// Get the USB device descriptor
status = WdfUsbTargetDeviceRetrieveConfigDescriptor(deviceContext->UsbDevice, &deviceContext->UsbConfigurationDescriptor, NULL);
if (!NT_SUCCESS(status))
{
KdPrint(("WdfUsbTargetDeviceGetDeviceDescriptor failed 0x%x\n", status));
return status;
}
// Select the appropriate USB interface
WDF_USB_INTERFACE_SELECT_SETTING_PARAMS settingParams;
WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_DESCRIPTOR(&settingParams, &deviceContext->UsbInterfaceDescriptor);
status = WdfUsbInterfaceSelectSetting(deviceContext->UsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &settingParams);
if (!NT_SUCCESS(status))
{
KdPrint(("WdfUsbInterfaceSelectSetting failed 0x%x\n", status));
return status;
}
// Configure the USB pipe for reading data
WDF_USB_PIPE_INFORMATION pipeInfo;
WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
for (UCHAR i = 0; i < WdfUsbInterfaceGetNumConfiguredPipes(deviceContext->UsbInterface); i++)
{
WDFUSBPIPE pipe = WdfUsbInterfaceGetConfiguredPipe(deviceContext->UsbInterface, i, &pipeInfo);
if (WdfUsbPipeTypeInterrupt == pipeInfo.PipeType && WdfUsbTargetPipeIsInEndpoint(pipe))
{
deviceContext->InterruptReadPipe = pipe;
break;
}
}
if (deviceContext->InterruptReadPipe == NULL)
{
KdPrint(("Could not find a suitable interrupt read pipe\n"));
return STATUS_UNSUCCESSFUL;
}
status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceContext->Queue);
if (!NT_SUCCESS(status))
{
return status;
}
// Set up the USB interface for the HID device
WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
WDFUSBDEVICE usbDevice;
WDF_USB_DEVICE_CREATE_CONFIG_INIT(&createParams, USBD_CLIENT_CONTRACT_VERSION_602);
status = WdfUsbTargetDeviceCreateWithParameters(device, &createParams, WDF_NO_OBJECT_ATTRIBUTES, &usbDevice);
if (!NT_SUCCESS(status))
{
return status;
}
WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);
status = WdfUsbTargetDeviceSelectConfig(usbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams);
if (!NT_SUCCESS(status))
{
return status;
}
// Allocate memory for the input buffer
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = deviceContext->Queue;
status = WdfMemoryCreate(&attributes, NonPagedPoolNx, 'HIDF', 1024, &deviceContext->ReadMemory, NULL);
if (!NT_SUCCESS(status))
{
return status;
}
return status;
}
NTSTATUS
ReadCompletionRoutine(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t Length,
_In_ WDFCONTEXT Context
)
{
PDEVICE_CONTEXT deviceContext;
WDFREQUEST newRequest;
NTSTATUS status;
PVOID readBuffer = NULL;
size_t readBufferSize;
UNREFERENCED_PARAMETER(Context);
deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
// Log the data from the input stream
WdfMemoryGetBuffer(deviceContext->ReadMemory, &readBuffer, &readBufferSize);
KdPrint(("Read %lu bytes from the HID device\n", readBufferSize));
// Print the content of the buffer
for (size_t i = 0; i < readBufferSize; i++)
{
KdPrint(("Buffer[%lu] = %02X\n", i, ((PUCHAR)readBuffer)[i]));
}
// Introduce the configurable delay
LARGE_INTEGER delay;
delay.QuadPart = WDF_REL_TIMEOUT_IN_MS(deviceContext->DelayMs);
KeDelayExecutionThread(KernelMode, FALSE, &delay);
// Re-submit the request to continue reading data from the HID device
status = WdfRequestReuse(Request, STATUS_SUCCESS);
if (!NT_SUCCESS(status))
{
KdPrint(("Failed to reuse the request, status: 0x%X\n", status));
return;
}
status = WdfIoQueueRetrieveNextRequest(deviceContext->Queue, &newRequest);
if (!NT_SUCCESS(status))
{
KdPrint(("Failed to retrieve the next request, status: 0x%X\n", status));
return;
}
status = WdfRequestForwardToIoQueue(newRequest, deviceContext->Queue);
if (!NT_SUCCESS(status))
{
KdPrint(("Failed to forward the request to the I/O queue, status: 0x%X\n", status));
return;
}
return STATUS_SUCCESS;
}
driver.h
#pragma once
#include <ntddk.h>
#include <wdf.h>
#include <usb.h>
#include <usbdlib.h>
#include <wdfusb.h>
typedef struct _DEVICE_CONTEXT
{
WDFDEVICE Device;
WDFQUEUE Queue;
ULONG DelayMs;
WDFMEMORY ReadMemory;
WDFUSBDEVICE UsbDevice;
USB_DEVICE_DESCRIPTOR UsbDeviceDescriptor;
PUSB_CONFIGURATION_DESCRIPTOR UsbConfigurationDescriptor;
WDFUSBINTERFACE UsbInterface;
WDF_USB_INTERFACE_SELECT_SETTING_PARAMS UsbInterfaceDescriptor;
WDFUSBPIPE InterruptReadPipe;
} DEVICE_CONTEXT, * PDEVICE_CONTEXT;
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath);
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
);
NTSTATUS
EvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
);
NTSTATUS
ReadCompletionRoutine(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ ULONG_PTR NumberOfBytes,
_In_ WDFCONTEXT Context
);`
The code has a bunch of errors so it never got to the KMDF debugger. Its a KMDF empty project, I have no experience writing code, but will read anything you tell me to. ChatGPT recommended some stuff to read, but I dont trust it as it doesnt have the latest information.