Freigeben über


Behandeln einer IRP_MN_QUERY_REMOVE_DEVICE-Anforderung

Der PnP-Manager sendet diese IRP, um Treiber darüber zu informieren, dass ein Gerät vom Computer entfernt werden soll, und um zu fragen, ob das Gerät entfernt werden kann, ohne den Computer zu stören. Außerdem wird diese IRP gesendet, wenn ein Benutzer die Aktualisierung der Treiber für das Gerät anfordert.

Der PnP-Manager sendet diese IRP bei IRQL PASSIVE_LEVEL im Kontext eines Systemthreads.

Vor dem Senden dieses IRP an die Treiber für ein Gerät erfolgt Folgendes:

  • Benachrichtigt alle Anwendungen im Benutzermodus, die sich für Benachrichtigungen auf dem Gerät (oder einem zugehörigen Gerät) registriert haben.

    Dies umfasst Anwendungen, die für Benachrichtigungen auf dem Gerät, auf einem der untergeordneten Geräte (untergeordnetes Gerät, untergeordnetes Gerät des untergeordneten Geräts usw.) oder auf einer der Entfernungsbeziehungen des Geräts registriert wurden. Eine Anwendung registriert sich für diese Benachrichtigung, indem sie RegisterDeviceNotification aufruft.

    Als Reaktion auf diese Benachrichtigung bereitet eine Anwendung entweder die Geräteentfernung vor (schließt Handles für das Gerät) oder schlägt die Abfrage fehl.

  • Benachrichtigt alle Kernelmodustreiber, die sich für Benachrichtigungen auf dem Gerät (oder einem zugehörigen Gerät) registriert haben.

    Dies umfasst Treiber, die für Benachrichtigungen auf dem Gerät, auf einem der untergeordneten Geräte oder in einer der Entfernungsbeziehungen des Geräts registriert wurden. Ein Treiber registriert sich für diese Benachrichtigung, indem er IoRegisterPlugPlayNotification mit der Ereigniskategorie EventCategoryTargetDeviceChange aufruft.

    Als Reaktion auf diese Benachrichtigung bereitet ein Treiber entweder die Geräteentfernung vor (schließt Handles für das Gerät) oder schlägt die Abfrage fehl.

  • Sendet IRP_MN_QUERY_REMOVE_DEVICE IRPs an die Treiber für die untergeordneten Geräte.

  • (Windows 2000 und höhere Systeme) Wenn ein Dateisystem auf dem Gerät eingebunden ist, sendet der PnP-Manager eine Abfrage-Entfernungsanforderung an das Dateisystem und alle Dateisystemfilter. Wenn für das Gerät geöffnete Handles vorhanden sind, schlägt das Dateisystem in der Regel die Abfrage-Entfernungsanforderung fehl. Andernfalls sperrt das Dateisystem das Volume in der Regel, um zu verhindern, dass zukünftige Erstellungen erfolgreich sind. Wenn ein eingebundenes Dateisystem keine Abfrage-Entfernungsanforderung unterstützt, schlägt der PnP-Manager die Abfrage-Entfernungsanforderung für das Gerät fehl.

Wenn alle oben genannten Schritte erfolgreich sind, sendet der PnP-Manager die IRP_MN_QUERY_REMOVE_DEVICE an die Treiber für das Gerät.

Eine IRP_MN_QUERY_REMOVE_DEVICE Anforderung wird zuerst vom obersten Treiber im Gerätestapel und dann von jedem nächstniedrigten Treiber verarbeitet. Ein Treiber verarbeitet das Entfernen von IRPs in seiner DispatchPnP-Routine .

