我正在研究WDK7的Microsoft Toaster示例代码,我发现了一个微妙的问题。
现在在Windows 7上尝试编译的驱动程序(WDM busenum和WDM featured1)。
在README的指导下,enum -p 1
添加了烤面包机设备,然后,我打开设备管理器(devmgmt),找到设备,卸载。
这将破坏烤面包机devnode(我相信); 我们可以看到 ToasterDevice01 节点现在从设备管理器中消失。 !devnode 0 1
显示烤面包机devnode仍然存在,State = DeviceNodeUninitialized(0x301),Previous State = DeviceNodeRemoved(0x312)。
然后,我执行enum -p 1
尝试再次添加设备。但我收到错误0x57(ERROR_INVALID_PARAMETER)。
我调试源代码并确定原因:buspdo.c
不区分devmgmt的禁用和卸载操作。他的代码逻辑是:
enum -u 1
),它会调用Bus_DestroyPdo()
这是正确的行为。Bus_DestroyPdo()
,这也是正确的。 问题,当最终用户从devmgmt执行卸载时,它会跟随禁用路径。现在发生了一些不好的事情:Windows删除了烤面包机devnode,但是烤面包机总线驱动程序没有销毁相应的PDO,因此,当下次用户执行enum -p 1
时,烤面包机总线驱动程序Bus_PlugInDevice()
指责烤面包机设备SerialNo == 1已经存在,因此用户请求失败。
现在我的问题很明确:我如何区分禁用和卸载,我应该在总线驱动程序或子设备驱动程序中进行此操作吗?也欢迎使用KMDF版本的答案。
答案 0 :(得分:0)
现在我可以得出结论。我们的客户端驱动程序无法区分从设备管理器中禁用和卸载。这是微软的设计。
为了进行区分,我们需要应用层的帮助。为子设备提供CoInstaller,并且当CoInstaller获得DIF_REMOVE通知时(这是devmgmt执行卸载的结果),将自定义IOCTL(例如IOCTL_UNPLUG_MY_CHILD)发送到内核驱动程序,以便内核驱动程序拔出相应的子设备。