處理IRP_MN_QUERY_REMOVE_DEVICE要求
PnP 管理員會傳送此 IRP,通知驅動程式裝置即將從電腦中移除,並詢問是否可以移除裝置,而不中斷電腦。 當使用者要求更新裝置的驅動程式時,也會傳送此 IRP。
PnP 管理員會在 IRQL PASSIVE_LEVEL在系統執行緒的內容中傳送此 IRP。
它會先執行下列動作,再將此 IRP 傳送至裝置的驅動程式:
通知註冊裝置上通知的所有使用者模式應用程式, (或相關的裝置) 。
這包括在裝置上註冊通知的應用程式、裝置的其中一個子系 (子裝置、子系子系等) ,或裝置的其中一個移除關聯性。 應用程式會藉由呼叫 RegisterDeviceNotification來註冊這類通知。
為了回應此通知,應用程式會準備移除裝置, (關閉裝置的控制碼) 或查詢失敗。
通知所有在裝置上註冊通知的核心模式驅動程式, (或相關的裝置) 。
這包括在裝置上、裝置的其中一個子系或其中一個裝置移除關聯上註冊通知的驅動程式。 驅動程式會藉由呼叫 IoRegisterPlugPlayNotification 與 EventCategoryTargetDeviceChange的事件類別目錄來註冊此通知。
為了回應此通知,驅動程式會準備移除裝置, (關閉裝置的控制碼) 或查詢失敗。
將 IRP_MN_QUERY_REMOVE_DEVICE IRP 傳送至裝置子系的驅動程式。
(Windows 2000 和更新版本系統) 如果檔案系統掛接在裝置上,PnP 管理員會將查詢移除要求傳送至檔案系統和任何檔案系統篩選器。 如果裝置有開啟的控制碼,檔案系統通常會失敗查詢移除要求。 如果沒有,檔案系統通常會鎖定磁片區,以防止未來建立成功。 如果掛接的檔案系統不支援查詢移除要求,PnP 管理員會失敗裝置的查詢移除要求。
如果上述所有步驟都成功,PnP 管理員會將 IRP_MN_QUERY_REMOVE_DEVICE 傳送給裝置的驅動程式。
IRP_MN_QUERY_REMOVE_DEVICE要求會先由裝置堆疊中的頂端驅動程式處理,然後再由每個下一個較低的驅動程式處理。 驅動程式會處理 其 DispatchPnP 常式中的 IRP。
為了回應 IRP_MN_QUERY_REMOVE_DEVICE,驅動程式必須執行下列動作:
判斷是否可以從機器中移除裝置,而不中斷作業。
如果下列任一項成立,驅動程式必須失敗查詢移除 IRP:
如果移除裝置可能會導致資料遺失。
如果元件有裝置的開啟控制碼。 (這是僅限 Windows 98/Me 的問題。Windows 2000 和更新版本的 Windows 追蹤開啟控制碼,如果 IRP_MN_QUERY_REMOVE_DEVICE 完成之後有開啟控制碼,查詢就會失敗。)
如果驅動程式已透過 (IRP_MN_DEVICE_USAGE_NOTIFICATION IRP 收到通知,) 裝置位於分頁、損毀傾印或休眠檔案的路徑。
如果驅動程式針對裝置有未處理的介面參考。 也就是說,驅動程式提供了介面來回應 IRP_MN_QUERY_INTERFACE 要求,而且介面尚未取值。
如果無法移除裝置,請失敗查詢移除 IRP。
將 Irp-IoStatus.Status > 設定為通常STATUS_UNSUCCESSFUL) 的適當錯誤狀態 (、使用 IO_NO_INCREMENT 呼叫 IoCompleteRequest ,然後從驅動程式的 DispatchPnP 常式傳回。 請勿將 IRP 傳遞至下一個較低的驅動程式。
如果驅動程式先前傳送 IRP_MN_WAIT_WAKE 要求來啟用裝置進行喚醒,請取消等候喚醒 IRP。
記錄裝置先前的 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 要求。
完成 IRP:
在函式或篩選驅動程式中:
將 [Irp-IoStatus.Status > ] 設定為 [STATUS_SUCCESS]。
使用 IoSkipCurrentIrpStackLocation 設定下一個堆疊位置,並使用 IoCallDriver將 IRP 傳遞至下一個較低的驅動程式。
將 狀態從 IoCallDriver 傳播為 DispatchPnP 常式的傳回狀態。
請勿完成 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_DEVICE 或 IRP_MN_REMOVE_DEVICE為止。