取消键盘驱动中的IRP
键盘过滤驱动中,挂接到键盘设备上之后,第一个按键,过滤驱动中是接收不到的.
现在要解决这个问题:
1.向键盘模拟发送一个按键,将那个IRP消耗掉
2.结束掉这个IRP
第一种想法:我在网上找到一些资料,但是都是汇编的,因为程序有32和64两种平台的,64位又不支持__asm,我对汇编实在不熟悉,也就没有改
现在想从第二个办法入手,现在做的是,找到kbdclass的驱动对像,然后,遍历,驱动下面的设备,在设备中的DeviceExtension->ReadQueue中
获取IRP,然后,cancel掉.
用ObReferenceObjectByName这个函数找到kdbclass的驱动对像指针
cancel的代码如下:(我是从DDK里面找到源码)
VOID
KeyboardClassCleanupQueue (
IN PDEVICE_OBJECT DeviceObject,
IN PKDB_DEVICE_EXTENSION DeviceExtension,
IN PFILE_OBJECT FileObject
)
/*++
Routine Description:
This does the work of MouseClassCleanup so that we can also do that work
during remove device for when the grand master isn't enabled.
--*/
{
KdPrint(("In KeyboardClassCleanupQueue\n"));
PIRP irp;
LIST_ENTRY listHead, *entry;
KIRQL irql;
PIO_STACK_LOCATION stack;
PDRIVER_CANCEL oldCancelRoutine;
UNREFERENCED_PARAMETER(DeviceObject);
InitializeListHead(&listHead);
KeAcquireSpinLock(&DeviceExtension->SpinLock, &irql);
/*if (IsListEmpty(DeviceExtension->ReadQueue.Flink))
{
KeReleaseSpinLock(&DeviceExtension->SpinLock, irql);
return ;
}*/
for (entry = DeviceExtension->ReadQueue.Flink;
entry != &DeviceExtension->ReadQueue;) {
PLIST_ENTRY nextEntry = entry->Flink;
irp = CONTAINING_RECORD (entry, IRP, Tail.Overlay.ListEntry);
stack = IoGetCurrentIrpStackLocation (irp);
//
// If no FileObject is given, lets cleanup all of them,
// otherwise lets try to find only the matching ones
//
if (NULL == FileObject || stack->FileObject == FileObject) {
RemoveEntryList (entry);
oldCancelRoutine = IoSetCancelRoutine (irp, NULL);
//
// IoCancelIrp() could have just been called on this IRP.
// What we're interested in is not whether IoCancelIrp() was called
// (ie, nextIrp->Cancel is set), but whether IoCancelIrp() called (or
// is about to call) our cancel routine. To check that, check the result
// of the test-and-set macro IoSetCancelRoutine.
//
if (oldCancelRoutine) {
//
// Cancel routine not called for this IRP. Queue this IRP.
//
irp->IoStatus.Status = STATUS_CANCELLED;
irp->IoStatus.Information = 0;
InsertTailList (&listHead, &irp->Tail.Overlay.ListEntry);
}
else {
//
// This IRP was just cancelled and the cancel routine was (or will
// be) called. The cancel routine will complete this IRP as soon as
// we drop the spinlock. So don't do anything with the IRP.
//
// Also, the cancel routine will try to dequeue the IRP, so make the
// IRP's listEntry point to itself.
//
ASSERT (irp->Cancel);
InitializeListHead (&irp->Tail.Overlay.ListEntry);
}
}
entry = nextEntry;
//break;
}
KeReleaseSpinLock(&DeviceExtension->SpinLock, irql);
//
// Complete these irps outside of the spin lock
//
while (! IsListEmpty (&listHead)) {
entry = RemoveHeadList (&listHead);
irp = CONTAINING_RECORD (entry, IRP, Tail.Overlay.ListEntry);
IoCompleteRequest (irp, IO_NO_INCREMENT);
IoReleaseRemoveLock (&DeviceExtension->RemoveLock, irp);
}
}