原始PDO将IOCTL发送到上层过滤器驱动程序(kbfiltr / moufiltr)以启用/禁用设备

时间:2009-09-16 03:28:45

标签: winapi driver device-driver wdk kmdf

我对驱动程序开发很陌生,并试图编写一个简单的过滤器驱动程序来启用或禁用键盘或鼠标设备。如果我可以使它工作,我想用它来插入鼠标插入我的笔记本电脑上的触摸板。我意识到可能有软件已经做到这一点,但我真的对设备驱动程序感兴趣,并希望自己学习如何做到这一点。

我正在使用WDK附带的 kbfiltr moufiltr 示例,作为上层过滤器驱动程序安装。 kbfiltr示例创建一个pdo,可以通过usermode程序枚举和连接。这允许我将IOCTL发送到由 KbFilter_EvtIoDeviceControlForRawPdo 处理的PDO。但是,当我尝试执行与过滤器驱动程序相关的任何操作时,例如调用 KbFilter_EvtIoInternalDeviceControl ,这样我就可以执行类似

的操作
VOID
KbFilter_EvtIoInternalDeviceControl(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    )
    ...
    hDevice = WdfIoQueueGetDevice(Queue);
    devExt = FilterGetData(hDevice);

    switch (IoControlCode) {      
    ...
      case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
       //
       // Clear the connection parameters in the device extension.
       //
       devExt->UpperConnectData.ClassService = NULL;
       break;
    ...
    }

我得到了一个BSOD。它不是上面的代码,在vanilla示例中,set to null被注释掉,只是调用Kbfilter会导致BSOD。我试图直接在PDO中设置设备扩展,但这也会导致BSOD,大概是因为它是PDO devExt,而不是kbfiltr的?

(相关:什么是从BSOD获取堆栈跟踪的好方法?我使用Virtual PC作为我的测试环境和未经检查的XPSP3版本)

我无法直接向驱动程序堆栈发送IOCTL_INTERNAL_KEYBOARD_DISCONNECT(我知道输入设备一次只接受一个连接?)因此需要原始PDO。我真的只需要发送两个IOCTL(启用和禁用),我想我会使用键盘断开连接,因为这些已经定义了。

如果我对这些假设有任何错误,请告诉我,我知道我真的是一个菜鸟,但我没有找到很多关于通过PDO进行此类通信的文档。

2 个答案:

答案 0 :(得分:16)

好的,我终于解决了这个问题,我的司机正在工作。

实施KMDF过滤器驱动程序

感谢Sergius提出了COM端口方法,因为这有助于我设置WinDbg. This awesome blog post解释如何快速设置它,基本上你让VPC设置一个com端口作为命名管道,在虚拟化操作系统上启用内核调试模式,并在启动时连接到它。然后,您可以在加载驱动程序时获取所有DbgPrint消息并执行更多操作,但在启动过程中只是跟踪消息对我来说是一个巨大的帮助。

我认为我的主要问题是尝试在KbFiltr中重用内部IOCTL。这对我来说只是一个糟糕的设计理念,因为我不理解内部IOCTL和其他IOCTL之间的区别 - 内部IOCTLS(如IOCTL_INTERNAL_KEYBOARD_DISCONNECT)具有受限的访问条件,只应由其他驱动程序或内核发送。另外this KB article "How to send IOCTL to filter driver"是使用相同控制设备结构的示例,但它是WDM。

无论如何,在整个周末与KbFiltr示例战斗后,我终于放弃并开始使用WDF Toaster/filtr example。这是一个更准系统的KMDF过滤器驱动程序,我不得不使用KbFiltr和MouFiltr填写很多空白。 Toaster过滤器驱动程序操作类似于KbFiltr,但它创建了一个控制设备而不是PDO。它还为控制设备设置dos设备名称,以便您可以从usermode与它进行通信,而无需Pinvoke执行该步骤。控制设备允许您通过迭代集合来控制所有装有过滤器驱动程序的设备。 waitlock用于同步对集合的访问。

我还能够修改INF文件(使用Mouse类而不是Toaster类)并直接在我的测试机器上应用它而不修改驱动程序代码!从有效的东西开始要容易得多。 This page提供了一个全面的列表,列出了您应该更改的内容以适应样本。

答案 1 :(得分:3)

首先:您可以在用户模式下执行您想要执行的操作(在插入鼠标时禁用笔记本电脑上的触摸板)。它会更简单,更安全。查看Using Device Installation FunctionsWM_DEVICECHANGE

调试代码中的问题:从BSOD获取内存转储或设置内核调试器连接(使用重定向到管道的虚拟PC上的COM端口)。见Debugging Tools for Windows

玩得开心!