HID提交HID_XFER_PACKET模拟击键
HID submit HID_XFER_PACKET to simulate keystrokes
我正在尝试编写一个 KMDF 驱动程序来模拟击键。
当驱动程序接收到 IOCTL_HID_READ_REPORT
时,它会将请求重定向到队列:
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
KdPrint(("GET DEVICE DESCRIPTOR\n"));
_Analysis_assume_(deviceContext->HidDescriptor.bLength != 0);
status = RequestCopyFromBuffer(Request, &deviceContext->HidDescriptor, deviceContext->HidDescriptor.bLength);
break;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
KdPrint(("GET DEVICE ATTRIBUTES\n"));
status = RequestCopyFromBuffer(Request, &queueContext->DeviceContext->HidDeviceAttributes, sizeof(HID_DEVICE_ATTRIBUTES));
break;
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
KdPrint(("GET REPORT DESCRIPTOR\n"));
status = RequestCopyFromBuffer(Request, deviceContext->ReportDescriptor, deviceContext->HidDescriptor.DescriptorList[0].wReportLength);
break;
case IOCTL_HID_READ_REPORT:
WdfRequestForwardToIoQueue(Request, QueueContext->DeviceContext->ManualQueue); // <= HERE
break;}
有了定时器,项目会定期出队,并在请求中复制键盘输入报告
void EvtTimerFunc(_In_ WDFTIMER Timer)
{
NTSTATUS status;
WDFQUEUE queue;
PMANUAL_QUEUE_CONTEXT queueContext;
WDFREQUEST request;
KdPrint(("EvtTimerFunc\n"));
queue = (WDFQUEUE)WdfTimerGetParentObject(Timer);
queueContext = GetManualQueueContext(queue);
//
// see if we have a request in manual queue
//
status = WdfIoQueueRetrieveNextRequest(queueContext->Queue, &request);
if (NT_SUCCESS(status))
{
KdPrint(("Handling"));
HID_XFER_PACKET hidXferPacket;
BYTE keycodes[6] = {0};
keycodes[0] = 0x04;
HID_KEYBOARD_INPUT_REPORT report;
report.ReportId = REPORT_ID_KEYBOARD_INPUT;
report.Modifiers = 0;
report._reserved = 0;
memcpy(&report.KeyCodes, &keycodes, 6);
hidXferPacket.reportBuffer = (UCHAR*)&report;
hidXferPacket.reportBufferLen = sizeof(HID_KEYBOARD_INPUT_REPORT);
hidXferPacket.reportId = REPORT_ID_KEYBOARD_INPUT;
RequestCopyFromBuffer(request, hidXferPacket.reportBuffer, sizeof(HID_KEYBOARD_INPUT_REPORT));
WdfRequestComplete(request, status);
}
}
虽然一切正常,但没有发出击键。我错过了什么?!
描述符:
HID_REPORT_DESCRIPTOR g_reportDescriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xA1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_MOUSE_INPUT,
0x09, 0x01, // USAGE_PAGE (Pointer)
0xA1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Buttons)
0x19, 0x01, // USAGE_MINIMUM (1)
0x29, 0x03, // USAGE_MAXIMUM (3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data, Variable, Absolute)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x01, // INPUT (Constant)
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)
0xC0, // END_COLLECTION
0xC0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_MOUSE_OUTPUT,
0x09, 0x00, // USAGE (Undefined)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x08, // REPORT_SIZE (8)
0x91, 0x02, // OUTPUT (Data, Variable, Absolute)
0xc0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xA1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_KEYBOARD_INPUT,
0x05, 0x07, // USAGE_PAGE (Keyboard Key Codes)
0x19, 0xE0, // USAGE_MINIMUM (224)
0x29, 0xE7, // USAGE_MAXIMUM (231)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data, Variable, Absolute)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x01, // INPUT (Constant)
0x19, 0x00, // USAGE_MINIMUM (0)
0x29, 0x65, // USAGE_MAXIMUM (101)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x00, // INPUT (Data, Array, Absolute)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x91, 0x02, // OUTPUT (Data, Variable, Absolute)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x01, // OUTPUT (Constant)
0xC0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_KEYBOARD_OUTPUT,
0x09, 0x00, // USAGE (Undefined)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x08, // REPORT_SIZE (8)
0x91, 0x02, // OUTPUT (Data, Variable, Absolute)
0xc0 // END_COLLECTION
};
HID_DESCRIPTOR g_hidDescriptor = {
0x09, // length of HID descriptor
0x21, // descriptor type == HID 0x21
0x0100, // hid spec release
0x00, // country code == Not Specified
0x01, // number of HID class descriptors
{ // DescriptorList[0]
0x22, // report descriptor type 0x22
sizeof(g_reportDescriptor) // total length of report descriptor
}
};
我使用 Hyper V 虚拟机作为调试机器,这就是它不起作用的原因。
我一用另一台电脑,按键就发过来了
如果您要模拟击键或鼠标移动,我建议这样做:
看看 https://github.com/djpnewton/vmulti(将 HidMapper 集成到您的驱动程序)
避免使用 Hyper V 进行测试
我正在尝试编写一个 KMDF 驱动程序来模拟击键。
当驱动程序接收到 IOCTL_HID_READ_REPORT
时,它会将请求重定向到队列:
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
KdPrint(("GET DEVICE DESCRIPTOR\n"));
_Analysis_assume_(deviceContext->HidDescriptor.bLength != 0);
status = RequestCopyFromBuffer(Request, &deviceContext->HidDescriptor, deviceContext->HidDescriptor.bLength);
break;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
KdPrint(("GET DEVICE ATTRIBUTES\n"));
status = RequestCopyFromBuffer(Request, &queueContext->DeviceContext->HidDeviceAttributes, sizeof(HID_DEVICE_ATTRIBUTES));
break;
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
KdPrint(("GET REPORT DESCRIPTOR\n"));
status = RequestCopyFromBuffer(Request, deviceContext->ReportDescriptor, deviceContext->HidDescriptor.DescriptorList[0].wReportLength);
break;
case IOCTL_HID_READ_REPORT:
WdfRequestForwardToIoQueue(Request, QueueContext->DeviceContext->ManualQueue); // <= HERE
break;}
有了定时器,项目会定期出队,并在请求中复制键盘输入报告
void EvtTimerFunc(_In_ WDFTIMER Timer)
{
NTSTATUS status;
WDFQUEUE queue;
PMANUAL_QUEUE_CONTEXT queueContext;
WDFREQUEST request;
KdPrint(("EvtTimerFunc\n"));
queue = (WDFQUEUE)WdfTimerGetParentObject(Timer);
queueContext = GetManualQueueContext(queue);
//
// see if we have a request in manual queue
//
status = WdfIoQueueRetrieveNextRequest(queueContext->Queue, &request);
if (NT_SUCCESS(status))
{
KdPrint(("Handling"));
HID_XFER_PACKET hidXferPacket;
BYTE keycodes[6] = {0};
keycodes[0] = 0x04;
HID_KEYBOARD_INPUT_REPORT report;
report.ReportId = REPORT_ID_KEYBOARD_INPUT;
report.Modifiers = 0;
report._reserved = 0;
memcpy(&report.KeyCodes, &keycodes, 6);
hidXferPacket.reportBuffer = (UCHAR*)&report;
hidXferPacket.reportBufferLen = sizeof(HID_KEYBOARD_INPUT_REPORT);
hidXferPacket.reportId = REPORT_ID_KEYBOARD_INPUT;
RequestCopyFromBuffer(request, hidXferPacket.reportBuffer, sizeof(HID_KEYBOARD_INPUT_REPORT));
WdfRequestComplete(request, status);
}
}
虽然一切正常,但没有发出击键。我错过了什么?!
描述符:
HID_REPORT_DESCRIPTOR g_reportDescriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xA1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_MOUSE_INPUT,
0x09, 0x01, // USAGE_PAGE (Pointer)
0xA1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Buttons)
0x19, 0x01, // USAGE_MINIMUM (1)
0x29, 0x03, // USAGE_MAXIMUM (3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data, Variable, Absolute)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x01, // INPUT (Constant)
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)
0xC0, // END_COLLECTION
0xC0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_MOUSE_OUTPUT,
0x09, 0x00, // USAGE (Undefined)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x08, // REPORT_SIZE (8)
0x91, 0x02, // OUTPUT (Data, Variable, Absolute)
0xc0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xA1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_KEYBOARD_INPUT,
0x05, 0x07, // USAGE_PAGE (Keyboard Key Codes)
0x19, 0xE0, // USAGE_MINIMUM (224)
0x29, 0xE7, // USAGE_MAXIMUM (231)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data, Variable, Absolute)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x01, // INPUT (Constant)
0x19, 0x00, // USAGE_MINIMUM (0)
0x29, 0x65, // USAGE_MAXIMUM (101)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x00, // INPUT (Data, Array, Absolute)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x91, 0x02, // OUTPUT (Data, Variable, Absolute)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x01, // OUTPUT (Constant)
0xC0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_KEYBOARD_OUTPUT,
0x09, 0x00, // USAGE (Undefined)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x08, // REPORT_SIZE (8)
0x91, 0x02, // OUTPUT (Data, Variable, Absolute)
0xc0 // END_COLLECTION
};
HID_DESCRIPTOR g_hidDescriptor = {
0x09, // length of HID descriptor
0x21, // descriptor type == HID 0x21
0x0100, // hid spec release
0x00, // country code == Not Specified
0x01, // number of HID class descriptors
{ // DescriptorList[0]
0x22, // report descriptor type 0x22
sizeof(g_reportDescriptor) // total length of report descriptor
}
};
我使用 Hyper V 虚拟机作为调试机器,这就是它不起作用的原因。 我一用另一台电脑,按键就发过来了
如果您要模拟击键或鼠标移动,我建议这样做:
看看 https://github.com/djpnewton/vmulti(将 HidMapper 集成到您的驱动程序)
避免使用 Hyper V 进行测试