当前位置: 代码迷 >> 驱动开发 >> 撤销键盘驱动中的IRP
  详细解决方案

撤销键盘驱动中的IRP

热度:49   发布时间:2016-04-28 10:17:38.0
取消键盘驱动中的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
  相关解决方案