Sto scrivendo un driver di filtro della tastiera per Windows e ho bisogno di inserire i miei dati di battitura personalizzati nella coda dei messaggi di Windows. Sono riuscito a catturare tutti i tasti che vengono premuti insediano OnReadCompletion() di callback per IoSetCompletionRoutine() in Per saperne di mio autista() la funzione in questo modo:Come attivare o simulare l'interruzione della tastiera?
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)
{
// ...
}
Questo driver di filtro è attaccato al conducente kbdclass in questo modo:
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
// ...
CCHAR ntNameBuffer[64] = "\\Device\\KeyboardClass0";
status = IoAttachDevice(deviceObject, &uKeyboardDeviceName, &DeviceExtension->pKeyboardDevice);
// ...
}
Quindi, posso prendere tutti i tasti premuti in OnReadCompletion(). Ma ho bisogno di inserire le mie informazioni nel flusso dei messaggi della tastiera. Qui ci sono 2 problemi:
OnReadCompletion() viene richiamato solo quando viene premuto un tasto. Idealmente mi piacerebbe in qualche modo chiamarlo quando non viene premuto nulla. Posso farlo in qualche modo? Devo attivare un interrupt di tastiera? Ho provato a scrivere comandi su una tastiera (0x60 e 0x64) con WRITE_PORT_UCHAR() ma non ha funzionato.
Ho cercato di inserire i miei dati in IRP in OnReadCompletion() per far sembrare che ad esempio un tasto sia stato premuto due volte mentre in realtà è stato premuto una sola volta. Qualcuno può aiutarmi anche su quello, perché il seguente non ha funzionato?
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; }
E quando verifico che per esempio in Blocco note, tutto quello che ottiene è solo una lettera per ogni tasto. Sono davvero disperata. Per favore aiuto!
Sono riuscito ad aggiungere nuovi dati al buffer del sistema IRP. Il trucco consisteva nell'usare un codice diverso per il tratto chiave, non lo stesso come nel codice sopra. Quindi, se vuoi inserire un MakeCode = 2 (uguale a premere il pulsante "1"), fallo in OnReadCompletion(): RtlCopyMemory (newSystemBuffer, keys, Irp-> IoStatus.Information); keys-> MakeCode = 2; RtlCopyMemory (newSystemBuffer + Irp-> IoStatus.Information, keys, Irp-> IoStatus.Information); –
La differenza è in "keys-> MakeCode = 2;" che cambia MakeCode nel secondo messaggio KEYBOARD_INPUT_DATA. E ricevi un "1" aggiunto dopo ogni sequenza di tasti, ad esempio nel blocco note. –
Quindi l'unica domanda rimane è come posso attivare un interrupt? –