WMI 事件跟踪
本部分介绍 Windows 2000 及更高版本支持的 WDM (WMI 扩展,) 作为信息提供程序的内核模式驱动程序可用于向信息使用者提供信息。 驱动程序通常提供使用者用于确定驱动程序配置和资源使用情况的信息。 除了 WDM 的 WMI 扩展外,用户模式 API 还支持 WMI 事件信息的提供程序或使用者,有关详细信息,请参阅 Windows SDK。
事件跟踪记录器最多支持 32 个实例。 其中一个实例保留用于跟踪内核。 记录器支持跟踪高事件速率。
跟踪事件的定义方式与其他 WMI 事件相同。 MOF 文件中介绍了 WMI 事件。 有关 WMI 事件说明的详细信息,请参阅 WMI 数据和事件块的 MOF 语法。
内核模式驱动程序日志信息集成到现有 WMI 基础结构的过程。 若要记录跟踪事件,驱动程序将执行以下操作:
通过调用 IoWMIRegistrationControl 注册为 WMI 提供程序。
通过在驱动程序向 WMI 注册事件时传递的 WMIREGGUID 结构的 Flags 成员中设置WMIREG_FLAG_TRACED_GUID,将事件标记为可跟踪。
通过在驱动程序向 WMI 注册事件时传递的 WMIREGGUID 结构的 Flags 成员中设置WMIREG_FLAG_TRACE_CONTROL_GUID,将一个事件指定为控制事件,以全面启用/禁用一组跟踪事件。
在收到来自 WMI 的请求以启用 GUID 与跟踪控制 GUID 匹配的事件时,驱动程序应将句柄存储到记录器。 编写事件时需要 值。 有关如何使用此句柄的信息,请参阅步骤 6。 记录器句柄值包含在 WMI 缓冲区的 WNODE_HEADER 部分的 HistoricalContext 成员中,该部分是启用事件请求中的参数的一部分。
确定跟踪事件是发送给 WMI 事件使用者,还是仅针对 WMI 事件记录器。 这将确定 EVENT_TRACE_HEADER 结构的内存应来自何处。 此内存最终将传递到 IoWMIWriteEvent。
如果事件只是日志事件,则内存不会由 WMI 删除。 在这种情况下,驱动程序应传入堆栈上的缓冲区,或者应为此重用分配的缓冲区。 出于性能原因,驱动程序应尽量减少对分配或释放内存的任何不必要的调用。 不遵守此建议将损害日志文件中包含的计时信息的完整性。
如果要将事件同时发送到记录器和 WMI 事件使用者,则必须从非分页池分配内存。 在这种情况下,事件将发送到记录器,然后转发到 WMI,以发送给已请求事件通知的 WMI 事件使用者。 然后,WMI 将根据 IoWMIWriteEvent 的行为释放事件的内存。
保护 EVENT_TRACE_HEADER 的内存和任何驱动程序事件数据(如果有)后,应设置以下信息:
将 Size 成员设置为 size of (EVENT_TRACE_HEADER) 加上将追加到 EVENT_TRACE_HEADER末尾的任何其他驱动程序事件数据的大小。
将 Flags 成员设置为 WNODE_FLAG_TRACED_GUID以将事件发送到记录器。 如果事件也要发送到 WMI 事件使用者,请设置WNODE_FLAG_LOG_WNODE。 请注意,如果设置WNODE_FLAG_LOG_WNODE,则无需设置WNODE_FLAG_TRACED_GUID。 如果两者都已设置,则WNODE_FLAG_TRACED_GUID优先,并且不会将事件发送给 WMI 事件使用者。
设置 Guid 或 GuidPtr 成员。 如果使用 GuidPtr,请在 Flags 成员中设置WNODE_FLAG_USE_GUID_PTR。
(可选)指定 TimeStamp 的值。 如果驱动程序未指定 TimeStamp 值,记录器将填充此值。 如果驱动程序不希望记录器设置时间戳,则应在 Flags 成员中设置WNODE_FLAG_USE_TIMESTAMP。
设置以下任 一EVENT_TRACE_HEADER 对驱动程序具有含义的成员: Class.Type、 Class.Level 和 Class.Version。
最后,将EVENT_TRACE_HEADER强制转换为WNODE_HEADER并将 Wnode 的 HistoricalContext 值设置为在上面的步骤 4 中保存的记录器句柄。
使用指向EVENT_TRACE_HEADER结构的指针调用 IoWMIWriteEvent。
驱动程序应继续记录与控制 GUID 关联的跟踪事件,直到驱动程序收到通过 IRP_MN_DISABLE_EVENTS 请求禁用事件日志记录的通知。