Virtual HID Mouse Driver Development
Budget: $10 – $30 USD
I'm looking for an experienced developer to write a Virtual HID Mouse Driver using the Virtual HID Framework (VHF) in KMDF. The goal is to create a driver that registers a fake mouse with Windows, capable of sending right-click events without moving the actual cursor.
Key Requirements:
- Develop a kernel-mode driver that uses VHF to register a virtual mouse.
- Implement HID report descriptors for a mouse with input report capability.
- Support right-click down and right-click up events without moving the real cursor.
- The virtual mouse should only be detected as having the right-click button.
- Report the right-click event at a fixed position on the screen.
- Utilize VhfReadReportSubmit() to send HID input reports from the kernel driver.
- Needs to use C syntax and NOT C++.
Ideal Skills and Experience:
- Proficiency in developing KMDF drivers, especially with the Virtual HID Framework.
- Strong understanding of HID class drivers and Windows input systems.
- Experience with HID report descriptors and input report capabilities.
- Ability to work with kernel-mode programming and driver development in Windows.
The desired outcome is to have right-click events appear at an arbitrary X/Y position without affecting the real mouse cursor's position. If you have the expertise to accomplish this, I look forward to your proposal.
IMPORTANT: I will not go over the budget, if you want to try to discuss it I will go with someone else.
Here's a basic example, the project will not be bigger than this, if you want to approach this differently then feel free to but here's an example:
#include <ntddk.h>
#include <wdf.h>
#include <vhf.h>
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD VHFMouseEvtDeviceAdd;
EVT_WDF_OBJECT_CONTEXT_CLEANUP VHFMouseEvtDriverContextCleanup;
typedef struct _DEVICE_CONTEXT {
VHFHANDLE VhfHandle;
BOOLEAN AbsoluteMode;
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)
// HID Report Descriptor for a mouse with absolute and relative positioning
const UCHAR g_VHFMouseHidReportDescriptor[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
// Buttons
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
// Padding
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x81, 0x03, // Input (Constant)
// Relative X/Y
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x06, // Input (Data, Variable, Relative)
// Absolute X/Y
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x16, 0x00, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data, Variable, Absolute)
0xC0 // End Collection
};
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
KdPrint(("VHFMouse DriverEntry\n"));
WDF_DRIVER_CONFIG_INIT(&config, VHFMouseEvtDeviceAdd);
config.EvtDriverUnload = VHFMouseEvtDriverContextCleanup;
status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
if (!NT_SUCCESS(status)) {
KdPrint(("WdfDriverCreate failed: 0x%x\n", status));
}
return status;
}
NTSTATUS VHFMouseEvtDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
{
WDFDEVICE device;
NTSTATUS status;
PDEVICE_CONTEXT deviceContext;
WDF_OBJECT_ATTRIBUTES attributes;
VHF_CONFIG vhfConfig;
UNREFERENCED_PARAMETER(Driver);
KdPrint(("VHFMouseEvtDeviceAdd\n"));
// Initialize device attributes
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
attributes.EvtCleanupCallback = VHFMouseEvtDriverContextCleanup;
// Create the device
status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if (!NT_SUCCESS(status)) {
KdPrint(("WdfDeviceCreate failed: 0x%x\n", status));
return status;
}
deviceContext = GetDeviceContext(device);
deviceContext->AbsoluteMode = FALSE; // Default to relative mode
// Initialize VHF
VHF_CONFIG_INIT(&vhfConfig, WdfDeviceWdmGetDeviceObject(device));
// Set the HID report descriptor
vhfConfig.HidDescriptor.ReportDescriptorLength = sizeof(g_VHFMouseHidReportDescriptor);
vhfConfig.HidDescriptor.ReportDescriptor = g_VHFMouseHidReportDescriptor;
vhfConfig.HidDescriptor.VendorID = 0x1234;
vhfConfig.HidDescriptor.ProductID = 0x5678;
vhfConfig.HidDescriptor.VersionNumber = 0x0100;
status = VhfCreate(&vhfConfig, &deviceContext->VhfHandle);
if (!NT_SUCCESS(status)) {
KdPrint(("VhfCreate failed: 0x%x\n", status));
return status;
}
// Start the virtual device
status = VhfStart(deviceContext->VhfHandle);
if (!NT_SUCCESS(status)) {
KdPrint(("VhfStart failed: 0x%x\n", status));
VhfDelete(deviceContext->VhfHandle, TRUE);
return status;
}
return status;
}
VOID VHFMouseEvtDriverContextCleanup(_In_ WDFOBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
KdPrint(("VHFMouseEvtDriverContextCleanup\n"));
}
// Function to send a mouse report (exported for other drivers to use)
NTSTATUS SendMouseReport(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ BOOLEAN Absolute,
_In_ USHORT X,
_In_ USHORT Y,
_In_ CHAR RelX,
_In_ CHAR RelY,
_In_ BYTE Buttons)
{
NTSTATUS status;
HID_XFER_PACKET packet;
UCHAR reportBuffer[6] = {0};
// First byte is buttons (bits 0-4) and padding (bits 5-7)
reportBuffer[0] = Buttons & 0x1F;
if (Absolute) {
// Absolute coordinates (2 bytes each)
reportBuffer[2] = (UCHAR)(X & 0xFF);
reportBuffer[3] = (UCHAR)((X >> 8) & 0xFF);
reportBuffer[4] = (UCHAR)(Y & 0xFF);
reportBuffer[5] = (UCHAR)((Y >> 8) & 0xFF);
} else {
// Relative coordinates (1 byte each)
reportBuffer[1] = (UCHAR)RelX;
reportBuffer[2] = (UCHAR)RelY;
}
packet.reportId = 0;
packet.reportBuffer = reportBuffer;
packet.reportBufferLen = sizeof(reportBuffer);
status = VhfReadReportSubmit(DeviceContext->VhfHandle, &packet);
if (!NT_SUCCESS(status)) {
KdPrint(("VhfReadReportSubmit failed: 0x%x\n", status));
}
return status;
}
Key Requirements:
- Develop a kernel-mode driver that uses VHF to register a virtual mouse.
- Implement HID report descriptors for a mouse with input report capability.
- Support right-click down and right-click up events without moving the real cursor.
- The virtual mouse should only be detected as having the right-click button.
- Report the right-click event at a fixed position on the screen.
- Utilize VhfReadReportSubmit() to send HID input reports from the kernel driver.
- Needs to use C syntax and NOT C++.
Ideal Skills and Experience:
- Proficiency in developing KMDF drivers, especially with the Virtual HID Framework.
- Strong understanding of HID class drivers and Windows input systems.
- Experience with HID report descriptors and input report capabilities.
- Ability to work with kernel-mode programming and driver development in Windows.
The desired outcome is to have right-click events appear at an arbitrary X/Y position without affecting the real mouse cursor's position. If you have the expertise to accomplish this, I look forward to your proposal.
IMPORTANT: I will not go over the budget, if you want to try to discuss it I will go with someone else.
Here's a basic example, the project will not be bigger than this, if you want to approach this differently then feel free to but here's an example:
#include <ntddk.h>
#include <wdf.h>
#include <vhf.h>
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD VHFMouseEvtDeviceAdd;
EVT_WDF_OBJECT_CONTEXT_CLEANUP VHFMouseEvtDriverContextCleanup;
typedef struct _DEVICE_CONTEXT {
VHFHANDLE VhfHandle;
BOOLEAN AbsoluteMode;
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)
// HID Report Descriptor for a mouse with absolute and relative positioning
const UCHAR g_VHFMouseHidReportDescriptor[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
// Buttons
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
// Padding
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x81, 0x03, // Input (Constant)
// Relative X/Y
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x06, // Input (Data, Variable, Relative)
// Absolute X/Y
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x16, 0x00, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data, Variable, Absolute)
0xC0 // End Collection
};
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
KdPrint(("VHFMouse DriverEntry\n"));
WDF_DRIVER_CONFIG_INIT(&config, VHFMouseEvtDeviceAdd);
config.EvtDriverUnload = VHFMouseEvtDriverContextCleanup;
status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
if (!NT_SUCCESS(status)) {
KdPrint(("WdfDriverCreate failed: 0x%x\n", status));
}
return status;
}
NTSTATUS VHFMouseEvtDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
{
WDFDEVICE device;
NTSTATUS status;
PDEVICE_CONTEXT deviceContext;
WDF_OBJECT_ATTRIBUTES attributes;
VHF_CONFIG vhfConfig;
UNREFERENCED_PARAMETER(Driver);
KdPrint(("VHFMouseEvtDeviceAdd\n"));
// Initialize device attributes
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
attributes.EvtCleanupCallback = VHFMouseEvtDriverContextCleanup;
// Create the device
status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if (!NT_SUCCESS(status)) {
KdPrint(("WdfDeviceCreate failed: 0x%x\n", status));
return status;
}
deviceContext = GetDeviceContext(device);
deviceContext->AbsoluteMode = FALSE; // Default to relative mode
// Initialize VHF
VHF_CONFIG_INIT(&vhfConfig, WdfDeviceWdmGetDeviceObject(device));
// Set the HID report descriptor
vhfConfig.HidDescriptor.ReportDescriptorLength = sizeof(g_VHFMouseHidReportDescriptor);
vhfConfig.HidDescriptor.ReportDescriptor = g_VHFMouseHidReportDescriptor;
vhfConfig.HidDescriptor.VendorID = 0x1234;
vhfConfig.HidDescriptor.ProductID = 0x5678;
vhfConfig.HidDescriptor.VersionNumber = 0x0100;
status = VhfCreate(&vhfConfig, &deviceContext->VhfHandle);
if (!NT_SUCCESS(status)) {
KdPrint(("VhfCreate failed: 0x%x\n", status));
return status;
}
// Start the virtual device
status = VhfStart(deviceContext->VhfHandle);
if (!NT_SUCCESS(status)) {
KdPrint(("VhfStart failed: 0x%x\n", status));
VhfDelete(deviceContext->VhfHandle, TRUE);
return status;
}
return status;
}
VOID VHFMouseEvtDriverContextCleanup(_In_ WDFOBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
KdPrint(("VHFMouseEvtDriverContextCleanup\n"));
}
// Function to send a mouse report (exported for other drivers to use)
NTSTATUS SendMouseReport(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ BOOLEAN Absolute,
_In_ USHORT X,
_In_ USHORT Y,
_In_ CHAR RelX,
_In_ CHAR RelY,
_In_ BYTE Buttons)
{
NTSTATUS status;
HID_XFER_PACKET packet;
UCHAR reportBuffer[6] = {0};
// First byte is buttons (bits 0-4) and padding (bits 5-7)
reportBuffer[0] = Buttons & 0x1F;
if (Absolute) {
// Absolute coordinates (2 bytes each)
reportBuffer[2] = (UCHAR)(X & 0xFF);
reportBuffer[3] = (UCHAR)((X >> 8) & 0xFF);
reportBuffer[4] = (UCHAR)(Y & 0xFF);
reportBuffer[5] = (UCHAR)((Y >> 8) & 0xFF);
} else {
// Relative coordinates (1 byte each)
reportBuffer[1] = (UCHAR)RelX;
reportBuffer[2] = (UCHAR)RelY;
}
packet.reportId = 0;
packet.reportBuffer = reportBuffer;
packet.reportBufferLen = sizeof(reportBuffer);
status = VhfReadReportSubmit(DeviceContext->VhfHandle, &packet);
if (!NT_SUCCESS(status)) {
KdPrint(("VhfReadReportSubmit failed: 0x%x\n", status));
}
return status;
}