Übergeben von PnP-IRPs im Gerätestapel

Der PnP-Manager verwendet IRPs, um Treiber zum Starten, Beenden und Entfernen von Geräten und zum Abfragen von Treibern zu ihren Geräten anweisen. Alle PnP-IRPs verfügen über den Hauptfunktionscode IRP_MJ_PNP, und alle PnP-Treiber müssen eine DispatchPnP-Routine bereitstellen, um diesen Funktionscode zu bedienen. Der PnP-Manager initialisiert Irp-IoStatus.Status> auf STATUS_NOT_SUPPORTED, wenn er eine IRP sendet. Weitere Informationen finden Sie unter DispatchPnP-Routinen.

Eine Liste der PnP-Neben-IRPs finden Sie unter Plug & Play Neben-IRPs.

Alle Treiber für ein Gerät müssen die Möglichkeit haben, auf eine PnP-IRP zu reagieren, es sei denn, ein Treiber im Stapel schlägt die IRP aus. (Siehe folgende Abbildung.)

Diagramm, das das Übergeben eines Plug-and-Play-Irpings des Gerätestapels veranschaulicht.

Kein einzelner Treiber für ein Gerät kann davon ausgehen, dass es der einzige Treiber ist, der auf eine PnP-IRP reagiert. Betrachten Sie beispielsweise einen Funktionstreiber, der auf eine IRP_MN_QUERY_CAPABILITIES-Anforderung antwortet und die IRP abschließt, ohne sie an den nächstniedrigen Treiber zu übergeben. Keine der Funktionen, die von niedrigeren Treibern unterstützt werden, z. B. eine eindeutige instance-ID oder Energieverwaltungsfunktionen, die vom übergeordneten Bustreiber unterstützt werden, wird gemeldet.

Ein PnP-IRP fährt den Gerätestapel zurück, wenn der übergeordnete Bustreiber IoCompleteRequest aufruft und der E/A-Manager alle vom Funktionstreiber oder Filtertreiber registrierten IoCompletion-Routinen aufruft.

Ein Funktions- oder Filtertreiber muss folgendes tun, wenn er einen PnP-IRP empfängt:

  • Wenn der Treiber Als Reaktion auf die IRP Aktionen ausführt:
    1. Führen Sie die entsprechenden Aktionen aus.
    2. Legen Sie Irp-IoStatus.Status> auf einen entsprechenden status fest, z. B. STATUS_SUCCESS. Legen Sie Irp-IoStatus.Information> fest, falls für die IRP geeignet.
    3. Richten Sie den nächsten Stapelspeicherort mit IoSkipCurrentIrpStackLocation oder IoCopyCurrentIrpStackLocationToNext ein. Rufen Sie letztere Routine auf, wenn Sie eine IoCompletion-Routine festlegen.
    4. Legen Sie bei Bedarf eine IoCompletion-Routine fest.
    5. Schließen Sie die IRP nicht ab. (Rufen Sie IoCompleteRequest nicht auf.) Der übergeordnete Bustreiber schließt die IRP ab.
  • Wenn der Treiber keine Aktionen für diese IRP ausführt, bereitet er einfach die Übergabe des IRP an den nächsten Treiber vor:
    1. Rufen Sie IoSkipCurrentIrpStackLocation auf, um den Stapelspeicherort aus dem IRP zu entfernen.
    2. Legen Sie keine Felder in Irp-IoStatus> fest.
    3. Legen Sie keine IoCompletion-Routine fest.
    4. Schließen Sie die IRP nicht ab. (Rufen Sie IoCompleteRequest nicht auf.) Der übergeordnete Bustreiber schließt die IRP ab.

Wenn bei einem Funktions- oder Filtertreiber der IRP kein Fehler aufgetreten ist, wird der IRP mit IoCallDriver an den nächstniedrigen Treiber übergeben. Ein Treiber verfügt über einen Zeiger auf den nächstniedrigen Treiber. dieser Zeiger vom IoAttachDeviceToDeviceStack-Aufruf in der AddDevice-Routine des höheren Treibers zurückgegeben wurde.

Der übergeordnete Bustreiber schließt die IRP ab, nachdem er aufgaben ausgeführt hat, um auf die IRP zu reagieren. Nachdem der Bustreiber IoCompleteRequest aufgerufen hat, ruft der E/A-Manager alle IoCompletion-Routinen auf, die von der Funktion oder den Filtertreibern für das Gerät registriert wurden.