共用方式為


建立 Lower-Level 驅動程式的 IRP

若要為非同步要求配置 IRP,這會由較低的驅動程式在任意執行緒內容中處理, DispatchReadWrite 常式可以呼叫下列其中一個支援常式:

  • IoAllocateIrp,其會配置 IRP 和一些以零初始化的 I/O 堆疊位置

    分派常式必須為新配置的 IRP 設定下一個較低驅動程式的 I/O 堆疊位置,通常是從原始 IRP 中複製 (可能修改的) 資訊。 如果較高層級的驅動程式為新配置的 IRP 配置自己的 I/O 堆疊位置,則分派常式可以在該處設定每個要求內容資訊,以供 IoCompletion 常式使用。

  • IoBuildAsynchronousFsdRequest,其會根據呼叫端指定的參數,設定下一個較低驅動程式的 I/O 堆疊位置

    較高層級的驅動程式可以呼叫此常式,為 IRP_MJ_READIRP_MJ_WRITEIRP_MJ_FLUSH_BUFFERSIRP_MJ_SHUTDOWN 要求配置 IRP。

    針對這類 IRP 呼叫 IoCompletion 常式時,它可以檢查 I/O 狀態欄塊,並視需要 (或可能) 在 IRP 中設定下一個較低驅動程式的 I/O 堆疊位置,然後再次重試要求或重複使用它。 不過, IoCompletion 常式在 IRP 中本身沒有本機內容儲存體,因此驅動程式必須維護內部記憶體中其他地方原始要求的相關內容。

  • IoMakeAssociatedIrp,它會配置 IRP 和一些以零初始化的 I/O 堆疊位置,並將 IRP 與 主要 IRP 產生關聯。

    中繼驅動程式無法呼叫 IoMakeAssociatedIrp 來建立較低驅動程式的 IRP。

    呼叫 IoMakeAssociatedIrp 以建立較低驅動程式的 IRP 的任何最高層級驅動程式,都可以在上傳送相關聯的 IRP 並呼叫原始主要 IRP 的 IoMarkIrpPending 之後,將控制權傳回給 I/O 管理員。 當所有相關聯的 IRP 都由較低驅動程式完成時,最高層級驅動程式可以依賴 I/O 管理員來完成主要 IRP。

    驅動程式很少會為相關聯的 IRP 設定 IoCompletion 常式。 如果高層級驅動程式呼叫 IoSetCompletionRoutine 以取得其建立的相關聯 IRP,則如果驅動程式從 其 IoCompletion 常式傳回STATUS_MORE_PROCESSING_REQUIRED,I/O 管理員就不會完成主要 IRP。 在這些情況下,驅動程式的 IoCompletion 常式必須使用 IoCompleteRequest明確完成主要 IRP。

如果驅動程式在新的 IRP 中配置自己的 I/O 堆疊位置,則分派常式必須在呼叫IoGetCurrentIrpStackLocation 之前呼叫 IoSetNextIrpStackLocation,才能在IoCompletion常式的自己的 I/O 堆疊位置中設定內容。 如需詳細資訊,請參閱 在Intermediate-Level驅動程式中處理 IRP

分派常式必須使用原始 IRP 呼叫 IoMarkIrpPending ,但不能呼叫任何驅動程式配置的 IRP,因為 IoCompletion 常式會釋放它們。

如果分派常式為部分傳輸配置 IRP,而基礎設備磁碟機可能會控制抽取式媒體裝置,則分派常式必須從原始 IRP 中的 Tail.Overlay.Thread 值,在其新配置的 IRP 中設定執行緒內容。

卸載式媒體裝置的基礎驅動程式可能會針對驅動程式配置的 IRP 呼叫 IoSetHardErrorOrVerifyDevice,其參考 Irp-Tail.Overlay.Thread >上的指標。 如果驅動程式呼叫此支援常式,檔案系統驅動程式可以將對話方塊傳送給適當的使用者執行緒,提示使用者取消、重試或失敗驅動程式無法滿足的作業。 如需詳細資訊 ,請參閱支援卸載式媒體

將所有驅動程式配置的 IRP 傳送至較低的驅動程式之後,分派常式必須傳回STATUS_PENDING。

驅動程式的 IoCompletion 常式應該使用 IoFreeIrp 釋放所有驅動程式配置的 IRP,然後再呼叫原始 IRP 的 IoCompleteRequest 。 當它完成原始 IRP 時, IoCompletion 常式必須先釋放所有驅動程式配置的 IRP,才能傳回控制權。

每個較高層級的驅動程式都會設定任何驅動程式配置的 (,並重複使用) IRP 給較低的驅動程式,如此一來,無論指定的要求來自中繼驅動程式或源自任何其他來源,例如檔案系統或使用者模式應用程式,都對基礎設備磁碟機而言不重要。

最高層級的驅動程式可以呼叫 IoMakeAssociatedIrp 來配置 IRP,並針對較低驅動程式鏈結加以設定。 只要驅動程式未使用原始 IRP 呼叫 IoSetCompletionRoutine 或它所配置的任何相關聯 IRP,I/O 管理員就會自動完成原始 IRP。 不過,最高層級驅動程式不得為要求緩衝 I/O 作業的任何 IRP 配置相關聯的 IRP。

中繼層級驅動程式無法藉由呼叫 IoMakeAssociatedIrp,為較低層級的驅動程式配置 IRP。 中繼驅動程式接收的任何 IRP 可能已經是相關聯的 IRP,而且驅動程式無法將另一個 IRP 與這類 IRP 產生關聯。

相反地,如果中繼驅動程式為較低的驅動程式建立 IRP,它應該呼叫 IoAllocateIrpIoBuildDeviceIoControlRequestIoBuildSynchronousFsdRequestIoBuildAsynchronousFsdRequest。 不過, IoBuildSynchronousFsdRequest 只能在下列情況下呼叫:

  • 由驅動程式建立的執行緒來建置 IRP 以進行讀取或寫入要求,因為這類執行緒可以在發送器物件上等候非位元組執行緒內容, (自己的) ,例如傳遞至IoBuildSynchronousFsdRequest的驅動程式初始化事件

  • 在初始化期間或在卸載期間于系統執行緒內容中

  • 為原本同步的作業建置 IRP,例如建立、排清、關機、關閉和裝置控制要求

不過,驅動程式較可能呼叫 IoBuildDeviceIoControlRequest 來配置裝置控制 IRP,而不是 IoBuildSynchronousFsdRequest