處理裝置電源狀態的IRP_MN_QUERY_POWER

裝置查詢電源 IRP 會查詢單一裝置的狀態變更,並傳送至裝置堆疊中的所有驅動程式。 這類 IRP 會在 I/O 堆疊位置的Power.Type成員中指定DevicePowerState

驅動程式在向下移動堆疊時處理查詢電源 IRP。

如果下列任一項成立,函式或篩選驅動程式可能會失敗 IRP_MN_QUERY_POWER 要求:

  • 裝置已啟用喚醒,而要求的電源狀態低於裝置可以喚醒系統的狀態。 例如,可以從 D2 喚醒系統的裝置,但無法從 D3 喚醒系統,將會失敗 D3 的查詢,但會成功查詢 D2。

  • 輸入要求的狀態會強制驅動程式放棄會遺失資料的作業,例如開啟的數據機連線。 驅動程式很少會因為這個原因而失敗查詢;在大部分情況下,應用程式會處理這類情況。

若要失敗 IRP_MN_QUERY_POWER 要求,驅動程式會採取下列步驟:

  1. 呼叫 PoStartNextPowerIrp 以指出驅動程式已準備好處理下一個電源 IRP。 (Windows Server 2003、Windows XP 和 Windows 2000 only.)

  2. Irp-IoStatus.Status > 設定為失敗狀態,並呼叫 IoCompleteRequest,並指定IO_NO_INCREMENT。 驅動程式不會進一步將 IRP 傳遞至裝置堆疊。

  3. 其 DispatchPower 常式傳回錯誤狀態。

如果驅動程式成功查詢電源 IRP,則它不得啟動任何作業,或採取任何其他動作,以防止其成功完成後續 的IRP_MN_SET_POWER 要求至查詢的電源狀態。

成功 IRP 的驅動程式必須針對已查詢狀態的 set-power IRP 做好準備,並向下傳遞查詢 IRP,如下所示:

  1. 完成任何未完成的 I/O 作業。

  2. 佇列傳入的 I/O 要求。

  3. 避免啟動任何其他會干擾轉換至指定電源狀態的新活動。 不過,驅動程式不應該儲存裝置內容,或採取其他步驟來關機。

  4. 呼叫 IoCopyCurrentIrpStackLocationToNext 來設定下一個較低驅動程式的 IRP 堆疊位置。

  5. 設定 IoCompletion 常式。 在 IoCompletion 常式中,呼叫 PoStartNextPowerIrp (Windows Server 2003、Windows XP 和 Windows 2000 僅) ,以指出驅動程式處理下一個電源 IRP 的整備程度。

  6. 在 Windows Server 2003、Windows XP 和 Windows 2000) 中呼叫IoC (allDriver) (,將查詢 IRP 傳遞至下一個較低的驅動程式。 請勿完成 IRP。

  7. 傳回STATUS_PENDING。 驅動程式不得變更 Irp-IoStatus.Status >的值。

當查詢電源 IRP 到達匯流排驅動程式時,匯流排驅動程式會呼叫 PoStartNextPowerIrp (Windows Server 2003、Windows XP 和 Windows 2000 僅) ,並將 Irp-IoStatus.Status > 設定為STATUS_SUCCESS,如果驅動程式可以變更為指定的電源狀態,或如果無法變更,則會設定失敗狀態。 然後匯流排驅動程式會呼叫 IoCompleteRequest,並指定IO_NO_INCREMENT。

一般裝置堆疊中的驅動程式會處理裝置查詢電源 IRP,如下所示:

  • 大部分篩選驅動程式應該只會將 IRP 傳遞至下一個較低的驅動程式 (請參閱 傳遞 Power IRP) 並傳回STATUS_PENDING。 不過,某些篩選驅動程式可能必須先執行裝置特定的工作,例如佇列連入 IRP 或節省裝置電源狀態。

  • 函式驅動程式會 (執行裝置特定工作,例如完成擱置的 I/O 要求、佇列傳入 I/O 要求、儲存裝置內容,或變更裝置電源) 、設定 IoCompletion 常式,並將裝置電源 IRP 傳遞至下一個較低的驅動程式 (請參閱 傳遞 Power IRP) 。 它會從 DispatchPower 常式傳回STATUS_PENDING。

  • 匯流排驅動程式會呼叫 PoStartNextPowerIrp (Windows Server 2003、Windows XP 和 Windows 2000,只) 啟動下一個電源 IRP。 然後,它會完成 IRP,並指定IO_NO_INCREMENT。 如果驅動程式無法立即完成 IRP,它會呼叫 IoMarkIrpPending、從其 DispatchPower 常式傳回STATUS_PENDING,並在稍後完成 IRP。

即使目標裝置已處於查詢電源狀態,每個函式或篩選驅動程式都必須將 I/O 排入佇列,並將 IRP 向下傳遞至下一個較低的驅動程式。 IRP 必須一直往下移動裝置堆疊到匯流排驅動程式,以完成它。

處理 IRP_MN_QUERY_POWER 要求時,驅動程式應該儘快從 DispatchPower 常式傳回。 驅動程式不得在其 DispatchPower 常式中等候處理相同 IRP 的程式碼發出訊號的核心事件。 因為電源 IRP 會在整個系統中同步處理,所以可能會發生死結。