カスタム エラーの種類の定義

ドライバーは、独自のエラーの種類とエラー メッセージを指定できます。 カスタム エラー メッセージを定義するには、まず、新しい IO_ERR_XXX 値を定義して、エラー コード エントリの ErrorCode メンバーとして指定します。 イベント ビューアーは、IO_ERR_XXX 値を使用してドライバーのエラー メッセージを検索します。

ドライバーでカスタム エラー メッセージをサポートするには、次の手順に従います。

  1. カスタム IO_ERR_XXX 値を指定するメッセージ テキスト ファイルと、それに対応するエラー メッセージを作成します。 詳細については、「エラー メッセージ テキスト ファイルの作成」を参照してください。

  2. エラー メッセージ テキスト ファイルをリソースにコンパイルし、ドライバー イメージにリソースをアタッチします。 詳細については、「エラー メッセージ テキスト ファイルのコンパイル」を参照してください。

  3. エラー メッセージを格納したドライバー イメージを登録します。 詳細については、「エラー メッセージのソースとしての登録」を参照してください。

エラー メッセージ テキスト ファイルの作成

ドライバーのカスタム IO_ERR_XXX 値の定義およびそれと一致するエラー メッセージ テンプレートをドライバー イメージにメッセージ テーブル リソースとしてアタッチします。 ドライバーのメッセージは、メッセージ テキスト ファイル (ファイル名拡張子.mc ) で記述できます。

メッセージ テキスト ファイルは、ヘッダー セクションとメッセージ セクションの 2 つのセクションで構成されます。 ヘッダー セクションでは、数値のシンボリック名の宣言を行います。メッセージ セクションでは、IO_ERR_XXX 値とそれに対応するエラー メッセージ テンプレートを指定します。

メッセージ テキスト ファイルの例については、GitHub にあるシリアル ドライバー サンプルの Serlog.mc ファイルを参照してください。

ヘッダー セクション

ヘッダー セクションには、次の行が必要です。

MessageIdTypedef=NTSTATUS

これにより、メッセージ コンパイラによって生成される IO_ERR_XXX 値の種類が NTSTATUS として宣言されます。

ヘッダー セクションに表示されるその他のディレクティブでは、メッセージ セクションで数値の代わりに使用されるシンボリック値を定義します。

SeverityNames ディレクティブと FacilityNames ディレクティブは、NTSTATUS 値の重大度フィールドとファシリティ フィールドのシンボリック値を定義します。 ディレクティブはフォーム keyword= ( values )です。ここで、 values は、空白で区切られたフォーム name = value : header_name の 1 つ以上のステートメントで構成されます。 name パラメーターは、メッセージ テキスト ファイルで数値 (value) の指定に使用する名前です。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 )で、 values は空白で区切られたフォーム language_name = lcid : langfile の 1 つ以上のステートメントで構成されます。 language_name パラメーターは、メッセージ テキスト ファイルの lcid の代わりに使用する名前です。filename は、一意のファイル名 (拡張子なし) を指定します。 メッセージ コンパイラは、メッセージ テキスト ファイルからリソース スクリプトを生成すると、この言語のすべての文字列リソースを langfile.bin という名前のファイルに格納します。

メッセージ セクション

各メッセージ定義では、まず、ドライバーがこの特定の種類のエラーを報告するために使用するカスタム IO_ERR_XXX 値を定義します。 IO_ERR_XXX 値は、一連の keyword = value のペアで定義されます。 使用可能なキーワード (keyword) とその意味は次のとおりです。

キーワード

MessageId

新しい IO_ERR_XXX 値のコード フィールド。

重大度

新しい IO_ERR_XXX 値の重大度フィールド。 指定する値には、SeverityNames ヘッダー ディレクティブで定義されているシンボリック名のいずれかを使用する必要があります。

施設

新しい IO_ERR_XXX 値のファシリティ フィールド。 指定する値には、FacilityNames ヘッダー ディレクティブで定義されているシンボリック名のいずれかを使用する必要があります。

SymbolicName

新しい IO_ERR_XXX 値のシンボリック名。 メッセージ コンパイラは、対応する NTSTATUS 値として名前の #define 宣言を含む C ヘッダー ファイルを生成します。 ドライバーは、エラーの種類を指定するときにその名前を使用します。

最初のキーワードには、常に MessageId を指定します。

メッセージ定義の残りの部分は、1 つ以上のローカライズされたバージョンのエラー メッセージで構成されます。 各バージョンの形式は次のとおりです。

Language=language_name
localized_message

language_name 値は、LanguageNames ヘッダー ディレクティブによって定義されるシンボリック名の 1 つを使用する必要があり、メッセージ テキストの言語を指定します。 ローカライズされたメッセージ テキスト自体は、Unicode 文字列で構成されます。 "%n" という形式の埋め込み文字列は、エラーのログ記録時にイベント ビューアーが置き換えるテンプレートとして処理されます。 "%1" 文字列はドライバーのデバイス オブジェクトの名前に置き換えられ、"%2" から "%n" はドライバーによって提供される挿入文字列に置き換えられます。

メッセージ定義は、1 行に 1 つのピリオドのみを指定でき、そのピリオドによって終了します。

カスタム エラー メッセージを定義する場合は、必要な場合を除き、挿入文字列を使用しないでください。 挿入文字列はローカライズできないため、数値やファイル名など、言語に依存しない文字列にのみ使用します。 ほとんどのドライバーでは、挿入文字列は使用されません。

エラー メッセージ テキスト ファイルのコンパイル

メッセージ コンパイラ (mc.exe) を使用して、メッセージ テキスト ファイルをリソース スクリプト ファイル (ファイル名拡張子 .rc ) にコンパイルします。 コマンドの形式は次のとおりです。

mc filename.mc

このコマンドを実行すると、メッセージ コンパイラによって次のファイルが生成されます。

  • filename.h。filename.mc 内の各カスタム IO_ERR_XXX 値が入ったヘッダー ファイル。

  • filename.rc。リソース スクリプト。

  • メッセージ テキスト ファイルに表示される言語ごとに 1 つのファイル。 これらの各ファイルには、1 つの言語のすべてのエラー メッセージ文字列リソースが格納されます。 各言語のファイル名は、langfile.bin です。langfile は、メッセージ テキスト ファイルの LanguageNames ディレクティブ内の言語に指定されている値です。

メッセージ コンパイラの詳細については、Microsoft Windows SDK を参照してください。

リソース コンパイラは、リソース スクリプトを、ドライバー イメージにアタッチできるリソース ファイルに変換します。 ビルド ユーティリティを使用してドライバーをビルドする場合は、ドライバーの SOURCES 変数にリソース スクリプトの名前を含めるだけで、確実にリソース スクリプトがリソース ファイルに変換され、ドライバー イメージにアタッチされます。 リソース コンパイラの詳細については、Windows SDK のドキュメントを参照してください。 ビルド ユーティリティを使用してドライバーをビルドする方法については、「ドライバーのビルド」を参照してください。