Share via


Definieren benutzerdefinierter Fehlertypen

Treiber können ihre eigenen Fehlertypen und Fehlermeldungen angeben. Um eine benutzerdefinierte Fehlermeldung zu definieren, müssen Sie zunächst einen neuen IO_ERR_XXX-Wert definieren, der als ErrorCode-Member des Fehlerprotokolleintrags angegeben werden soll. Der Ereignisanzeige verwendet den wert IO_ERR_XXX, um die Fehlermeldung des Treibers nachzuschlagen.

Führen Sie die folgenden Schritte aus, um benutzerdefinierte Fehlermeldungen in Ihrem Treiber zu unterstützen:

  1. Erstellen Sie eine Nachrichtentextdatei, die den benutzerdefinierten IO_ERR_XXX-Wert und die entsprechenden Fehlermeldungen angibt. Weitere Informationen finden Sie unter Erstellen der Fehlermeldungstextdatei.

  2. Kompilieren Sie die Fehlermeldungstextdatei in eine Ressource, und fügen Sie die Ressource an das Treiberimage an. Weitere Informationen finden Sie unter Kompilieren der Fehlermeldungstextdatei.

  3. Registrieren Sie das Treiberimage als Fehlermeldungen. Weitere Informationen finden Sie unter Registrieren als Quelle von Fehlermeldungen.

Erstellen der Fehlermeldungstextdatei

Die Definition der benutzerdefinierten IO_ERR_XXX-Werte eines Treibers und übereinstimmende Fehlermeldungsvorlagen werden als Nachrichtentabellenressource an das Treiberimage angefügt. Sie können die Nachrichten für einen Treiber in einer Nachrichtentextdatei (mit der Dateinamenerweiterung .mc) beschreiben.

Eine Nachrichtentextdatei besteht aus zwei Abschnitten: einem Headerabschnitt und einem Nachrichtenabschnitt. Der Headerabschnitt lässt die Deklaration symbolischer Namen für numerische Werte zu, während der Nachrichtenabschnitt die IO_ERR_XXX-Werte und übereinstimmende Fehlermeldungsvorlagen angibt.

Ein Beispiel für eine Nachrichtentextdatei finden Sie in der datei Serlog.mc im Beispiel für serielle Treiber , das auf GitHub verfügbar ist.

Headerabschnitt

Der Headerabschnitt muss die folgende Zeile enthalten:

MessageIdTypedef=NTSTATUS

Dadurch wird sichergestellt, dass der Typ der vom Nachrichtencompiler generierten IO_ERR_XXX-Werte als NTSTATUS deklariert wird.

Die anderen Anweisungen, die im Headerabschnitt angezeigt werden, definieren symbolische Werte, die anstelle numerischer Werte im Nachrichtenabschnitt verwendet werden.

Die Anweisungen SeverityNames und FacilityNames definieren symbolische Werte für die Schweregrad- und Facilityfelder von NTSTATUS-Werten. Die Direktiven haben die Form Schlüsselwort (keyword)= (Werte), wobei Werte aus einer oder mehreren Anweisungen des Formularnamens=value:header_name bestehen, getrennt durch Leerzeichen. Der name-Parameter ist der Name, den Sie verwenden, um den numerischen Wert in der Nachrichtentextdatei anzugeben, während der header_name der Name für diesen Wert ist, der in der vom Nachrichtencompiler generierten C-Headerdatei deklariert ist. Die :header_name-Klausel ist optional.

Hier sehen Sie ein Beispiel für eine Headerdeklaration mit symbolischen Namen für Schweregradcodes:

SeverityNames = (
  Success       = 0x0:STATUS_SEVERITY_SUCCESS
  Informational = 0x1:STATUS_SEVERITY_INFORMATIONAL
  Warning       = 0x2:STATUS_SEVERITY_WARNING
  Error         = 0x3:STATUS_SEVERITY_ERROR
)

Die LanguageNames-Direktive definiert symbolische Werte für Gebietsschema-IDs (LCID). Die -Direktive hat das Format LanguageNames = (values), wobei Werte aus einer oder mehreren Anweisungen der Form language_name=lcid:langfile bestehen, getrennt durch Leerzeichen. Der parameter language_name ist der Name, den Sie anstelle von lcid in der Nachrichtentextdatei verwenden, während der Dateiname einen eindeutigen Dateinamen (ohne Erweiterung) angibt. Wenn der Nachrichtencompiler das Ressourcenskript aus der Nachrichtentextdatei generiert, speichert er alle Zeichenfolgenressourcen für diese Sprache in einer Datei mit dem Namen langfile. bin.

Nachrichtenabschnitt

Jede Nachrichtendefinition beginnt mit der Definition des benutzerdefinierten IO_ERR_XXX-Werts , den der Treiber verwendet, um diesen bestimmten Fehlertyp zu melden. Der IO_ERR_XXX-Wert wird durch eine Reihe von Schlüsselwort (keyword) = Wertpaaren definiert. Die möglichen Schlüsselwörter und ihre Bedeutung sind wie folgt.

Schlüsselwort Wert

MessageId

Codefeld des neuen IO_ERR_XXX-Werts .

Schweregrad

Schweregradfeld des neuen werts IO_ERR_XXX . Der angegebene Wert muss einer der symbolischen Namen sein, die von der Headerdirektive SeverityNames definiert werden.

Facility

Facility-Feld des neuen IO_ERR_XXX-Werts . Der angegebene Wert muss einer der symbolischen Namen sein, die von der FacilityNames-Header-Direktive definiert werden.

SymbolicName

Der symbolische Name für den neuen IO_ERR_XXX-Wert . Der Nachrichtencompiler generiert eine C-Headerdatei, die eine #define Deklaration des Namens als entsprechenden NTSTATUS-Wert enthält. Der Treiber verwendet diesen Namen, wenn er den Fehlertyp angibt.

Der erste Schlüsselwort (keyword) muss immer MessageId sein.

Der Rest der Nachrichtendefinition besteht aus mindestens einer lokalisierten Version der Fehlermeldung. Jede Version hat folgendes Format:

Language=language_name
localized_message

Der language_name-Wert , der einer der symbolischen Namen sein muss, die von der LanguageNames-Headerdirektive definiert werden müssen, gibt die Sprache des Nachrichtentexts an. Der lokalisierte Nachrichtentext selbst besteht aus einer Unicode-Zeichenfolge. Alle eingebetteten Zeichenfolgen des Formulars "%n" werden als Vorlagen behandelt, die der Ereignisanzeige ersetzt, wenn der Fehler protokolliert wird. Die Zeichenfolge "%1" wird durch den Namen des Geräteobjekts des Treibers ersetzt, während "%2" bis "%n" durch alle vom Treiber bereitgestellten Einfügezeichenfolgen ersetzt werden.

Die Nachrichtendefinition wird durch einen einzelnen Punkt allein in einer Zeile beendet.

Wenn Sie benutzerdefinierte Fehlermeldungen definieren, sollten Sie keine Einfügezeichenfolgen verwenden, es sei denn, dies ist erforderlich. Einfügezeichenfolgen können nicht lokalisiert werden, daher sollten sie für sprachunabhängige Zeichenfolgen wie Zahlen oder Dateinamen verwendet werden. Die meisten Treiber verwenden keine Einfügezeichenfolgen.

Kompilieren der Fehlermeldungstextdatei

Verwenden Sie den Nachrichtencompiler (mc.exe), um Ihre Nachrichtentextdatei in eine Ressourcenskriptdatei zu kompilieren (mit der Dateinamenerweiterung .rc). Ein Befehl des Formulars

mc filename.mc

bewirkt, dass der Nachrichtencompiler die folgenden Dateien generiert:

  • filename.h, eine Headerdatei, die Deklarationen jedes benutzerdefinierten IO_ERR_XXX-Werts in Dateiname enthält. mc.

  • filename.rc, ein Ressourcenskript.

  • Eine Datei für jede Sprache, die in der Nachrichtentextdatei angezeigt wird. Jede dieser Dateien speichert alle Fehlerzeichenfolgenressourcen für eine Sprache. Die Datei für jede Sprache heißt langfile. bin, wobei langfile der Wert ist, der für die Sprache in der LanguageNames-Direktive der Nachrichtentextdatei angegeben wird.

Weitere Informationen zum Nachrichtencompiler finden Sie im Microsoft Windows SDK.

Der Ressourcencompiler konvertiert ein Ressourcenskript in eine Ressourcendatei, die Sie ihrem Treiberimage anfügen können. Wenn Sie das Hilfsprogramm Build zum Erstellen Ihres Treibers verwenden, können Sie sicherstellen, dass das Ressourcenskript in eine Ressourcendatei konvertiert und ihrem Treiberimage angefügt wird, indem Sie einfach den Namen des Ressourcenskripts in die SOURCES-Variable für den Treiber einschließen. Weitere Informationen zum Ressourcencompiler finden Sie in der Dokumentation zum Windows SDK. Informationen zur Verwendung des Hilfsprogramms Build zum Erstellen Ihres Treibers finden Sie unter Erstellen eines Treibers.