0

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.

Eugene Mihaylin
  • 1,736
  • 3
  • 16
  • 31
  • 1
    "I have no experience writing code...": If so, a kernel mode driver is to wrong place to start learning it. It's a very advanced topic. Invest two years into writing simpler software. Then revisit it once you coding skills have considerably advanced. – Codo Apr 19 '23 at 05:42

0 Answers0