Behandeln einer IRP_MN_QUERY_REMOVE_DEVICE-Anforderung
Der PnP-Manager sendet dieses IRP, um die Treiber darüber zu informieren, dass ein Gerät aus der Maschine entfernt werden soll und um zu fragen, ob das Gerät entfernt werden kann, ohne die Maschine zu stören. Sie sendet dieses IRP auch, wenn ein Benutzer anfordert, Treiber für das Gerät zu aktualisieren.
Der PnP-Manager sendet diese IRP an IRQL PASSIVE_LEVEL im Kontext eines System-Threads.
Es führt die folgenden Aktionen aus, bevor es dieses IRP an die Treiber für ein Gerät sendet:
Benachrichtigt alle Benutzermodus-Anwendungen, die sich für Benachrichtigungen auf dem Gerät (oder einem zugehörigen Gerät) registriert haben.
Dazu gehören Anwendungen, die sich für eine Benachrichtigung auf dem Gerät, auf einem der untergeordneten Geräte (untergeordnetes Gerät, untergeordnetes Gerät von untergeordnetem Gerät usw.) oder für eine der Entfernungsbeziehungen des Geräts registriert haben. Eine Anwendung registriert sich für eine solche Benachrichtigung durch den Aufruf von CM_Register_Notification oder RegisterDeviceNotification.
Als Reaktion auf diese Benachrichtigung bereitet sich eine Anwendung entweder auf die Entfernung des Geräts vor (schließt die Handles für das Gerät) oder lässt die Abfrage fehlschlagen. Weitere Informationen zum Umgang mit diesen Benachrichtigungen finden Sie unter Registrierung für die Benachrichtigung über die Verfügbarkeit einer Geräteschnittstelle und das Entfernen eines Geräts.
Benachrichtigt alle Kernel-Mode-Treiber, die sich für das Gerät (oder ein verwandtes Gerät) registriert haben.
Dies schließt Treiber ein, die sich für eine Benachrichtigung auf dem Gerät, auf einem der Nachfolger des Geräts oder auf einer der Entfernungsbeziehungen des Geräts registriert haben. Ein Treiber registriert sich für diese Benachrichtigung durch den Aufruf von IoRegisterPlugPlayNotification mit einer Ereigniskategorie von EventCategoryTargetDeviceChange.
Als Reaktion auf diese Benachrichtigung bereitet sich ein Treiber entweder auf die Entfernung des Geräts vor (schließt die Handles zum Gerät) oder lässt die Abfrage fehlschlagen.
Sendet IRP_MN_QUERY_REMOVE_DEVICE -RPs an die Treiber für die Nachfolger des Geräts. Weitere Informationen darüber, wie ein Gerätestack diese IRP behandelt, finden Sie weiter unten.
(Windows 2000- und höher-Systeme) Wenn ein Dateisystem auf dem Gerät eingebunden ist, sendet der PnP-Manager eine Abfrage zur Entfernung an das Dateisystem und alle Dateisystemfilter. Wenn es offene Handles für das Gerät gibt, lässt das Dateisystem die query-remove-Anfrage normalerweise fehlschlagen. Ist dies nicht der Fall, sperrt das Dateisystem in der Regel das Volume, um zu verhindern, dass zukünftige Erstellungen erfolgreich sind. Wenn ein gemountetes Dateisystem eine query-remove-Anfrage nicht unterstützt, lässt der PnP-Manager die query-remove-Anfrage für das Gerät fehlschlagen.
Wenn alle oben genannten Schritte erfolgreich waren, sendet der PnP-Manager den IRP_MN_QUERY_REMOVE_DEVICE an die Treiber für das Gerät.
Eine IRP_MN_QUERY_REMOVE_DEVICE-Anfrage wird zuerst vom obersten Treiber im Gerätestack und dann von jedem nächst niedrigeren Treiber bearbeitet. Ein Treiber behandelt Entfernen-IRPs in seiner DispatchPnP -Funktion.
Als Antwort auf eine IRP_MN_QUERY_REMOVE_DEVICE muss ein Treiber Folgendes tun:
Ermitteln Sie, ob das Gerät sicher vom Computer entfernt werden kann.
Ein Treiber muss eine query-remove-IRP ablehnen, wenn einer der folgenden Punkte zutrifft:
Wenn das Gerät entfernt wird, können Daten verloren gehen.
Wenn eine Komponente ein offenes Handle für das Gerät hat. (Dies ist nur unter Windows 98/Me ein Problem. Windows 2000 und neuere Versionen von Windows verfolgen offene Handles und lassen die Abfrage fehlschlagen, wenn nach Abschluss der IRP_MN_QUERY_REMOVE_DEVICE noch offene Handles vorhanden sind.)
Wenn ein Treiber benachrichtigt wurde (durch einen IRP_MN_DEVICE_USAGE_NOTIFICATION-IRP), dass sich das Gerät im Pfad für eine Paging-, Crash Dump- oder Hibernation-Datei befindet.
Wenn der Treiber eine ausstehende Schnittstellenreferenz für das Gerät hat. Das heißt, der Treiber hat eine Schnittstelle als Antwort auf eine IRP_MN_QUERY_INTERFACE-Anfrage bereitgestellt und die Schnittstelle wurde nicht dereferenziert.
Wenn das Gerät nicht entfernt werden kann, schlägt die query-remove-IRP fehl.
Legen Sie Irp->IoStatus.Status auf einen geeigneten Fehlerstatus fest (typischerweise STATUS_UNSUCCESSFUL), rufen Sie IoCompleteRequest mit IO_NO_INCREMENT auf und kehren Sie aus der Funktion DispatchPnP des Treibers zurück. Geben Sie den IRP nicht an den nächst niedrigeren Treiber weiter.
Wenn der Treiber zuvor eine IRP_MN_WAIT_WAKE-Anfrage gesendet hat, um das Gerät für wake-up zu aktivieren und den wait-wake-IRP abzubrechen.
Notieren Sie den vorherigen PnP-Zustand des Geräts.
Ein Treiber sollte den PnP-Zustand aufzeichnen, in dem sich das Gerät befand, als der Treiber die IRP_MN_QUERY_REMOVE_DEVICE Anforderung empfangen hat, da der Treiber das Gerät an diesen Zustand zurückgeben muss, wenn die Abfrage abgebrochen wird (IRP_MN_CANCEL_REMOVE_DEVICE). Der vorherige Zustand ist in der Regel "gestartet". Dies ist der Zustand, den das Gerät eingibt, wenn der Treiber eine IRP_MN_START_DEVICE Anforderung erfolgreich abgeschlossen hat.
Es sind jedoch auch andere frühere Zustände möglich. Beispielsweise hat der Benutzer das Gerät über den Geräte-Manager deaktiviert. Oder als Antwort auf eine IRP_MN_QUERY_CAPABILITIES-Anfrage hat der übergeordnete Bustreiber (oder ein Filtertreiber des Bustreibers) möglicherweise gemeldet, dass die Hardware des Geräts deaktiviert ist. In beiden Fällen kann der Treiber für das deaktivierte Gerät eine IRP_MN_QUERY_REMOVE_DEVICE-Anfrage erhalten, bevor er eine IRP_MN_START_DEVICE-Anfrage erhält.
IRP abschließen:
In einer Funktion oder einem Filtertreiber:
Legen Sie Irp->IoStatus.Status auf STATUS_SUCCESS fest.
Richten Sie den nächsten Stack-Speicherort mit IoSkipCurrentIrpStackLocation ein und übergeben Sie die IRP mit IoCallDriver an den nächst niedrigeren Treiber.
Propagieren Sie den Status von IoCallDriver als Rückgabestatus der Funktion DispatchPnP.
IRP nicht abschließen.
In einem Bustreiber:
Legen Sie Irp->IoStatus.Status auf STATUS_SUCCESS fest.
Schließen Sie die IRP (IoCompleteRequest) mit IO_NO_INCREMENT ab.
Kehren Sie von der Funktion DispatchPnP zurück.
Wenn ein Treiber im Gerätestapel eine IRP_MN_QUERY_REMOVE_DEVICE fehlschlägt, sendet der PnP-Manager eine IRP_MN_CANCEL_REMOVE_DEVICE an den Gerätestack. Dadurch wird verhindert, dass Treiber eine IoCompletion-Routine für eine Abfrage-Remove-IRP benötigen, um zu erkennen, ob ein untergeordneter Treiber die IRP nicht bestanden hat.
Sobald ein Treiber eine IRP_MN_QUERY_REMOVE_DEVICE erfolgreich abgeschlossen hat und er das Gerät als im Status remove-pending betrachtet, muss der Treiber alle nachfolgenden Anfragen zum Erstellen des Geräts ablehnen. Der Treiber verarbeitet alle anderen IRPs wie gewohnt, bis der Treiber ein IRP_MN_CANCEL_REMOVE_DEVICE oder ein IRP_MN_REMOVE_DEVICE erhält.