註冊 IoCompletion 常式
若要註冊 IoCompletion 常式,分派常式會呼叫 IoSetCompletionRoutine,並提供 IoCompletion 常式的位址,以及其後續會使用 IoCallDriver傳遞至較低驅動程式的 IRP。
呼叫 IoSetCompletionRoutine時,分派常式會指定 I/O 管理員應該呼叫指定的 IoCompletion 常式的情況。 您可以選擇讓 較低 層級驅動程式順利完成 IRP (InvokeOnSuccess) 、以錯誤狀態值完成 IRP, (InvokeOnError) ,或取消任何組合的 IRP (InvokeOnCancel) 。
IoCompletion常式的目的是監視低階驅動程式對 IRP 執行的動作,並視需要執行額外的完成處理。 具體而言,驅動程式 IoCompletion 常式最常見的用法如下:
處置驅動程式使用 IoAllocateIrp 或 IoBuildAsynchronousFsdRequest 配置的 IRP
任何使用這些支援常式來配置 IRP 的高階驅動程式都必須提供該 IRP 的 IoCompletion 常式。 IoCompletion常式必須呼叫IoFreeIrp以處置驅動程式配置的 IRP。
若要重複使用傳入的 IRP,要求較低的驅動程式完成一些作業,例如部分傳輸,直到 IoCompletion 常式滿足原始要求並完成為止
若要重試較低驅動程式已完成且發生錯誤的要求
最高層級的驅動程式,例如檔案系統,較可能擁有嘗試重試要求的 IoCompletion 常式,而不是中繼驅動程式,但可能分層在緊密結合的埠驅動程式上方的類別驅動程式。 不過,任何中繼驅動程式都使用 IoCompletion 常式重試要求。
雖然最高層級或中繼驅動程式的 DispatchReadWrite 常式最有可能處理需要 IoCompletion 常式的 IRP,但任何將 IRP 傳遞至較低驅動程式的驅動程式中的任何分派常式都可以註冊 IoCompletion 常式。
對於驅動程式配置的 IRP 和重複使用的 IRP,分派常式必須呼叫具有下列布林參數的 IoSetCompletionRoutine :
InvokeOnSuccess 設定為 TRUE
InvokeOnError 設定為 TRUE
如果鏈結中的任何較低驅動程式可能處理可取消的 IRP,InvokeOnCancel會設定為TRUE
InvokeOnCancel通常設定為TRUE,不論 IRP 是否可能以 STATUS_CANCELLED傳回,以確保IoCompletion常式釋放每個驅動程式配置的 IRP,或檢查每個重複使用 IRP 的完成狀態。
使用 IoAllocateIrp 或 IoBuildAsynchronousFsdRequest為較低驅動程式配置 IRP 的分派常式,必須為每個驅動程式配置的 IRP 設定 IoCompletion 常式。
分派常式必須設定原始 IRP 及其配置 IRP () 的狀態, 以供 IoCompletion 常式使用。 IoCompletion常式至少需要存取原始 IRP,以及配置多少額外的 IRP 計數。
分派常式應該呼叫 IoSetCompletionRoutine ,並將 IRP 的所有 InvokeOnXxx 參數設定為 TRUE (其配置) 。
針對一連串作業或重試 I/O 作業重複使用 IRP 的分派常式,必須針對將重複使用或重試的每個 IRP 呼叫 IoSetCompletionRoutine 。
分派常式必須儲存原始 IRP 的狀態資訊, 以供 IoCompletion 常式後續使用。
例如, DispatchReadWrite 常式必須先儲存 IoCompletion 常式輸入 IRP 的相關傳輸參數,才能在該 IRP 中設定下一個較低驅動程式的部分傳輸。 如果 DispatchReadWrite 常式修改 IoCompletion 常式需要判斷原始要求何時滿足的任何參數,儲存參數特別重要。
如果 IoCompletion 常式可以重試要求,則分派常式必須針對 其 IoCompletion 常式的重試次數設定驅動程式決定的上限,才能完成原始的 IRP 併發生錯誤。
如果要重複使用 IRP,分派常式應該呼叫 IoSetCompletionRoutine ,並將所有 InvokeOnXxx 參數設定為 TRUE。
對於非同步要求,任何中繼驅動程式的分派常式都必須呼叫原始 IRP 的 IoMarkIrpPending 。 然後,它必須在將 IRP 傳送至較低的驅動程式之後傳回STATUS_PENDING。