Freigeben über


Abbrechen eines Warte-/Reaktivierungs-IRP

Nur der Treiber, der eine Warte-/Reaktivierungs-IRP gesendet hat, kann diese IRP abbrechen.

Unter den folgenden Umständen muss ein Treiber möglicherweise eine ausstehende Warte-/Reaktivierungs-IRP abbrechen:

  • Der Treiber empfängt eine PnP-IRP_MN_STOP_DEVICE, IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_REMOVE_DEVICE oder IRP_MN_SURPRISE_REMOVAL Anforderung für das Gerät. Der Treiber sollte die Wait/Wake-IRP (PoRequestPowerIrp) nach dem Neustart des Geräts erneut aufsetzen.

  • Das System wird in den Ruhemodus versetzt, aber das Gerät sollte nicht aktiviert werden, um das System zu reaktivieren.

    Beispielsweise kann der USB-Hubtreiber beim Gerätestart eine IRP_MN_WAIT_WAKE Anforderung senden, falls eines seiner Eingabegeräte später in den Ruhezustand versetzt wird. Während sich das System im Betriebszustand befindet, wird das Gerät durch ein Aktivierungssignal vom Gerät in den Betriebszustand zurück versetzt (hat jedoch keine Auswirkungen auf den Systembetriebszustand). Wenn sich das System auf das Herunterfahren vorbereitet, bricht der USB-Hubtreiber diese IRP ab, wenn das Gerät das System nicht wecken darf.

  • Das System wechselt in einen Ruhezustand, aus dem das Gerät es nicht erwecken kann. Das heißt, es wird ein Zustand mit weniger Leistung als der SystemWake-Wert in seiner DEVICE_CAPABILITIES-Struktur angegeben.

  • Das Gerät wechselt in einen Energiezustand, von dem es nicht auf ein Wecksignal reagieren kann. Das heißt, es wird ein Zustand mit weniger Leistung als der DeviceWake-Wert in seiner DEVICE_CAPABILITIES-Struktur angegeben.

Um eine Warte-/Reaktivierungs-IRP abzubrechen, ruft der Treiber, der die IRP gesendet hat , IoCancelIrp an und übergibt den Zeiger auf die IRP, die zuvor zurückgegeben wurde, als der Treiber PoRequestPowerIrp aufgerufen hat.

Ein Treiber darf einen nicht gesendeten Warte-/Reaktivierungs-IRP nicht abbrechen.

Abbrechen von Routinen für Warte-/Reaktivierungs-IRPs

Viele Funktions- und Bustreiber sollten Abbruchroutinen für ausstehende Warte-/Aktivierungs-IRPs festlegen. Die folgenden Treibertypen müssen solche Routinen festlegen:

  • Treiber, die Geräteeinstellungen ändern, um die Aktivierung zu aktivieren oder zu deaktivieren.

  • Treiber, die IRP_MN_WAIT_WAKE Anforderungen an Treiber übergeordneter Geräte senden.

Eine Cancel-Routine ermöglicht es einem Treiber, die Aktivierung für sein Gerät zu deaktivieren und alle Daten im Zusammenhang mit dem ausstehenden Warte-/Reaktivierungs-IRP zu sauber. Treiber, die Warte-/Reaktivierungs-IRPs für übergeordnete Geräte anfordern, können diese IRPs ebenfalls abbrechen.

In der Warte-/ Reaktivierungsroutine "Abbrechen" sollte ein Treiber die folgenden Schritte ausführen:

  1. Rufen Sie IoSetCancelRoutine auf , um die Cancel-Routine für den IRP auf NULL zurückzusetzen.

  2. Rufen Sie IoReleaseCancelSpinLock auf, und übergeben Sie die in der IRP angegebene CancelIRQL , um die Abbruchdrehsperre für das IRP zu lösen.

  3. Setzen Sie alle relevanten Felder in der Geräteerweiterung zurück. Wenn beispielsweise ein Warte-/Reaktivierungs-IRP aussteht, legen die meisten Treiber ein Flag fest und behalten einen Zeiger auf den IRP in der Geräteerweiterung bei.

    Beachten Sie, dass es für einen Treiber möglich ist, eine Warte-/Reaktivierungs-IRP zu erhalten, während er eine andere solche IRP abbricht. Der Treiber muss überprüfen, ob er bereits über ein IRP unter Spin Lock-Schutz (oder dessen Entsprechung) verfügt. Wenn ja, muss der Treiber seine Handhabung sorgfältig synchronisieren, um sicherzustellen, dass die richtige IRP abgebrochen wird. Weitere Informationen zur Verwendung von Drehsperren in Abbruchroutinen finden Sie unter Abbrechen von IRPs.

  4. Ändern Sie alle erforderlichen Geräteeinstellungen. Beispielsweise würde ein Modemtreiber die Aktivierungseinstellung des Geräts deaktivieren.

  5. Legen Sie Irp-IoStatus.Status> auf STATUS_CANCELLED fest.

  6. Rufen Sie IoCompleteRequest auf, um die Warte-/Reaktivierungs-IRP abzuschließen, und geben Sie IO_NO_INCREMENT an.

  7. Wenn der Treiber zuvor eine zugehörige IRP_MN_WAIT_WAKE für ein übergeordnetes Gerät angefordert hat, sollte der Treiber diese IRP innerhalb seiner Cancel-Routine abbrechen. Der Treiber muss die Abbruch-Spin-Sperre freigeben, bevor er die IRP des übergeordneten Elements abbricht.

    Beispielsweise sollte ein Treiber, der als Bustreiber für ein Gerät fungiert und den Energierichtlinientreiber für sein übergeordnetes Gerät besitzt, eine zugehörige Warte-/Aktivierungs-IRP abbrechen, die er zuvor an sein übergeordnetes Element gesendet hat. Beim Aufrufen von IoCancelIrp wird die Cancel-Routine des übergeordneten Elements aufgerufen, usw. im Gerätestapel.