Tôi đang viết trình điều khiển bộ lọc bàn phím cho Windows và tôi cần chèn dữ liệu tổ hợp phím tùy chỉnh của mình vào hàng đợi thư Windows. Tôi đã quản lý để nắm bắt tất cả các phím được ép thiết OnReadCompletion() gọi lại để IoSetCompletionRoutine() trong đọc lái xe của tôi() chức năng như vậy:Làm thế nào để kích hoạt hoặc mô phỏng ngắt bàn phím?
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)
{
// ...
}
tài xế Bộ lọc này được gắn liền với tài xế kbdclass như vậy:
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
// ...
CCHAR ntNameBuffer[64] = "\\Device\\KeyboardClass0";
status = IoAttachDevice(deviceObject, &uKeyboardDeviceName, &DeviceExtension->pKeyboardDevice);
// ...
}
Vì vậy, tôi có thể bắt tất cả các phím bấm trong OnReadCompletion(). Nhưng tôi cần chèn thông tin của riêng mình vào luồng thông báo bàn phím. Dưới đây là 2 vấn đề với điều đó:
OnReadCompletion() chỉ được gọi khi nhấn phím. Lý tưởng nhất là tôi muốn bằng cách nào đó nó được gọi khi không có gì được nhấn. Tôi có thể làm điều đó bằng cách nào đó không? Tôi cần phải kích hoạt một bàn phím gián đoạn? Tôi đã cố gắng để viết lệnh vào một cổng bàn phím (0x60 và 0x64) với WRITE_PORT_UCHAR() nhưng điều đó không làm việc ra ngoài.
Tôi đã cố gắng chèn dữ liệu của mình vào IRP trong OnReadCompletion() để làm cho nó trông giống như ví dụ một phím được nhấn hai lần trong khi thực tế nó chỉ được nhấn một lần. Ai đó cũng có thể giúp tôi về điều đó, bởi vì những điều sau đây không hiệu quả?
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; }
Và khi tôi kiểm tra nó ví dụ như trong Notepad, tất cả tôi nhận được chỉ là một lá thư mỗi tổ hợp phím. Tôi thực sự tuyệt vọng. Hãy giúp tôi!
Tôi đã quản lý để thêm dữ liệu mới vào bộ đệm Hệ thống IRP. Bí quyết là sử dụng mã đột quỵ chính khác nhau, không giống như mã lệnh ở trên. Vì vậy, nếu bạn muốn chèn một MakeCode = 2 (bằng cách nhấn nút "1"), làm điều này trong OnReadCompletion(): RtlCopyMemory (newSystemBuffer, keys, Irp-> IoStatus.Information); keys-> MakeCode = 2; RtlCopyMemory (newSystemBuffer + Irp-> IoStatus.Information, keys, Irp-> IoStatus.Information); –
Sự khác biệt là trong "keys-> MakeCode = 2;" thay đổi MakeCode trong thông báo KEYBOARD_INPUT_DATA thứ hai. Và bạn nhận được "1" được thêm sau mỗi lần nhấn phím, ví dụ như trong notepad. –
Vì vậy, câu hỏi duy nhất còn lại là làm cách nào để kích hoạt gián đoạn? –