使用 IoWMIWriteEvent 发送事件

驱动程序可以调用 IoWMIWriteEvent 来发送任何事件。 事件可以包含单个项、单个实例或数据块的所有实例,并且可以使用动态实例名称。

与通过查询或更改请求传递 的WNODE_XXX 结构不同,这些结构由 WMI 分配和部分初始化,驱动程序必须分配并初始化包含事件的 WNODE_XXX 结构的所有成员。

只有在 WMI 发送 了启用事件的IRP_MN_ENABLE_EVENTS 请求后,驱动程序才必须发送事件。 然后,当事件发生的触发条件时,驱动程序会:

  1. 从非分页池分配缓冲区,以包含事件所需的 WNODE_XXX 结构,包括变量数据的空间(如果有)。

    根据事件,驱动程序可能会为事件分配 WNODE_SINGLE_ITEMWNODE_SINGLE_INSTANCEWNODE_ALL_DATAWNODE_XXX 加上变量数据的大小不得超过注册表定义的 1K 限制。

  2. 初始化 WNODE_XXX 结构的所有成员,包括 WnodeHeader.Flags

    • 驱动程序设置 WNODE_FLAG_EVENT_ITEM 标志以指示结构是事件。

    • 驱动程序设置以下标志之一来指示 WNODE_XXX 结构的类型:

      WNODE_FLAG_ALL_DATA

      WNODE_FLAG_SINGLE_INSTANCE

      WNODE_FLAG_SINGLE_ITEM

    • 驱动程序设置或清除以下标志,以指示块是使用静态实例名称还是动态实例名称:

      WNODE_FLAG_STATIC_INSTANCE_NAMES

      WNODE_FLAG_PDO_INSTANCE_NAMES

    • 驱动程序可能会根据事件设置其他标志。

  3. 将指向 WNODE_XXX 的指针强制转换为PWNODE_EVENT_ITEM。

  4. 使用 指针调用 IoWMIWriteEvent

    如果 IoWMIWriteEvent 成功完成,WMI 会释放事件驱动程序分配的内存。

IoWMIWriteEvent 返回后,驱动程序将继续监视事件的触发条件,并在每次触发条件发生时发送事件,直到 WMI 发送IRP_MN_DISABLE_EVENTS请求来禁用该事件。

如果事件的大小超过注册表定义的最大值 1K (不建议) 驱动程序应使用初始化WNODE_EVENT_REFERENCE调用 IoWmiWriteEvent ,该初始化 WNODE_EVENT_REFERENCE 指定事件的 GUID、大小以及静态实例名称的实例索引 (,) 或动态实例名称的名称 () 。 WMI 将使用 WNODE_EVENT_REFERENCE 中的信息来查询事件。

驱动程序可以通过调用 WMI 库例程 WmiFireEvent 发送不使用动态实例名称且包含单个实例的事件。 驱动程序不需要为 WmiFireEvent 调用分配和初始化 WNODE_XXX 结构。 WMI 将驱动程序的事件数据打包在 WNODE_SINGLE_INSTANCE 中,并将其传递给数据使用者。 有关使用 WmiFireEvent 发送事件的详细信息,请参阅 使用 WmiFireEvent 发送事件