容器 ID 概述
在 Windows 系列操作系统中,设备基本上是功能设备实例的集合,每个实例都表示一个功能终结点,该终结点支持与设备进行某种形式的通信。
术语 设备节点 (devnode) 是指此类功能终结点的 驱动程序堆栈 ,以及描述终结点及其关联状态的属性。 例如,支持打印机、扫描仪和传真功能的多功能设备可以有多个开发节点,设备中的每个功能终结点对应一个开发节点。
在 Windows 7 之前,每个功能终结点都有一个与之关联的开发节点。 Windows 平台组件和第三方应用程序可以查询开发节点以获取设备状态和信息,并且可以通过功能终结点公开的接口与设备硬件通信。
对于单功能设备,单个开发节点包含与设备的功能终结点相关的所有信息。 同样,多功能设备具有多个与每个设备的功能终结点关联的开发节点。 但是,Windows 无法识别一组开发节点源自同一物理设备。 属于同一多功能设备的每个开发节点不包含任何标识信息,这些信息使即插即用 (PnP) 管理器能够将多个开发节点分组为单个设备。 因此,无法对设备和单个物理设备提供的功能进行整体视图。
从 Windows 7 开始,操作系统使用新的 ID (容器 ID) 对源自特定物理设备的每个实例的一个或多个开发节点进行分组。 容器 ID 是每个开发节点的属性,通过全局唯一标识符 (GUID) 值指定。
计算机中安装的物理设备的每个实例都有一个唯一的容器 ID。 表示该物理设备实例上的函数的所有开发节点共享相同的容器 ID。 下图显示了该关系的示例。
有一个容器 ID 对总线驱动程序具有特殊含义:NULL_GUID定义为: {00000000-0000-0000-0000-000000000000}。
通常,在报告容器 ID 时,不要将NULL_GUID作为默认情况返回。 相反,不要处理 BusQueryContainerIDs 案例的IRP_MN_QUERY_ID,而是让 PnP 应用其默认逻辑。
将NULL_GUID作为容器 ID 返回时,总线驱动程序会向 PnP 声明设备不得是任何容器的一部分,因此返回NULL_GUID仅在非常特殊的情况下才适用。 例如,卷设备等 开发节点 可能跨多个容器中的多个磁盘,但不属于任何容器。 此类设备的 DEVPKEY_Device_BaseContainerId 等于 NULL_GUID,并且根本没有 DEVPKEY_Device_ContainerId 。
除了非常特殊的情况外,总线驱动程序在报告硬件设备时绝不应返回NULL_GUID,并且总线驱动程序应防止报告其总线NULL_GUID值的故障硬件。 在这些情况下,总线驱动程序应将其视为设备错误,或将其视为设备未报告值。