取消等候/喚醒 IRP
只有傳送等候/喚醒 IRP 的驅動程式可以取消該 IRP。
在下列情況下,驅動程式可能需要解除擱置的等候/喚醒 IRP:
驅動程式會收到裝置的 PnP IRP_MN_STOP_DEVICE、 IRP_MN_QUERY_REMOVE_DEVICE、 IRP_MN_REMOVE_DEVICE或 IRP_MN_SURPRISE_REMOVAL 要求。 驅動程式應該在重新開機裝置之後,重新發出等候/喚醒 IRP (PoRequestPowerIrp) 。
系統會進入睡眠狀態,但裝置不應該啟用以喚醒系統。
例如,USB 中樞驅動程式可能會在裝置啟動時傳送 IRP_MN_WAIT_WAKE 要求,以防稍後將其中一個輸入裝置置於睡眠狀態。 當系統處於工作狀態時,來自裝置的喚醒訊號會將裝置傳回工作狀態 (,但不會影響系統電源狀態) 。 當系統準備關閉時,如果不允許裝置喚醒系統,USB 中樞驅動程式就會取消此 IRP。
系統會進入睡眠狀態,裝置無法從中喚醒它。 也就是說,其進入狀態比其DEVICE_CAPABILITIES結構中指定的SystemWake值少。
裝置進入電源狀態,無法回應喚醒訊號。 也就是說,其進入狀態比其DEVICE_CAPABILITIES結構中指定的DeviceWake值少。
若要取消等候/喚醒 IRP,傳送 IRP 的驅動程式會呼叫 IoCancelIrp,並將指標傳遞至先前呼叫 PoRequestPowerIrp時傳回的 IRP。
驅動程式不得取消未傳送的等候/喚醒 IRP。
取消等候/喚醒 IRP 的常式
許多函式和匯流排驅動程式都應該為擱置等候/喚醒 IRP 設定 Cancel 常式;下列驅動程式類型必須設定這類常式:
變更裝置設定以啟用或停用喚醒的驅動程式。
將 IRP_MN_WAIT_WAKE 要求傳送至父裝置驅動程式的驅動程式。
Cancel常式可讓驅動程式停用其裝置的喚醒,以及清除與擱置等候/喚醒 IRP 相關的任何資料。 要求父裝置等候/喚醒 IRP 的驅動程式也可以取消這些 IRP。
在等候/喚醒 取消 常式中,驅動程式應該採取下列步驟:
呼叫 IoSetCancelRoutine ,將 IRP 的 Cancel 常式重設為 Null。
呼叫 IoReleaseCancelSpinLock,傳遞 IRP 中指定的 CancelIRQL ,以釋放 IRP 的取消微調鎖定。
重設裝置擴充功能中的任何相關欄位。 例如,當等候/喚醒 IRP 擱置時,大部分驅動程式都會設定旗標,並在裝置擴充功能中保留 IRP 的指標。
請注意,當驅動程式取消另一個這類 IRP 時,可能會收到等候/喚醒 IRP。 驅動程式必須檢查它是否已在微調鎖定保護 (或其對等) 下擁有 IRP。 如果是,驅動程式必須仔細同步處理其處理,以確保它取消正確的 IRP。 如需在 取消 常式中使用微調鎖定的詳細資訊,請參閱 取消 IRP。
變更任何必要的裝置設定。 例如,數據機驅動程式會停用裝置的喚醒設定。
將 Irp-IoStatus.Status > 設定為 STATUS_CANCELLED。
呼叫 IoCompleteRequest 以完成等候/喚醒 IRP,並指定IO_NO_INCREMENT。
如果驅動程式先前要求父裝置的相關 IRP_MN_WAIT_WAKE ,驅動程式應該從其 Cancel 常式內取消該 IRP。 驅動程式必須先釋放取消微調鎖定,才能取消父系的 IRP。
例如,作為裝置的匯流排驅動程式,並擁有其父系電源原則驅動程式的驅動程式,應該取消先前傳送至父系的相關等候/喚醒 IRP。 呼叫 IoCancelIrp 會叫用父系的 Cancel 常式,依此類移裝置堆疊。