Freigeben über


Entfernen eines Geräts in einem Funktionstreiber

Beim Entfernen eines Geräts muss ein Funktionstreiber alle Vorgänge rückgängig machen, die er zum Hinzufügen und Starten des Geräts ausgeführt hat. Diese Diskussion umfasst Funktionstreiber für Peripheriegeräte und Funktionstreiber für Busgeräte.

Ein Funktionstreiber entfernt ein Gerät mithilfe einer Prozedur wie der folgenden in seiner DispatchPnP-Routine :

  1. Ist dies ein Funktionstreiber für ein Busgerät?

    Wenn dies der Fall ist, löschen Sie möglicherweise alle ausstehenden untergeordneten PDOs für Geräte im Bus.

    Wenn der Bustreiber eine vorherige IRP_MN_SURPRISE_REMOVAL-Anforderung für das untergeordnete Gerät verarbeitet hat, aber der Treiber die nachfolgende IRP_MN_REMOVE_DEVICE-Anforderung noch nicht erhalten hat, lässt der Bustreiber die untergeordnete PDO intakt. Zu einem späteren Zeitpunkt, wenn alle Handles für das untergeordnete Gerät geschlossen sind, sendet der PnP-Manager die Remove-IRP für das untergeordnete Gerät, und der Bustreiber löscht die untergeordnete PDO zu diesem Zeitpunkt.

    Wenn der Bustreiber eine vorherige IRP_MN_REMOVE_DEVICE-Anforderung für das Gerät verarbeitet hat und es keine nachfolgende IRP_MN_SURPRISE_REMOVAL Anforderung gab, löscht der Bustreiber die untergeordnete PDO. In diesem Fall stellt der PnP-Manager sicher, dass alle Funktions- und Filtertreiber vom untergeordneten Gerät entfernt wurden (FDO und Filter-DOs wurden gelöscht), bevor er ein Remove-IRP an das übergeordnete Busgerät sendet. Das untergeordnete PDO ist möglicherweise noch vorhanden, sodass der Bustreiber die untergeordnete PDO löschen muss, bevor er das Busgerät entfernt.

  2. Hat der Treiber bereits eine vorherige IRP_MN_SURPRISE_REMOVAL-Anforderung für diese FDO verarbeitet?

    Wenn dies der Fall ist, führen Sie alle verbleibenden sauber aus, und fahren Sie mit Schritt 8, IoCallDriver, fort.

    Ein Treiber verwaltet in der Regel ein Flag in der Geräteerweiterung, das angibt, ob der Treiber eine IRP_MN_SURPRISE_REMOVAL Anforderung für das Gerät verarbeitet hat.

  3. Wenn der Treiber das Gerät zuvor für die Aktivierung aktiviert hat, brechen Sie die IRP_MN_WAIT_WAKE-Anforderung ab.

  4. Stellen Sie sicher, dass das Gerät inaktiv ist.

    Wenn das Gerät als Reaktion auf eine vorherige IRP_MN_QUERY_REMOVE_DEVICE noch nicht inaktiv ist, muss der Treiber das Gerät als nicht annehmend für neue Anforderungen markieren und alle Anforderungen abschließen, die in diesem Treiber in die Warteschlange gestellt werden. Der Treiber muss alle ausstehenden Anforderungen, die Zugriff auf das Gerät erfordern, fehlschlagen.

    Ein Treiber kann die IoXxxRemoveLockXxx-Routinen verwenden, um ausstehende E/A-Vorgänge zu zählen und ein Ereignis festzulegen, das angibt, dass die Verarbeitung des Entfernens fortgesetzt werden kann.

  5. Führen Sie alle Herunterschaltvorgänge aus.

    Jeder Treiber für das Gerät führt ggf. seine Herunterschaltvorgänge aus, wenn es die IRP_MN_REMOVE_DEVICE-Anforderung empfängt. Der Besitzer der Energierichtlinie für das Gerät, in der Regel der Funktionstreiber, sendet keine separate IRP_MN_SET_POWER-Anforderung , um den Energiezustand des Geräts auf D3 festzulegen. Der übergeordnete Bustreiber schaltet in der Regel den Steckplatz aus und benachrichtigt den Power Manager mit PoSetPowerState , wenn der Bustreiber das IRP remove erhält. Weitere Informationen finden Sie unter Energieverwaltung.

  6. Deaktivieren Sie alle Geräteschnittstellen, indem Sie IoSetDeviceInterfaceState aufrufen.

  7. Geben Sie alle Hardwareressourcen für das gerät frei, das vom Treiber verwendet wird.

    Die genauen Vorgänge hängen vom Gerät und dem Treiber ab, können jedoch das Trennen eines Interrupts mit IoDisconnectInterrupt, das Freigeben physischer Adressbereiche mit MmUnmapIoSpace und das Freigeben von E/A-Ports umfassen.

  8. Übergeben Sie die IRP_MN_REMOVE_DEVICE Anforderung an den nächsten Treiber.

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

    Ein Treiber muss nicht warten, bis die zugrunde liegenden Treiber ihre Entfernungsvorgänge abgeschlossen haben, bevor er mit seinen Entfernungsaktivitäten fortfährt.

  9. Entfernen Sie das Geräteobjekt mit IoDetachDevice aus dem Gerätestapel.

    Geben Sie einen Zeiger auf das nächstniedrigere Geräteobjekt als TargetDevice-Parameter an. Der Treiber empfängt einen solchen Zeiger aus dem Aufruf von IoAttachDeviceToDeviceStack in der AddDevice-Routine des Treibers.

  10. Bereinigen Sie gerätespezifische Zuordnungen, Arbeitsspeicher, Ereignisse usw.

  11. Geben Sie die FDO mit IoDeleteDevice frei.

  12. Kehren Sie aus der DispatchPnP-Routine zurück, wobei die Rückgabe status von IoCallDriver weitergegeben wird.

Ein Funktionstreiber gibt weder eine IoCompletion-Routine für ein Remove-IRP an, noch schließt er das IRP ab. IrPs werden vom übergeordneten Bustreiber entfernt.