Als Reaktion auf eine IRP_MN_QUERY_REMOVE_DEVICE muss ein Treiber Folgendes tun:

  1. Bestimmen Sie, ob das Gerät vom Computer entfernt werden kann, ohne den Betrieb zu unterbrechen.

    Bei einem Treiber muss ein Abfrage-Entfernen-IRP fehlschlagen, wenn eine der folgenden Punkte zutrifft:

    • Wenn Das Entfernen des Geräts zum Verlust von Daten führen kann.

    • Wenn eine Komponente über ein geöffnetes Handle für das Gerät verfügt. (Dies ist nur unter Windows 98/Me ein Problem. Windows 2000 und höhere Versionen von Windows verfolgen geöffnete Handles nach und schlagen die Abfrage fehl, wenn nach Abschluss der IRP_MN_QUERY_REMOVE_DEVICE geöffnet sind.)

    • Wenn ein Treiber (über eine IRP_MN_DEVICE_USAGE_NOTIFICATION IRP) benachrichtigt wurde, dass sich das Gerät im Pfad für eine Auslagerungs-, Absturzabbild- oder Ruhezustandsdatei befindet.

    • Wenn der Treiber einen hervorragenden Schnittstellenverweis für das Gerät aufweist. Das heißt, der Treiber hat als Reaktion auf eine IRP_MN_QUERY_INTERFACE Anforderung eine Schnittstelle bereitgestellt, und die Schnittstelle wurde nicht abgeleitet.

  2. Wenn das Gerät nicht entfernt werden kann, schlägt das Abfrage-Entfernen-IRP fehl.

    Legen Sie Irp-IoStatus.Status> auf einen entsprechenden Fehler status fest (in der Regel STATUS_UNSUCCESSFUL), rufen Sie IoCompleteRequest mit IO_NO_INCREMENT auf, und kehren Sie von der DispatchPnP-Routine des Treibers zurück. Übergeben Sie den IRP nicht an den nächst niedrigeren Treiber.

  3. Wenn der Treiber zuvor eine IRP_MN_WAIT_WAKE-Anforderung gesendet hat, um das Gerät für die Aktivierung zu aktivieren, brechen Sie die Warte-Reaktivierungs-IRP ab.

  4. 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 in diesen Zustand zurücksenden muss, wenn die Abfrage abgebrochen wird (IRP_MN_CANCEL_REMOVE_DEVICE). Der vorherige Zustand ist in der Regel "gestartet", d. h. der Zustand, den das Gerät erhält, wenn der Treiber eine IRP_MN_START_DEVICE Anforderung erfolgreich abgeschlossen hat.

    Es sind jedoch andere frühere Zustände möglich. Beispielsweise hat der Benutzer das Gerät über Geräte-Manager deaktiviert. Oder als Reaktion auf eine IRP_MN_QUERY_CAPABILITIES Anforderung hat der übergeordnete Bustreiber (oder ein Filtertreiber für den Bustreiber) 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 Anforderung empfangen, bevor es eine IRP_MN_START_DEVICE-Anforderung empfängt.

  5. Beenden Sie die IRP:

    In einer Funktion oder einem Filtertreiber:

    • Legen Sie Irp-IoStatus.Status> auf STATUS_SUCCESS fest.

    • Richten Sie den nächsten Stapelspeicherort mit IoSkipCurrentIrpStackLocation ein, und übergeben Sie den IRP mit IoCallDriver an den nächstniedrigen Treiber.

    • Verteilen Sie die status von IoCallDriver als Rückgabe status aus der DispatchPnP-Routine.

    • Schließen Sie die IRP nicht ab.

    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 DispatchPnP-Routine zurück.

Wenn ein Treiber im Gerätestapel einen IRP_MN_QUERY_REMOVE_DEVICE ausfällt, sendet der PnP-Manager eine IRP_MN_CANCEL_REMOVE_DEVICE an den Gerätestapel. Dadurch wird verhindert, dass Treiber eine IoCompletion-Routine für eine Abfrage entfernen-IRP benötigen, um zu erkennen, ob ein niedrigerer Treiber die IRP nicht erfolgreich war.

Sobald ein Treiber eine IRP_MN_QUERY_REMOVE_DEVICE erfolgreich ist und das Gerät als entfernt ausstehend betrachtet wird, muss der Treiber alle nachfolgenden Erstellungsanforderungen für das Gerät fehlschlagen. Der Treiber verarbeitet alle anderen IRPs wie gewohnt, bis der Treiber eine IRP_MN_CANCEL_REMOVE_DEVICE oder ein IRP_MN_REMOVE_DEVICE erhält.