WMI WNODE_XXX 结构

WMI 使用名为 WNODE_XXX 的标准数据结构集在用户模式数据使用者和内核模式数据提供程序(如驱动程序)之间传递数据。 如果驱动程序通过调用 WmiSystemControl来处理 WMI 请求,则不需要驱动程序读取或写入 WNODE_XXX 结构。 否则,驱动程序必须在 Parameters.WMI.Buffer 和/或将输出 WNODE_XXX 解释为该位置 WNODE_XXX

下表列出了 WMI IRP 及其相应的 WNODE_XXX 结构。

WMI IRP 相关WNODE_XXX结构

IRP_MN_CHANGE_SINGLE_INSTANCE

WNODE_SINGLE_INSTANCE

IRP_MN_CHANGE_SINGLE_ITEM

WNODE_SINGLE_ITEM

IRP_MN_EXECUTE_METHOD

WNODE_METHOD_ITEM

IRP_MN_QUERY_ALL_DATA

WNODE_ALL_DATA

IRP_MN_QUERY_SINGLE_INSTANCE

WNODE_SINGLE_INSTANCE

另外两个 WNODE_XXX 结构(WNODE_EVENT_ITEMWNODE_EVENT_REFERENCE)用于发送已启用事件的通知。 注册事件块的驱动程序将通过调用 ioWMIWriteEvent 并传递 WNODE_EVENT_XXX 结构将事件通知发送到 WMI。 有关发送 WMI 事件的信息,请参阅 发送 WMI 事件

每个 WNODE_XXX 结构都包含以下各项:

  • 嵌入式 WNODE_HEADER 结构,其中包含所有 WNODE_XXX 共有的信息,包括缓冲区大小、表示数据块的 GUID 以及指示 WNODE_XXX 结构类型(无论是使用静态实例名称还是动态实例名称)的标志。 块的其他特征。

  • 特定 WNODE_XXX 结构的固定成员,例如实例名称和数据的偏移量。

IRP 缓冲区(Parameters.WMI.Buffer)中的 WNODE_XXX 结构通常后跟与请求相关的变量数据,例如动态实例名称、静态实例名称字符串、方法的输入或输出,或数据块的一个或多个实例的数据。 因此,缓冲区的大小必须超过 sizeof(WNODE_XXX), 所涉及的变量数据量。

请注意,WMI 不会对驱动程序提供的变量数据执行类型检查。 驱动程序必须在输出缓冲区中的相应边界上对齐输出数据,以便数据使用者可以正确分析数据。 具体而言,每个实例必须从 8 字节边界开始,并且每个实例的项都必须根据驱动程序之前注册的数据块架构在自然边界上对齐。 动态实例名称可以在 2 字节边界上对齐。

下图显示了 IRP 缓冲区的块图,其中包含驱动程序在响应 IRP_MN_QUERY_SINGLE_INSTANCE 请求时可能返回的 WNODE_SINGLE_INSTANCE 结构。

图,说明包含 wnode-single 实例的 irp 缓冲区。

从上图顶部开始:

  • WNODE_SINGLE_INSTANCE 开头的 WNODE_HEADER 结构包含在 WnodeHeader 成员中。 WMI 在发送请求之前填写 WNODE_HEADER 的所有成员。 在 WNODE_HEADER

    • WnodeHeader.Buffersize 指示 WNODE_SINGLE_INSTANCE的大小,包括结构固定成员之后的数据。 (WnodeHeader.Buffersize 的值通常小于 Parameters.WMI.Buffersize,指示 WMI 分配的缓冲区的大小,以接收驱动程序的输出。
    • WnodeHeader.Guid 包含标识数据块的 GUID。
    • 在此示例中,WnodeHeader.Flags 指示此结构是 WNODE_SINGLE_INSTANCE,并且数据块使用静态实例名称。
  • 由于数据块使用静态实例名称,因此 WMI 将 InstanceIndex 设置为驱动程序注册块时驱动程序传递的静态实例名称列表中的实例索引。 不使用 OffsetInstanceNames

  • WMI DataBlockOffset 来指示缓冲区开头到实例数据的第一个字节的偏移量。 (驱动程序不得更改此值)同样,由于数据块使用静态实例名称,此偏移量指示与 VariableData相同的位置。 如果数据块使用了动态实例名称,则实例名称将在 variableData 开始,DataBlockOffset 会指定缓冲区的更大偏移量。

  • 驱动程序将 SizeDataBlock 设置为返回的实例数据的字节数。

  • VariableData(实例名称数据之后(如果存在),驱动程序会在输出缓冲区中为请求的实例写入实例数据。

驱动程序读取和写入 WNODE_METHOD_ITEMWNODE_SINGLE_ITEM 结构的方式与 WNODE_SINGLE_INSTANCE大致相同。 这些结构彼此相似,因为每个结构都有 OffsetInstanceNameInstanceIndexDataBlockOffsetSizeDataBlock(或者,WNODE_SINGLE_ITEMSizeDataItem)和 VariableDataWNODE_METHOD_ITEM 包括 MethodIdWNODE_SINGLE_ITEM 包括 ItemIdWNODE_SINGLE_INSTANCE 缺少。

WNODE_ALL_DATA 不同于上述结构,因为它用于传递数据块的多个实例,可能包括动态实例名称以及可能具有不同大小的实例。

下图显示了 IRP 缓冲区的块图,其中包含驱动程序可能返回的 WNODE_ALL_DATA,以响应 IRP_MN_QUERY_ALL_DATA 请求。

图,说明包含 wnode-all-data 的 irp 缓冲区。

从上图顶部开始:

  • 如上图中所述,WNODE_ALL_DATA 开头的 WNODE_HEADER 结构包含在 WnodeHeader 成员中。 WnodeHeader.BuffersizeWnodeHeader.Guid 分别指示数据块 WNODE_ALL_DATA 和 GUID 的大小。

    在此示例中,WMI 将 WnodeHeader.Flags 来指示此结构是 WNODE_ALL_DATA,并且数据块已注册到动态实例名称(即 WMI 清除WNODE_FLAG_STATIC_INSTANCE_NAMES和WNODE_FLAG_PDO_INSTANCE_NAMES)。 在输出中,驱动程序将WNODE_FLAG_FIXED_INSTANCE_SIZE来指示所有实例的大小都相同。

  • WMI DataBlockOffset 来指示缓冲区开头到实例数据的第一个字节的偏移量。 (驱动程序不得更改此值)。 在此示例中,实例数据遵循 OffsetInstanceNameOffsets的实例名称。

  • 驱动程序 InstanceCount 来指示要返回的实例数。

  • 对于使用动态实例名称的数据块,WNODE_XXX 始终包含实例名称字符串。 由于此示例使用动态实例名称,因此 OffsetInstanceNameOffsets 指示缓冲区开头到缓冲区中动态实例名称的偏移量数组的偏移量。

  • FixedInstanceSize 指示驱动程序返回的每个实例中的数据字节数。 如果此数据块的实例的大小不同, 驱动程序将在 WnodeHeader.Flags 中清除WNODE_FLAG_FIXED_INSTANCE_SIZE,并将 OffsetInstanceDataAndLength 设置为 OFFSETINSTANCEDATAANDLENGTH 结构数组,每个结构指定一个实例的数据偏移量以及该实例中的字节数,而不是设置 FixedInstanceSize

有关 WNODE_XXX 结构的详细信息,请参阅 系统结构