如何在我的Windows驱动程序代码中区分devmgmt的禁用和卸载?

时间:2016-08-05 08:24:36

标签: windows driver kmdf wdm

我正在研究WDK7的Microsoft Toaster示例代码,我发现了一个微妙的问题。

现在在Windows 7上尝试编译的驱动程序(WDM busenum和WDM featured1)。

在README的指导下,enum -p 1添加了烤面包机设备,然后,我打开设备管理器(devmgmt),找到设备,卸载

Uninstall toaster device from devmgmt.msc

这将破坏烤面包机devnode(我相信); 我们可以看到 ToasterDevice01 节点现在从设备管理器中消失。 !devnode 0 1显示烤面包机devnode仍然存在,State = DeviceNodeUninitialized(0x301),Previous State = DeviceNodeRemoved(0x312)。

然后,我执行enum -p 1尝试再次添加设备。但我收到错误0x57(ERROR_INVALID_PARAMETER)。

enum -p 1 , got 0x57 error

我调试源代码并确定原因:buspdo.c不区分devmgmt的禁用和卸载操作。他的代码逻辑是:

  • 如果烤面包机被意外删除(enum -u 1),它会调用Bus_DestroyPdo()这是正确的行为。
  • 如果烤面包机从devmgmt中被禁用,则调用Bus_DestroyPdo(),这也是正确的。

问题,当最终用户从devmgmt执行卸载时,它会跟随禁用路径。现在发生了一些不好的事情:Windows删除了烤面包机devnode,但是烤面包机总线驱动程序没有销毁相应的PDO,因此,当下次用户执行enum -p 1时,烤面包机总线驱动程序Bus_PlugInDevice()指责烤面包机设备SerialNo == 1已经存在,因此用户请求失败。

enter image description here

BTW:Toaster的KMDF版本出现了类似的问题(今天只尝试了静态枚举版本)

现在我的问题很明确:我如何区分禁用和卸载,我应该在总线驱动程序或子设备驱动程序中进行此操作吗?也欢迎使用KMDF版本的答案。

1 个答案:

答案 0 :(得分:0)

现在我可以得出结论。我们的客户端驱动程序无法区分从设备管理器中禁用和卸载。这是微软的设计。

为了进行区分,我们需要应用层的帮助。为子设备提供CoInstaller,并且当CoInstaller获得DIF_REMOVE通知时(这是devmgmt执行卸载的结果),将自定义IOCTL(例如IOCTL_UNPLUG_MY_CHILD)发送到内核驱动程序,以便内核驱动程序拔出相应的子设备。