首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 驱动开发 >

撤销键盘驱动中的IRP

2014-04-19 
取消键盘驱动中的IRP键盘过滤驱动中,挂接到键盘设备上之后,第一个按键,过滤驱动中是接收不到的.现在要解决

取消键盘驱动中的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);
    }
}


代码在进入for之后的第一句话PLIST_ENTRY nextEntry = entry->Flink;,就会出现异常.应该是内存访问的异常.我没有找到太多关于ReadQueue这个域的资料,有谁知道这个是因为什么?
或者想要解决第一个按键拿不到的问题,是否有别的办法?望指教.
[解决办法]
Kdbclass对应的PKDB_DEVICE_EXTENSION结构是Kdbclass私有的,别的驱动程序是不应该去访问控制的。

你的过滤驱动程序只能试图去访问控制自己驱动对象的Device_Extension结构。

另外,能不能解释一下你要做什么,碰到的具体问题是什么?

热点排行