定义自定义错误类型
驱动程序可以指定自己的错误类型和错误消息。 若要定义自定义错误消息,必须先定义新的 IO_ERR_XXX 值,以指定为 错误日志条目的 ErrorCode 成员。 事件查看器使用 IO_ERR_XXX 值来查找驱动程序的错误消息。
若要在驱动程序中支持自定义错误消息,请执行以下步骤:
创建一个消息文本文件,指定自定义IO_ERR_XXX 值和相应的错误消息。 有关详细信息,请参阅 “创建错误消息文本文件”。
将错误消息文本文件编译到资源,并将资源附加到驱动程序映像。 有关详细信息,请参阅 编译错误消息文本文件。
将驱动程序映像注册为包含错误消息。 有关详细信息,请参阅 “注册为错误消息源”。
创建错误消息文本文件
驱动程序的自定义IO_ERR_XXX 值和匹配错误消息模板的定义作为消息表资源附加到驱动程序映像。 可以在消息文本文件(扩展名为 .mc)中描述驱动程序的消息。
消息文本文件由两个部分组成:标头部分和消息节。 标头节允许声明数值的符号名称,而消息节指定 IO_ERR_XXX 值和匹配的错误消息模板。
有关消息文本文件的示例,请参阅 GitHub 上提供的串行驱动程序示例中的 Serlog.mc 文件。
标题部分
标头部分必须包含以下行:
MessageIdTypedef=NTSTATUS
这可确保消息编译器生成的 IO_ERR_XXX 值的类型声明为 NTSTATUS。
标头节中显示的其他指令定义用于代替消息节中的数值的符号值。
SeverityNames 和 FacilityNames 指令为 NTSTATUS 值的严重性和设施字段定义符号值。 指令属于 form keyword= (values),其中值由窗体名称=值的一个或多个语句组成:header_name,用空格分隔。 name 参数是在消息文本文件中使用指定数值的名称,而header_name是在消息编译器生成的 C 头文件中声明的此值的名称。 :header_name 子句是可选的。
下面是严重性代码符号名称标头声明的示例:
SeverityNames = (
Success = 0x0:STATUS_SEVERITY_SUCCESS
Informational = 0x1:STATUS_SEVERITY_INFORMATIONAL
Warning = 0x2:STATUS_SEVERITY_WARNING
Error = 0x3:STATUS_SEVERITY_ERROR
)
LanguageNames 指令为区域设置 ID (LCID) 定义符号值。 该指令的格式为 LanguageNames = (values),其中值由窗体的一个或多个语句组成,language_name = lcid : langfile,用空格分隔。 language_name参数是用于代替消息文本文件中的 lcid 的名称,而文件名指定唯一的文件名(没有扩展名)。 当消息编译器从消息文本文件生成资源脚本时,它将此语言的所有字符串资源存储在名为 langfile 的文件中。bin。
消息部分
每个消息定义都以驱动程序用于报告此特定错误类型的自定义 IO_ERR_XXX 值的定义开始。 IO_ERR_XXX 值由一系列关键字 = 值对定义。 可能的关键字及其含义如下所示。
关键字 | 值 |
---|---|
MessageId |
新 IO_ERR_XXX 值的代码字段。 |
严重性 |
新IO_ERR_XXX 值的严重性字段。 指定的值必须是 SeverityNames 标头指令定义的符号名称之一。 |
设施 |
新 IO_ERR_XXX 值的设施字段。 指定的值必须是 FacilityNames 标头指令定义的符号名称之一。 |
SymbolicName |
新 IO_ERR_XXX 值的符号名称。 消息编译器生成一个 C 头文件,该文件包含 名称的 #define 声明作为相应的 NTSTATUS 值。 驱动程序在指定错误类型时使用该名称。 |
第一个关键字必须始终为 MessageId。
消息定义的其余部分由错误消息的一个或多个本地化版本组成。 每个版本都采用以下形式:
Language=language_name
localized_message
language_name值(必须是 LanguageNames 标头指令定义的符号名称之一)指定消息文本的语言。 本地化的消息文本本身由 Unicode 字符串组成。 表单“%n”的任何嵌入字符串都将被视为记录错误时事件查看器将替换的模板。 “%1”字符串替换为驱动程序的设备对象的名称,而“%2”到“%n”将替换为驱动程序提供的任何插入字符串。
消息定义由单行上的单个句点终止。
如果定义自定义错误消息,则除非必要,否则不应使用插入字符串。 插入字符串不能本地化,因此它们应用于与语言无关的字符串,例如数字或文件名。 大多数驱动程序不使用插入字符串。
编译错误消息文本文件
使用消息编译器(mc.exe)将消息文本文件编译为资源脚本文件(扩展名为 .rc)。 窗体的命令
mc filename.mc
导致消息编译器生成以下文件:
filename.h 是一个头文件,其中包含文件名中每个自定义IO_ERR_XXX 值的声明。mc.
filename.rc,资源脚本。
消息文本文件中显示的每种语言都有一个文件。 其中每个文件存储一种语言的所有错误消息字符串资源。 每种语言的文件都命名为 langfile。bin,其中 langfile 是消息文本文件的 LanguageNames 指令中为语言指定的值。
有关消息编译器的详细信息,请参阅 Microsoft Windows SDK。
资源编译器将资源脚本转换为可以附加到驱动程序映像的资源文件。 如果使用生成实用工具生成驱动程序,则可以确保资源脚本已转换为资源文件并附加到驱动程序映像,只需在驱动程序的 SOURCES 变量中包含资源脚本的名称即可。 有关资源编译器的详细信息,请参阅 Windows SDK 文档。 有关使用生成实用工具生成驱动程序的信息,请参阅 生成驱动程序。