1

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

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

按照自述文件的指导,enum -p 1添加一个烤面包机设备,然后,我打开设备管理器(devmgmt),找到设备,卸载它。

从 devmgmt.msc 卸载烤面包机设备

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

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

枚举 -p 1 ,得到 0x57 错误

我调试源代码并找出原因:buspdo.c没有区分devmgmt的Disable和Uninstall操作。他的代码逻辑是:

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

问题是,当最终用户从 devmgmt 执行卸载时,它遵循禁用路径。现在发生了一些不好的事情:Windows 删除了 toaster devnode,但是 toaster bus driver 不会破坏相应的 PDO,因此,当用户下次执行时enum -p 1,toaster bus driverBus_PlugInDevice()会指责 SerialNo==1 的 toaster 设备已经存在,因此失败用户请求。

在此处输入图像描述

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

现在我的问题很清楚了:如何区分禁用和卸载,我应该在总线驱动程序还是子设备驱动程序中进行?也欢迎回答 KMDF 版本。

4

1 回答 1

0

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

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

于 2017-07-01T11:58:33.347 回答