Behandeln von IRP_MN_QUERY_POWER für Geräteleistungszustände
Ein IRP für Geräteabfragen fragt eine Zustandsänderung für ein einzelnes Gerät ab und wird an alle Treiber im Stapel für das Gerät gesendet. Ein solcher IRP gibt DevicePowerState im Power.Type-Member des E/A-Stapelspeicherorts an.
Treiber verarbeiten Abfrage-Power-IRPs, während sie den Stapel hinunterfahren.
Ein Funktions- oder Filtertreiber kann eine IRP_MN_QUERY_POWER Anforderung fehlschlagen, wenn eine der folgenden Punkte zutrifft:
Das Gerät ist für die Aktivierung aktiviert, und der angeforderte Energiezustand liegt unterhalb des Zustands, aus dem das Gerät das System reaktivieren kann. Ein Gerät, das das System beispielsweise von D2, aber nicht von D3 reaktivieren kann, schlägt eine Abfrage für D3 fehl, aber eine Abfrage für D2 ist erfolgreich.
Wenn Sie den angeforderten Zustand eingeben, muss der Treiber einen Vorgang abbrechen, bei dem Daten verloren gehen, z. B. eine offene Modemverbindung. Aus diesem Grund schlägt ein Treiber selten einen Fehler bei einer Abfrage aus. In den meisten Fällen verarbeitet die Anwendung solche Fälle.
Um eine IRP_MN_QUERY_POWER Anforderung fehlschlagen zu können, führt ein Treiber die folgenden Schritte aus:
Rufen Sie PoStartNextPowerIrp auf, um anzugeben, dass der Treiber bereit ist, die nächste Energie-IRP zu verarbeiten. (Nur Windows Server 2003, Windows XP und Windows 2000.)
Legen Sie Irp-IoStatus.Status> auf einen Fehler status fest, und rufen Sie IoCompleteRequest auf, und geben Sie IO_NO_INCREMENT an. Der Treiber übergibt den IRP nicht weiter unten im Gerätestapel.
Gibt einen Fehler status aus der DispatchPower-Routine zurück.
Wenn der Treiber die Abfrageleistungs-IRP erfolgreich ist, darf er keine Vorgänge starten oder andere Aktionen ausführen, die den erfolgreichen Abschluss einer nachfolgenden IRP_MN_SET_POWER Anforderung an den abgefragten Energiezustand verhindern würden.
Ein Treiber, der die IRP erfolgreich ist, muss sich auf einen IRP mit festgelegter Leistung für den abgefragten Zustand vorbereiten und die Abfrage-IRP wie folgt übergeben:
Schließen Sie alle ausstehenden E/A-Vorgänge ab.
Eingehende E/A-Anforderungen in die Warteschlange stellen.
Vermeiden Sie es, andere neue Aktivitäten zu starten, die einen Übergang zum angegebenen Energiezustand beeinträchtigen würden. Der Treiber sollte jedoch den Gerätekontext nicht speichern oder andere Schritte zum Herunterfahren unternehmen.
Rufen Sie IoCopyCurrentIrpStackLocationToNext auf, um den IRP-Stapelspeicherort für den nächstniedrigen Treiber festzulegen.
Legen Sie eine IoCompletion-Routine fest. Rufen Sie in der IoCompletion-RoutinePoStartNextPowerIrp (nur Windows Server 2003, Windows XP und Windows 2000) auf, um anzugeben, dass der Treiber bereit ist, die nächste Energie-IRP zu verarbeiten.
Rufen Sie IoCallDriver (in Windows 7 und Windows Vista) oder PoCallDriver (in Windows Server 2003, Windows XP und Windows 2000) auf, um die Abfrage-IRP an den nächstniedrigen Treiber zu übergeben. Schließen Sie die IRP nicht ab.
Gibt STATUS_PENDING zurück. Der Treiber darf den Wert bei Irp-IoStatus.Status> nicht ändern.
Wenn die Abfrageleistungs-IRP den Bustreiber erreicht, ruft der Bustreiber PoStartNextPowerIrp (nur Windows Server 2003, Windows XP und Windows 2000) auf und legt Irp-IoStatus.Status> auf STATUS_SUCCESS fest, wenn der Treiber in den angegebenen Energiezustand wechseln kann oder einen Fehler status festlegt, wenn dies nicht der Fehler ist. Der Bustreiber ruft dann IoCompleteRequest auf und gibt IO_NO_INCREMENT an.
Die Treiber in einem typischen Gerätestapel behandeln eine Geräteabfrage-IRP wie folgt:
Die meisten Filtertreiber sollten den IRP einfach an den nächstniedrigen Treiber übergeben (siehe Übergeben von Power IRPs) und STATUS_PENDING zurückgeben. Einige Filtertreiber müssen jedoch möglicherweise zuerst gerätespezifische Aufgaben ausführen, z. B. das Anstehen eingehender IRPs oder das Speichern des Gerätestromzustands.
Ein Funktionstreiber führt gerätespezifische Aufgaben aus (z. B. das Abschließen ausstehender E/A-Anforderungen, das Anstehen eingehender E/A-Anforderungen, das Speichern des Gerätekontexts oder das Ändern der Geräteleistung), legt eine IoCompletion-Routine fest und übergibt die IRP des Geräts an den nächstniedrigen Treiber (siehe Übergeben von Energie-IRPs). Es gibt STATUS_PENDING aus seiner DispatchPower-Routine zurück.
Der Bustreiber ruft PoStartNextPowerIrp (nur Windows Server 2003, Windows XP und Windows 2000) auf, um die nächste Energie-IRP zu starten. Anschließend wird die IRP abgeschlossen und IO_NO_INCREMENT angegeben. Wenn der Treiber die IRP nicht sofort abschließen kann, ruft er IoMarkIrpPending auf, gibt STATUS_PENDING aus seiner DispatchPower-Routine zurück und schließt die IRP später ab.
Auch wenn sich das Zielgerät bereits im abgefragten Energiezustand befindet, muss jeder Funktions- oder Filtertreiber E/A in die Warteschlange stellen und den IRP an den nächstniedrigen Treiber übergeben. Der IRP muss den gesamten Weg nach unten auf dem Gerätestapel zum Bustreiber fahren, der ihn abschließt.
Bei der Bearbeitung einer IRP_MN_QUERY_POWER Anforderung sollte ein Fahrer so schnell wie möglich von der DispatchPower-Routine zurückkehren. Ein Treiber darf in seiner DispatchPower-Routine nicht auf ein Kernelereignis warten, das durch Code signalisiert wird, der dieselbe IRP verarbeitet. Da Power IRPs im gesamten System synchronisiert werden, kann es zu einem Deadlock kommen.