Deklarieren von Funktionen mithilfe von Funktionsrollentypen für WDM-Treiber

Hinweis

Ab Windows 10 Version 2004 sind für die statische Treiberüberprüfung (Static Driver Verifier, SDV) keine Anmerkungen mehr erforderlich, um Rollentypen von Verteilungsroutinen für WDM-Treiber zu identifizieren. Befolgen Sie die Anleitung im Abschnitt Grundlegende und erweiterte Initialisierungen auf dieser Seite.

Um SDV über die Einstiegspunkte des Treibers zu informieren, wenn Sie einen WDM-Treiber analysieren, müssen Sie Funktionen mithilfe von Funktionsrollentypdeklarationen deklarieren. Die Funktionsrollentypen sind in Wdm.h definiert. Jeder Einstiegspunkt in der DriverEntry-Routine in Ihrem WDM-Treiber muss durch Angabe des entsprechenden Rollentyps deklariert werden. Bei den Rollentypen handelt es sich um vordefinierte Typdefinitionen, die den erkannten Einstiegspunkten in einem WDM-Treiber entsprechen.

Um beispielsweise eine Funktionsrollentypdeklaration für die Unload-Routine eines Treibers namens CsampUnload zu erstellen, verwenden Sie die vordefinierte Typdefinition DRIVER_UNLOAD Rollentypdeklaration. Die Funktionsrollentypdeklaration muss vor der Funktionsdefinition angezeigt werden.

DRIVER_UNLOAD CsampUnload;

Die Definition der CsampUnload-Funktion bleibt unverändert:

VOID
CsampUnload(
    IN PDRIVER_OBJECT DriverObject
    )
{
    ...
}

SDV erkennt die Typen von Einstiegspunkten, die in der folgenden Tabelle dargestellt sind.

WDM-Funktionsrollentyp WDM-Routine

DRIVER_INITIALIZE

DriverEntry

DRIVER_STARTIO

StartIO

DRIVER_UNLOAD

Entladen

DRIVER_ADD_DEVICE

AddDevice

Dispatch_type(type) DRIVER_DISPATCH

Die vom Treiber verwendete(n) Dispatch-Routine(en). Weitere Informationen finden Sie unter Schreiben von Dispatch-Routinen.

IO_COMPLETION_ROUTINE

IoCompletion

Die IoCompletion-Routine wird festgelegt, indem IoSetCompletionRoutine oder IoSetCompletionRoutineEx aufgerufen und der Funktionszeiger an die IoCompletion-Routine als zweiter Parameter übergeben wird.

DRIVER_CANCEL

Abbrechen

Die Cancel-Routine wird festgelegt, indem IoSetCancelRoutine aufgerufen und der Funktionszeiger an die Abbruchroutine für das IRP als zweiter Parameter an die Funktion übergeben wird.

IO_DPC_ROUTINE

DpcForIsr

Die DpcForIsr-Routine wird registriert, indem IoInitializeDpcRequest aufgerufen und der Funktionszeiger an die DpcForIsr-Routine als zweiter Parameter übergeben wird. Um den DPC in die Warteschlange zu stellen, rufen Sie IoQueueDpc aus der ISR-Routine auf, indem Sie dasselbe DPC-Objekt verwenden.

KDEFERRED_ROUTINE

CustomDpc

Die CustomDpc-Routine wird festgelegt, indem KeInitializeDpc aufgerufen und der Funktionszeiger an customDpc als zweiter Parameter übergeben wird. Um den CustomDpc für den Treiber in die Warteschlange zu stellen, rufen Sie KeInsertQueueDpc über die ISR-Routine auf, indem Sie dasselbe DPC-Objekt verwenden.

KSERVICE_ROUTINE

InterruptService

Die InterruptService-Routine (ISR) verwendet einen Geräte-Interrupt und plant bei Bedarf die Verarbeitung empfangener Daten nach dem Interrupt.

REQUEST_POWER_COMPLETE

Die PowerCompletion-Rückrufroutine schließt die Verarbeitung eines Power-IRP ab. Wenn der Treiber zusätzliche Aufgaben ausführen muss, nachdem alle anderen Treiber die IRP abgeschlossen haben, registriert der Treiber eine PowerCompletion-Rückrufroutine während des Aufrufs der PoRequestPowerIrp-Routine , die den IRP zuordnet.

WORKER_THREAD_ROUTINE

Routine

Routine ist die Rückrufroutine, die im zweiten Parameter für die ExInitializeWorkItem-Funktion angegeben wird.

Die Routine sollte nur so deklariert werden, wenn der Treiber ExQueueWorkItem aufruft, um das Arbeitselement einer Systemwarteschlange hinzuzufügen.

Deklarieren von Treiberverteilungsroutinen

Ab Windows 10 Version 2004 werden die Funktionsrollentypdeklarationen für Dispatchroutinen basierend auf der Initialisierung der DriverObject-MajorFunction-Tabelle in der DriverEntry-Routine eines WDM-Treibers automatisch mit ihrer IRP-Kategorie> verfeinert.

Ein Treiber foo muss Rollendeklarationen entweder mithilfe des einfachen oder erweiterten Deklarationsstils ausführen, um mit SDV kompatibel zu sein.

Grundlegende und erweiterte Initialisierungen

Der grundlegende Stil ist im folgenden Beispiel zu sehen (beachten Sie, dass die Dispatch-Routinenamen FooCreate und FooCleanup nur Beispiele sind, wobei jeder geeignete Name verwendet werden kann):

DriverObject->MajorFunction[IRP_MJ_CREATE] = FooCreate; //Basic style
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCleanup;

Es kann ein erweiterter Ansatz verwendet werden, um die erforderliche Liste zu verkürzen. Während dieselbe Dispatchroutine für mehr als eine IRP-Kategorie verwendet wird, kann ein Treiber zwei Initialisierungen auf diese Weise codieren:

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 den oben gezeigten einfachen oder erweiterten Stil verwenden. Die SDV-Verficiation auf dem Treiber funktioniert nicht wie erwartet , wenn eine dieser beiden Methoden nicht verwendet wird.

Funktionsparameter und Funktionsrollentypen

Wie in der Programmiersprache C erforderlich, müssen die Parametertypen, die Sie in der Funktionsdefinition verwenden, mit den Parametertypen des Funktionsprototyps oder 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.

Sie sollten beispielsweise eine IoCompletion-Routine mit dem IO_COMPLETION_ROUTINE Funktionsrollentyp 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 zur Syntax).

NTSTATUS
myCompletionRoutine(
 PDEVICE_OBJECT  DeviceObject,
 PIRP  Irp,
 PVOID  Context
 )
{
}

Ausführen der Codeanalyse für Treiber zum Überprüfen der Funktionsdeklarationen

Führen Sie die Codeanalyse für Treiber aus, um festzustellen, ob der Quellcode vorbereitet ist. Die Codeanalyse für Treiber überprüft auf Funktionsrollentypdeklarationen und kann dazu beitragen, Funktionsdeklarationen zu identifizieren, die möglicherweise übersehen wurden oder Sie warnen, wenn die Parameter der Funktionsdefinition nicht mit denen im Funktionsrollentyp übereinstimmen.