是否可以自定义 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”, MessageVariablesControlCode 的值。

如果已定义 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_ENABLEDWPP_LEVEL_LOGGER

  • WPP_LEVEL_ENABLED (标志) 确定是否使用指定的标志值启用日志记录。 它返回 TRUEFALSE

  • 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 预处理器