Deklarieren von Funktionen mithilfe von Funktionsrollentypen für WDM-Treiber
Hinweis
Ab Windows 10 Version 2004 erfordert Static Driver Verifier (SDV) keine Anmerkungen mehr, um Rollentypen von Versandroutinen für WDM-Treiber zu identifizieren. Bitte befolgen Sie die Anweisungen im Abschnitt Basic- und Advanced-Initialisierungen auf dieser Seite.
Um SDV über die Einstiegspunkte des Treibers zu informieren, wenn Sie einen WDM-Treiber analysieren, müssen Sie Funktionen mit Hilfe von Funktionsrollentypdeklarationen deklarieren. Die Funktionsrollentypen sind in Wdm.h definiert. Jeder Einstiegspunkt in der Routine DriverEntry in Ihrem WDM-Treiber muss durch Angabe des entsprechenden Rollentyps deklariert werden. Die Rollentypen sind vordefinierte Typendefinitionen, die den erkannten Einstiegspunkten in einem WDM-Treiber entsprechen.
Um z.B. eine Funktionsrollentypdeklaration für die Treiberroutine Unload mit dem Namen CsampUnload zu erstellen, verwenden Sie die vordefinierte Rollentypdeklaration typedef DRIVER_UNLOAD. Die Deklaration des Funktionsrollentyps muss vor der Funktionsdefinition stehen.
DRIVER_UNLOAD CsampUnload;
Die Definition der Funktion CsampUnload bleibt unverändert:
VOID
CsampUnload(
IN PDRIVER_OBJECT DriverObject
)
{
...
}
SDV kennt die in der folgenden Tabelle aufgeführten Arten von Einstiegspunkten.
WDM-Funktion Rollentyp | WDM-Routine |
---|---|
TREIBER_INITIALISIEREN |
|
DRIVER_STARTIO |
|
DRIVER_UNLOAD |
|
DRIVER_ADD_DEVICE |
|
Dispatch_type( Typ ) DRIVER_DISPATCH | Die vom Treiber verwendete(n) Versandroutine(n). Siehe Schreiben von Versandroutinen. |
IO_COMPLETION_ROUTINE |
Die Routine IoCompletion wird durch den Aufruf IoSetCompletionRoutine oder IoSetCompletionRoutineEx und die Übergabe des Funktionszeigers auf die Routine IoCompletion als zweiten Parameter gesetzt. |
ANTRIEB_CANCEL |
Die Abbruchroutine wird durch den Aufruf IoSetCancelRoutine und die Übergabe des Funktionszeigers auf die Abbruchroutine für das IRP als zweiten Parameter an die Funktion gesetzt. |
IO_DPC_ROUTINE |
Die Routine DpcForIsr wird registriert, indem IoInitializeDpcRequest aufgerufen und der Funktionszeiger auf die Routine DpcForIsr als zweiter Parameter übergeben wird. Um den DPC in eine Warteschlange zu stellen, rufen Sie IoQueueDpc von der ISR-Routine aus auf, indem Sie das gleiche DPC-Objekt verwenden. |
KDEFERRED_ROUTINE |
Die CustomDpc Routine wird durch den Aufruf KeInitializeDpc und die Übergabe des Funktionszeigers auf die CustomDpc als zweiten Parameter gesetzt. Um die CustomDpc für den Treiber in eine Warteschlange zu stellen, rufen Sie KeInsertQueueDpc aus der ISR-Routine auf, indem Sie das gleiche DPC-Objekt verwenden. |
KSERVICE_ROUTINE |
Die InterruptService-Routine (ISR) bedient eine Geräteunterbrechung und plant die Verarbeitung der empfangenen Daten nach der Unterbrechung, falls erforderlich. |
LEISTUNG_ANFORDERN_VOLLENDEN |
Die Rückruf-Routine PowerCompletion schließt die Verarbeitung eines Power-IRP ab. Wenn der Treiber zusätzliche Aufgaben ausführen muss, nachdem alle anderen Treiber das IRP abgeschlossen haben, registriert der Treiber eine PowerCompletion Rückruf-Routine während des Aufrufs der PoRequestPowerIrp Routine, die das IRP zuweist. |
WORKER_THREAD_ROUTINE |
Routine Die Routine ist die Rückruf-Routine, die im zweiten Parameter der Funktion ExInitializeWorkItem angegeben ist. Die Routine sollte nur dann auf diese Weise deklariert werden, wenn der Treiber ExQueueWorkItem aufruft, um das Workitem in eine Systemwarteschlange aufzunehmen. |
Fahrerabfertigungsroutinen deklarieren
Ab Windows 10 Version 2004 werden die Funktionsrollentyp-Deklarationen für Versandroutinen automatisch mit ihrer IRP-Kategorie verfeinert, basierend auf der Initialisierung der DriverObject->MajorFunction-Tabelle in der DriverEntry-Routine eines WDM-Treibers.
Um SDV-konform zu sein, muss ein Foo-Treiber Rollendeklarationen entweder in der einfachen oder in der erweiterten Form durchführen.
Grundlegende und erweiterte Initialisierungen
Der grundlegende Stil ist im folgenden Beispiel zu sehen (die Namen der Versandroutinen FooCreate und FooCleanup sind nur Beispiele, es kann jeder geeignete Name verwendet werden):
DriverObject->MajorFunction[IRP_MJ_CREATE] = FooCreate; //Basic style
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCleanup;
Um die Liste zu verkürzen, kann ein fortschrittlicherer Ansatz gewählt werden. Während dieselbe Versandroutine für mehr als eine IRP-Kategorie verwendet wird, kann ein Treiber auf diese Weise zwei Initialisierungen kodieren:
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCreateCleanup; // Advanced style for a multi-role dispatch routine
Damit ein Treiber SDV ordnungsgemäß ausführen kann, darf der Treiber nur entweder den oben gezeigten basic oder advanced Stil verwenden. Die SDV-Überprüfung auf funktioniert nicht wie erwartet, wenn eine dieser beiden Methoden nicht verwendet wird.
Funktionsparameter und Funktionsrollentypen
Wie in der Programmiersprache C vorgeschrieben, müssen die Parametertypen, die Sie in der Funktionsdefinition verwenden, mit den Parametertypen des Funktionsprototyps bzw. in diesem Fall mit dem Funktionsrollentyp übereinstimmen. SDV hängt von den Funktionssignaturen für die Analyse ab und ignoriert Funktionen, deren Signaturen nicht übereinstimmen.
Zum Beispiel sollten Sie eine IoCompletion Routine mit dem Funktionsrollentyp IO_COMPLETION_ROUTINE deklarieren:
IO_COMPLETION_ROUTINE myCompletionRoutine;
Wenn Sie myCompletionRoutine implementieren, müssen die Parametertypen mit denen übereinstimmen, die von IO_COMPLETION_ROUTINE verwendet werden, nämlich PDEVICE_OBJECT, PIRP und PVOID (siehe IoCompletion routine for Syntax).
NTSTATUS
myCompletionRoutine(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
}
Ausführen von Code Analysis for Drivers zur Überprüfung der Funktionsdeklarationen
Um zu ermitteln, ob der Quellcode vorbereitet ist, führen Sie Code Analysis for Drivers aus. Code Analysis for Drivers prüft die Deklarationen von Funktionsrollentypen und kann helfen, Funktionsdeklarationen zu identifizieren, die möglicherweise übersehen wurden, oder Sie zu warnen, wenn die Parameter der Funktionsdefinition nicht mit denen des Funktionsrollentyps übereinstimmen.