簡體   English   中英

如何觸發或模擬鍵盤中斷?

[英]How to trigger or simulate keyboard interrupt?

我正在為Windows編寫鍵盤過濾器驅動程序,我需要將自定義擊鍵數據插入Windows消息隊列。 我已經設法捕獲所有按下的鍵,在我的驅動程序的Read()函數中將OnReadCompletion()回調設置為IoSetCompletionRoutine(),如下所示:

NTSTATUS Read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;

    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, OnReadCompletion, DeviceObject, TRUE, TRUE, TRUE);
    return IoCallDriver (deviceExtension->pKeyboardDevice, Irp);
}

NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
// ...
}

此過濾器驅動程序附加到kbdclass驅動程序,如下所示:

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
// ...
CCHAR ntNameBuffer[64] = "\\Device\\KeyboardClass0";
status = IoAttachDevice(deviceObject, &uKeyboardDeviceName, &DeviceExtension->pKeyboardDevice);
// ...

}

所以,我可以捕獲OnReadCompletion()中按下的所有鍵。 但我需要將自己的信息插入鍵盤消息流中。 這有兩個問題:

  1. OnReadCompletion()僅在按下某個鍵時調用。 理想情況下,我想以某種方式在沒有按下時調用它。 我能以某種方式這樣做嗎? 我需要觸發鍵盤中斷嗎? 我嘗試使用WRITE_PORT_UCHAR()將命令寫入鍵盤端口(0x60和0x64)但是沒有用完。

  2. 我試圖在OnReadCompletion()中將我的數據插入到IRP中,使其看起來像一個按鍵被按下兩次,而實際上只按了一次。 也有人可以幫我解決這個問題,因為下面沒有成功嗎?

     NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PIO_STACK_LOCATION IrpStackLocation = NULL; INT BufferLength; INT numKeys = 0, i = 0; PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; IrpStackLocation = IoGetCurrentIrpStackLocation(Irp); BufferLength = IrpStackLocation->Parameters.Read.Length; if(Irp->IoStatus.Status == STATUS_SUCCESS) { PCHAR newSystemBuffer, oldSystemBuffer; PKEYBOARD_INPUT_DATA keys = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA); for(i = 0; i < numKeys; i++) { // here we print whatever was pressed DbgPrint("%s -- ScanCode: %x\\n", __FUNCTION__, keys[i].MakeCode); } // allocate new buffer twice as big as original newSystemBuffer = ExAllocatePool(NonPagedPool, Irp->IoStatus.Information * 2); // copy existing buffer twice into new buffer RtlCopyMemory(newSystemBuffer, keys, Irp->IoStatus.Information); RtlCopyMemory(newSystemBuffer + Irp->IoStatus.Information, keys, Irp->IoStatus.Information); // assign new buffer to Irp->AssociatedIrp.SystemBuffer oldSystemBuffer = Irp->AssociatedIrp.SystemBuffer; Irp->AssociatedIrp.SystemBuffer = newSystemBuffer; // tell IRP that we now have twice as much data Irp->IoStatus.Information *= 2; // free the old buffer ExFreePool(oldSystemBuffer); } if(Irp->PendingReturned) IoMarkIrpPending(Irp); return Irp->IoStatus.Status; } 

當我在記事本中測試它時,我得到的只是每次擊鍵一個字母。 我真的很絕望。 請幫忙!

我認為應該有四種選擇:

1)您可以創建一個新的IRP來調用kbdclass驅動程序,而不是傳遞您收到的IRP。 無論何時想要插入數據以及每次有真正的鍵擊傳遞,您都可以完成原始IRP。

2)你可以有兩個設備,第二個是鍵盤設備。 然后,您將使用kbdclass過濾器來刪除擊鍵,並使用鍵盤設備添加它們。

3)您可以將驅動程序重新設計為鍵盤設備的上層過濾器,類似於MSDN示例驅動程序kbfiltr。

4)您可以有兩個設備,第二個是一個或多個鍵盤設備的上部過濾器。 您可以使用kbdclass過濾器來刪除擊鍵,使用鍵盤設備過濾器來添加它們。

我認為第一種選擇是最好的,但我不是專家。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM