Definition von benutzerdefinierten Fehlertypen
Treiber können eigene 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-Element des Fehlerprotokolleintrags angegeben wird. Der Ereignisanzeige verwendet den IO_ERR_XXX-Wert, um die Fehlermeldung des Treibers nachzuschlagen.
Führen Sie die folgenden Schritte aus, um benutzerdefinierte Fehlermeldungen in Ihrem Treiber zu unterstützen:
Erstellen Sie eine Nachrichtentextdatei, die den benutzerdefinierten IO_ERR_XXX-Wert und die entsprechenden Fehlermeldungen angibt. Weitere Informationen finden Sie unter Erstellen der Textdatei für Fehlermeldungen.
Kompilieren Sie die Fehlermeldungstextdatei zu einer Ressource, und fügen Sie die Ressource an das Treiberimage an. Weitere Informationen finden Sie unter Kompilieren der Textdatei für Fehlermeldungen.
Registrieren Sie das Treiberimage als Fehlermeldungen. Weitere Informationen finden Sie unter Registrieren als Quelle von Fehlermeldungen.
Erstellen der Textdatei für Fehlermeldungen
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 Kopfzeilenabschnitt und einem Nachrichtenabschnitt. Der Kopfzeilenabschnitt ermöglicht die Deklaration symbolischer Namen für numerische Werte, während der Nachrichtenabschnitt die IO_ERR_XXX-Werte und übereinstimmende Fehlermeldungsvorlagen angibt.
Ein Beispiel für eine Nachrichtentextdatei finden Sie in der Serlog.mc Datei im Beispiel für serielle Treiber, das auf GitHub verfügbar ist.
Headerabschnitt
Der Kopfzeilenabschnitt muss diese Zeile enthalten:
MessageIdTypedef=NTSTATUS
Dadurch wird sichergestellt, dass der Typ der vom Message Compiler generierten IO_ERR_XXX-Werte als NTSTATUS deklariert wird.
Die anderen Direktiven, die im Kopfzeilenabschnitt angezeigt werden, definieren symbolische Werte, die anstelle numerischer Werte im Nachrichtenabschnitt verwendet werden.
Die Richtlinien "SeverityNames " und "FacilityNames " definieren symbolische Werte für den Schweregrad und die Einrichtung von NTSTATUS-Werten. Die Direktiven sind des Formularschlüsselworts = ( Werte ), wobei Werte aus einer oder mehreren Anweisungen des Formularnamenswerts = bestehen: header_name, getrennt durch Leerzeichen. Der Nameparameter 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 Klausel : header_name ist optional.
Hier ist ein Beispiel für eine Headerdeklaration symbolischer 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 ist das Format LanguageNames = ( Werte ), wobei Werte aus einer oder mehreren Anweisungen des Formulars language_name = lcid : langfile, getrennt durch Leerzeichen bestehen. 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 namens langfile.bin.
Nachrichtenabschnitt
Jede Nachrichtendefinition beginnt mit der Definition des benutzerdefinierten IO_ERR_XXX-Werts , den der Treiber zum Melden dieses bestimmten Fehlertyps verwendet. Der IO_ERR_XXX-Wert wird durch eine Reihe von Schlüsselwortwertpaaren = definiert. Die möglichen Schlüsselwörter und deren Bedeutung sind wie folgt.
Schlüsselwort | Wert |
---|---|
MessageId |
Codefeld des neuen IO_ERR_XXX-Werts . |
Severity |
Schweregradfeld des neuen IO_ERR_XXX-Werts . Der angegebene Wert muss einer der symbolischen Namen sein, die durch die Headerdirektive "SeverityNames " definiert sind. |
Einrichtung |
Facility field of the new IO_ERR_XXX value. Der angegebene Wert muss eine der symbolischen Namen sein, die durch die FacilityNames-Headerdirektive definiert sind. |
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. |
Das erste Schlüsselwort muss immer MessageId sein.
Der Rest der Nachrichtendefinition besteht aus einer oder mehreren lokalisierten Versionen der Fehlermeldung. Jede Version weist das Format auf:
Language=language_name
localized_message
Der language_name Wert, der einer der symbolischen Namen sein muss, die durch die LanguageNames-Headerdirektive definiert werden, 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 vom Ereignisanzeige ersetzt werden, 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 von einem einzelnen Punkt allein in einer Zeile beendet.
Wenn Sie benutzerdefinierte Fehlermeldungen definieren, sollten Sie keine Einfügezeichenfolgen verwenden, es sei denn, sie sind erforderlich. Einfügezeichenfolgen können nicht lokalisiert werden, daher sollten sie für Zeichenfolgen verwendet werden, die sprachunabhängig sind, z. B. Zahlen oder Dateinamen. Die meisten Treiber verwenden keine Einfügezeichenfolgen.
Kompilieren der Textdatei für Fehlermeldungen
Verwenden Sie den Nachrichtencompiler (mc.exe), um die Nachrichtentextdatei in eine Ressourcenskriptdatei zu kompilieren (die über die Dateinamenerweiterung RC verfügt). Ein Befehl des Formulars
mc filename.mc
bewirkt, dass der Nachrichtencompiler die folgenden Dateien generiert:
filename.h, eine Headerdatei, die Deklarationen der einzelnen benutzerdefinierten IO_ERR_XXX-Wert im Dateinamen enthält.mc.
filename.rc, ein Ressourcenskript.
Eine Datei für jede Sprache, die in der Nachrichtentextdatei angezeigt wird. Jede dieser Dateien speichert alle Zeichenfolgenressourcen für Fehlermeldungen für eine Sprache. Die Datei für jede Sprache heißt "langfile".bin, wobei langfile der für die Sprache in der LanguageNames-Direktive der Nachrichtendatei angegebene Wert ist.
Weitere Informationen zum Nachrichtencompiler finden Sie im Microsoft Windows SDK.
Der Ressourcencompiler konvertiert ein Ressourcenskript in eine Ressourcendatei, die Sie an das Treiberimage anfügen können. Wenn Sie das Build-Hilfsprogramm zum Erstellen des Treibers verwenden, können Sie sicherstellen, dass das Ressourcenskript in eine Ressourcendatei konvertiert und dem 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 Windows SDK-Dokumentation. Informationen zur Verwendung des Build-Hilfsprogramms zum Erstellen des Treibers finden Sie unter Erstellen eines Treibers.