共用方式為


處理 IRP_MN_QUERY_REMOVE_DEVICE 請求

PnP 管理員會傳送此 IRP,通知驅動程式裝置即將從電腦中移除,並詢問裝置是否可以在不中斷電腦運作的情況下移除。 當使用者要求更新裝置的驅動程式時,也會傳送此 IRP。

PnP 管理員會在系統執行緒環境中,在 IRQL PASSIVE_LEVEL 傳送此 IRP。

它會先執行下列動作,再將此 IRP 傳送至裝置的驅動程式:

  • 通知所有已註冊在裝置(或相關裝置)上接收通知的使用者模式應用程式。

    這包括在裝置上註冊通知的應用程式、裝置的後代設備(子裝置、及子裝置的子裝置等等),或裝置的某一個 移除關係。 應用程式會藉由呼叫 CM_Register_NotificationRegisterDeviceNotification來註冊這類通知。

    為了回應此通知,應用程式會準備移除裝置(關閉裝置的控制代碼),或拒絕查詢。 如需如何處理這些通知的詳細資訊,請參閱 註冊裝置介面抵達和裝置移除通知

  • 通知所有已在裝置(或相關裝置)上註冊通知的核心模式驅動程式。

    這包括在裝置上註冊通知的驅動程式、裝置的其中一個子系,或裝置的其中一個 移除關係。 驅動程式會透過呼叫 IoRegisterPlugPlayNotification,並指定事件類別為 EventCategoryTargetDeviceChange,來註冊此通知。

    為了回應此通知,驅動程式處理程序會準備移除裝置(關閉對裝置的控制),或操作不成功。

  • IRP_MN_QUERY_REMOVE_DEVICE IRP 傳送至裝置子系的驅動程式。 如需裝置堆疊如何處理此 IRP 的詳細資訊,請參閱下文。

  • (Windows 2000 及更新版本系統)如果裝置上掛接文件系統,PnP 管理員會將查詢移除要求傳送至文件系統和任何文件系統篩選器。 如果設備有開啟的控制代碼,文件系統通常會拒絕查詢移除的請求。 如果沒有,文件系統通常會鎖定磁碟區,以防止未來的創建操作成功。 如果掛載的檔案系統不支援查詢移除請求,PnP 管理員會拒絕裝置的查詢移除請求。

如果上述所有步驟都成功,PnP 管理員會將 IRP_MN_QUERY_REMOVE_DEVICE 傳送給裝置的驅動程式。

IRP_MN_QUERY_REMOVE_DEVICE 要求會先由裝置堆疊中的頂端驅動程式處理,然後再由每個下一個較低的驅動程式處理。 驅動程式會在其 DispatchPnP 例程中的 處理移除 IRP。

為了回應 IRP_MN_QUERY_REMOVE_DEVICE,驅動程式必須執行下列動作:

  1. 判斷是否可以安全地從電腦移除裝置。

    如果下列任一項成立,驅動程式必須拒絕查詢移除 IRP:

    • 如果移除裝置可能會導致數據遺失。

    • 如果元件具有裝置的開啟句柄。 (這是 Windows 98/Me 的特有問題。Windows 2000 和更新版本的 Windows 會追蹤已開啟的控制代碼,如果在 IRP_MN_QUERY_REMOVE_DEVICE 完成之後仍有開啟的控制代碼,查詢將會失敗。)

    • 如果驅動程式已收到通知(透過 IRP_MN_DEVICE_USAGE_NOTIFICATION IRP),表示該裝置位於分頁、崩潰傾印或休眠檔案的路徑上。

    • 如果驅動程式對裝置有未消除的介面參考。 也就是說,驅動程式提供了一個介面來回應 IRP_MN_QUERY_INTERFACE 要求,而且該介面尚未被解除參照。

  2. 如果無法移除裝置,將查詢移除 IRP 設為失敗。

    Irp->IoStatus.Status 設定為適當的錯誤狀態(通常是STATUS_UNSUCCESSFUL)、使用 IO_NO_INCREMENT 呼叫 IoCompleteRequest,然後從驅動程式的 DispatchPnP 例程傳回。 請勿將 IRP 傳遞至下一個較低的驅動程式。

  3. 如果驅動程式先前已傳送 IRP_MN_WAIT_WAKE 要求以啟用裝置的喚醒功能,請取消該等候喚醒 IRP。

  4. 記錄裝置先前的 PnP 狀態。

    驅動程式應該記錄驅動程式收到 IRP_MN_QUERY_REMOVE_DEVICE 要求時裝置處於的 PnP 狀態,因為驅動程式必須在取消查詢時將裝置傳回該狀態(IRP_MN_CANCEL_REMOVE_DEVICE)。 先前的狀態通常是「已啟動」,也就是當驅動程式成功完成 IRP_MN_START_DEVICE 要求時,裝置輸入的狀態。

    不過,可能有其他先前的狀態。 例如,使用者可能已透過設備管理器停用裝置。 或者,為了回應 IRP_MN_QUERY_CAPABILITIES 要求,父總線驅動程式(或總線驅動程式上的篩選驅動程式)可能已回報裝置的硬體已被停用。 在任一情況下,已停用的裝置的驅動程式會在收到 IRP_MN_START_DEVICE 要求之前收到 IRP_MN_QUERY_REMOVE_DEVICE 要求。

  5. 完成 IRP:

    在函式或篩選驅動程式中:

    在公交車司機中:

    • Irp->IoStatus.Status 設定為 STATUS_SUCCESS。

    • 使用 IO_NO_INCREMENT 來完成 IRP(IoCompleteRequest)。

    • DispatchPnP 函式返回。

如果裝置堆疊中的任何驅動程式在 IRP_MN_QUERY_REMOVE_DEVICE中失敗,PnP 管理員會將 IRP_MN_CANCEL_REMOVE_DEVICE 傳送至裝置堆疊。 這可防止驅動程式需要一個 IoCompletion 例程來偵測查詢移除 IRP,以判斷較低層驅動程式是否導致 IRP 失敗。

一旦驅動程式成功處理 IRP_MN_QUERY_REMOVE_DEVICE 並認為該裝置處於移除擱置狀態,驅動程式必須拒絕任何後續的裝置建立請求。 驅動程式會像往常一樣處理所有其他 IRP,直到驅動程式收到 IRP_MN_CANCEL_REMOVE_DEVICEIRP_MN_REMOVE_DEVICE為止。