是否可以自定义 DoTraceMessage?
是的,可以编写自己的 DoTraceMessage 宏版本。 DoTraceMessage 生成跟踪消息。
TraceDrv 示例驱动程序提供了本主题中所述的方法示例。 GitHub 上的 Windows 驱动程序示例存储库中提供了 TraceDrv。
DoTraceMessage:默认版本
默认情况下,DoTraceMessage 宏采用以下格式:
DoTraceMessage(Flag,"Message",MessageVariables...);
在此默认版本中, Flag 表示 跟踪标志,即生成消息的条件。 MessageVariables 包含驱动程序定义并在跟踪消息中显示的以逗号分隔的变量列表。 MessageVariables 变量是使用 printf 元素格式化的。 WPP 预处理器从 DoTraceMessage 宏创建编译器指令。 此宏将消息定义信息和格式设置信息添加到为 跟踪提供程序生成的 PDB 文件,例如内核模式驱动程序或用户模式应用程序。
DoTraceMessage 宏在逻辑上扩展为以下内容:
PRE macro // If defined
If (WPP_CHECK_INIT && Flag is enabled) {
....Call WmiTraceMessage;
}
POST macro // If defined
请考虑以下代码示例。
DoTraceMessage(ERROR, "IOCTL = %d", ControlCode);
启用 ERROR 标志时,此调用将生成跟踪消息。 消息为“IOCTL=%d”, MessageVariables 是 ControlCode 的值。
如果已定义 PRE-logging 和 POST 日志记录宏,它们也将展开。 Microsoft Windows 2000 及更高版本的操作系统支持 PRE 宏和 POST 宏。 若要使用这些宏,必须使用 WDK 生成驱动程序。 如果使用早期版本的 Windows 驱动程序开发工具包 (DDK) 生成驱动程序,则 PRE 和 POST 功能不可用,并且宏不会作为跟踪语句的一部分运行。 使用早期版本的 Windows DDK 生成驱动程序可能不会导致生成中断,但代码无法按预期工作。
DoTraceMessage:常规格式
下面是有效跟踪消息函数的常规格式:
FunctionName(Conditions...,"Message",MessageVariables...);
在消息之前显示的参数将被解释为条件。 消息后显示的参数将被解释为消息变量。
条件 是一个以逗号分隔的值列表。 仅当所有条件都为 true 时,才会生成跟踪消息。 可以指定代码中支持的任何条件。
示例:MyTrace
下面是跟踪函数的示例。 此示例为生成跟踪消息的提供程序的跟踪级别和子组件添加条件。
MyDoTrace(Level, Flag, Subcomponent,"Message",MessageVariables...);
例如:
MyDoTrace(TRACE_LEVEL_ERROR, VERBOSE, Network,"IOCTL = %d", ControlCode);
跟踪级别是在 Evntrace.h 中定义的标准级别,Evntrace.h 是 WDK 的 Include 子目录中的公共头文件。
#define TRACE_LEVEL_NONE 0 // Tracing is not on
#define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination
#define TRACE_LEVEL_ERROR 2 // Severe errors that need logging
#define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure
#define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases(for example, Entry-Exit)
#define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps
#define TRACE_LEVEL_RESERVED6 6
#define TRACE_LEVEL_RESERVED7 7
#define TRACE_LEVEL_RESERVED8 8
#define TRACE_LEVEL_RESERVED9 9
如何创建自定义跟踪函数
若要创建自定义跟踪函数,请执行以下步骤:
编写支持 DoTraceMessage 宏的宏的替代版本。
将 -func 参数添加到调用 WPP 预处理器的 RUN_WPP 语句。
编写自定义宏
若要创建自定义跟踪函数来更改跟踪消息的条件 (出现在消息) 之前的参数,必须编写支持跟踪函数的宏的替代版本, WPP_LEVEL_ENABLED 和 WPP_LEVEL_LOGGER。
WPP_LEVEL_ENABLED (标志) 确定是否使用指定的标志值启用日志记录。 它返回 TRUE 或 FALSE。
WPP_LEVEL_LOGGER (标志) 查找启用提供程序的跟踪会话,并返回跟踪会话的句柄。
例如,如果要包含跟踪级别,除了标志之外,还需定义一个包含跟踪级别的新WPP_LEVEL_ENABLED宏。 可以将新宏的定义基于默认宏,如以下代码示例所示。
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >=lvl
通常,WPP_LEVEL_LOGGER宏不受影响。 在这些情况下,可以将新宏定义为默认宏。 例如:
#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)
但是,在某些情况下,需要更改 LOGGER 宏。 例如,你可能想要编写一个仅依赖于跟踪级别而不依赖于标志的跟踪函数。
在下面的代码示例中,宏中的标志值将替换为虚拟值。 声明控件 GUID 定义时未定义任何标志。
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID(CtlGuid,(a044090f,3d9d,48cf,b7ee,9fb114702dc1), \
WPP_DEFINE_BIT(DUMMY))
#define WPP_LEVEL_LOGGER(lvl) (WPP_CONTROL(WPP_BIT_ ## DUMMY).Logger)
将函数添加到 WPP
若要将自定义跟踪函数添加到 WPP,请将 -func 参数添加到带有函数声明的 RUN_WPP 语句,如以下代码示例所示。
RUN_WPP=$(SOURCES) -km -func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...)
注意 不得在用户模式应用程序或动态链接库的 RUN_WPP 指令中指定 -km 开关, (DLL) 。
有关RUN_WPP的可选参数的完整列表,请参阅 WPP 预处理器。