定义自定义错误类型

驱动程序可以指定自己的错误类型和错误消息。 若要定义自定义错误消息,必须先定义新的 IO_ERR_XXX 值,以指定为 错误日志条目的 ErrorCode 成员。 事件查看器使用 IO_ERR_XXX 值来查找驱动程序的错误消息。

若要在驱动程序中支持自定义错误消息,请执行以下步骤:

  1. 创建一个消息文本文件,指定自定义IO_ERR_XXX 值和相应的错误消息。 有关详细信息,请参阅 “创建错误消息文本文件”。

  2. 将错误消息文本文件编译到资源,并将资源附加到驱动程序映像。 有关详细信息,请参阅 编译错误消息文本文件

  3. 将驱动程序映像注册为包含错误消息。 有关详细信息,请参阅 “注册为错误消息源”。

创建错误消息文本文件

驱动程序的自定义IO_ERR_XXX 值和匹配错误消息模板的定义作为消息表资源附加到驱动程序映像。 可以在消息文本文件(扩展名为 .mc)中描述驱动程序的消息。

消息文本文件由两个部分组成:标头部分和消息节。 标头节允许声明数值的符号名称,而消息节指定 IO_ERR_XXX 值和匹配的错误消息模板。

有关消息文本文件的示例,请参阅 GitHub 上提供的串行驱动程序示例中的 Serlog.mc 文件

标题部分

标头部分必须包含以下行:

MessageIdTypedef=NTSTATUS

这可确保消息编译器生成的 IO_ERR_XXX 值的类型声明为 NTSTATUS。

标头节中显示的其他指令定义用于代替消息节中的数值的符号值。

SeverityNamesFacilityNames 指令为 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,资源脚本。

  • 消息文本文件中显示的每种语言都有一个文件。 其中每个文件存储一种语言的所有错误消息字符串资源。 每种语言的文件都命名为 langfilebin,其中 langfile 是消息文本文件的 LanguageNames 指令中为语言指定的值。

有关消息编译器的详细信息,请参阅 Microsoft Windows SDK。

资源编译器将资源脚本转换为可以附加到驱动程序映像的资源文件。 如果使用生成实用工具生成驱动程序,则可以确保资源脚本已转换为资源文件并附加到驱动程序映像,只需在驱动程序的 SOURCES 变量中包含资源脚本的名称即可。 有关资源编译器的详细信息,请参阅 Windows SDK 文档。 有关使用生成实用工具生成驱动程序的信息,请参阅 生成驱动程序