定义自定义错误类型

驱动程序可以指定自己的错误类型和错误消息。 若要定义自定义错误消息,必须首先定义一个新的 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。

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

SeverityNamesFacilityNames 指令为 NTSTATUS 值的严重性和设施字段定义符号值。 指令的形式为 关键字 (keyword) = () ,其中由名称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 指令为 LCID) (区域设置 ID 定义符号值。 指令的格式为 LanguageNames = () ,其中由一个或多个形式的语句组成=language_namelcidlangfile,用空格分隔。 language_name 参数是用于代替消息文本文件中 lcid 的名称,而文件名指定不带扩展名) 的唯一文件名 (。 当消息编译器从消息文本文件生成资源脚本时,它将此语言的所有字符串资源存储在名为 langfile 的文件中。bin

消息部分

每个消息定义都以自定义 IO_ERR_XXX 值的定义开始,驱动程序使用该值来报告此特定类型的错误。 IO_ERR_XXX 值由一系列关键字 (keyword) = 对定义。 可能的关键字及其含义如下所示。

关键字

MessageId

新 IO_ERR_XXX 值的代码字段。

严重性

新 IO_ERR_XXX 值的严重性字段。 指定的值必须是 SeverityNames 标头指令定义的符号名称之一。

设施

新 IO_ERR_XXX 值的“设施”字段。 指定的值必须是 FacilityNames 标头指令定义的符号名称之一。

SymbolicName

新 IO_ERR_XXX 值的符号名称。 消息编译器生成一个 C 头文件,其中包含名称 的#define 声明作为相应的 NTSTATUS 值。 驱动程序在指定错误类型时使用该名称。

第一个关键字 (keyword) 必须始终为 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 文档。 有关使用生成实用工具生成驱动程序的信息,请参阅 生成驱动程序