共用方式為


IoBuildAsynchronousFsdRequest 函式 (wdm.h)

IoBuildAsynchronousFsdRequest 例程配置並設定要傳送至較低層級驅動程式的 IRP。

語法

__drv_aliasesMem PIRP IoBuildAsynchronousFsdRequest(
  [in]           ULONG            MajorFunction,
  [in]           PDEVICE_OBJECT   DeviceObject,
  [in, out]      PVOID            Buffer,
  [in, optional] ULONG            Length,
  [in, optional] PLARGE_INTEGER   StartingOffset,
  [in, optional] PIO_STATUS_BLOCK IoStatusBlock
);

參數

[in] MajorFunction

要設定在 IRP 中的主要函式程式碼。 此程式代碼可以是 IRP_MJ_PNPIRP_MJ_READIRP_MJ_WRITEIRP_MJ_FLUSH_BUFFERSIRP_MJ_SHUTDOWN

[in] DeviceObject

下一個較低驅動程式裝置物件的指標。 這個物件代表讀取、寫入、排清或關機作業的目標裝置。

[in, out] Buffer

讀取數據或從中寫入數據之緩衝區的指標。 這個自變數的值是針對排清和關機要求 NULL

[in, optional] Length

緩衝區所指向的長度,以位元組為單位,Buffer。 對於磁碟之類的裝置,此值必須是扇區大小的整數倍數。 從 Windows 8 開始,扇區大小可以是 4,096 或 512 個字節。 在舊版 Windows 中,扇區大小一律為 512 位元組。 讀取和寫入要求需要此參數,但排清和關機要求必須為零。

[in, optional] StartingOffset

輸入/輸出媒體上起始位移的指標。 排清和關機要求的這個自變數值為零。

[in, optional] IoStatusBlock

I/O 狀態區塊位址的指標,其中 to-be-called 驅動程式會傳回所要求作業的最終狀態。

傳回值

IoBuildAsynchronousFsdRequest 會傳回 IRP 的指標,或如果無法配置 IRP,NULL 指標。

言論

中繼或最高層級驅動程式可以呼叫 IoBuildAsynchronousFsdRequest,為傳送至較低層級驅動程式的要求設定 IRP。 呼叫驅動程式必須針對 IRP 提供 IoCompletion 例程,以便將 IRP 解除分配 IoFreeIrp。 如需 IRP 解除分配的詳細資訊,請參閱範例。

所建置的 IRP 只包含足夠的資訊來啟動作業並完成 IRP。 不會追蹤其他內容資訊,因為異步要求與內容無關。

較低層級的驅動程式可能會對提供給此例程的參數施加限制。 例如,磁碟驅動器可能需要針對 LengthStartingOffset 提供的值, 為裝置扇區大小的整數倍數。

中繼或最高層級驅動程式也可以呼叫 IoBuildDeviceIoControlRequestIoAllocateIrpIoBuildSynchronousFsdRequest,以設定傳送至較低層級驅動程式的要求。 只有最高層級的驅動程式可以呼叫 IoMakeAssociatedIrp

IoBuildAsynchronousFsdRequest 呼叫期間,I/O 管理員會將 IRP 結構的 Tail.Overlay.Thread 成員設定為指向呼叫端線程對象的線程物件,但不會代表呼叫者取得線程物件的計數參考。 呼叫端將 IRP 傳送至目標裝置的驅動程序之後,此驅動程式可能會使用 Tail.Overlay.Thread 成員來存取線程物件。 例如,記憶體驅動程式可能會呼叫 IoSetHardErrorOrVerifyDevice 例程,並提供 IRP 作為輸入參數的指標。 在此呼叫期間,IoSetHardErrorOrVerifyDevice 會使用 Tail.Overlay.Thread 成員來存取線程物件。 以這種方式存取線程物件時,呼叫 IoBuildAsynchronousFsdRequest 的驅動程式 配置 IRP 負責確保處理 IRP 時線程物件保持有效。

若要讓線程物件保持有效,呼叫 IoBuildAsynchronousFsdRequest 的驅動程式 可以在傳送 IRP 之前,先在線程物件上取得計數參考。 例如,此驅動程式可以呼叫 ObReferenceObjectByPointerWithTag 例程,並提供 Object 參數,Tail.Overlay.Thread 的物件指標IRP 結構的成員。 稍後,此驅動程式的完成例程可以藉由呼叫 ObDereferenceObjectWithTag等例程來取值物件。

驅動程式可能會在一個線程中呼叫 IoBuildAsynchronousFsdRequest,並將此呼叫所配置的 IRP 傳送到另一個線程。 傳送 IRP 之前,此驅動程式應設定 IRP Tail.Overlay.Thread 成員,以指向傳送線程的線程物件。 一般而言,驅動程式會呼叫 PsGetCurrentThread 例程,以取得線程對象指標。

呼叫 IoBuildAsynchronousFsdRequest 來配置 IRP 的驅動程式不一定需要在 IRP Tail.Overlay.Thread 所指向的線程物件上取得計數參考, IRP 成員。 驅動程式可能會改用另一種技術來確保此線程對象在處理 IRP 時仍然有效。 例如,如果驅動程式建立線程,線程可以等到 IRP 完成以終止本身為止。

例子

呼叫 IoFreeIrp之前,必須先執行額外的步驟,才能釋放 ioBuildAsynchronousFsdReque st 所建置 IRP 的緩衝區,如果下列全都成立:

  • 已從系統記憶體集區配置緩衝區。

  • 在目標裝置的裝置物件中,DO_DIRECT_IO旗標是在 [DeviceObject->Flags] 字段中設定。

  • Irp->MdlAddress 字段為非 NULL。

釋放此 IRP 的緩衝區之前,請使用 Irp->MdlAddress 作為參數值,呼叫 MmUnlockPages 例程。 此呼叫會遞減 IoBuildAsynchronousFsdRequest 新增至 MDL 集區頁面的額外參考計數。 否則,後續呼叫 IoFreeMdl 將會錯誤檢查,因為這些集區頁面的參考計數會是 2,而不是 1。 下列程式代碼範例顯示 mmUnlockPagesIoFreeMdl,以及針對此案例 IoFreeIrp 呼叫:

if (((DeviceObject->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) &&
    (Irp->MdlAddress != NULL))
{
    MmUnlockPages(Irp->MdlAddress);
}

IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);

要求

要求 價值
目標平臺 普遍
標頭 wdm.h (包括 Wdm.h、Ntddk.h、Ntifs.h)
連結庫 NtosKrnl.lib
DLL NtosKrnl.exe
IRQL IRQL <= APC_LEVEL
DDI 合規性規則 ForwardedAtBadIrqlFsdAsync(wdm)HwStorPortProhibitedDIS(storport)IoBuildFsdComplete(wdm)IoBuildFsdForward(wdm)IoBuildFsdFree(wdm)

另請參閱

IO_STACK_LOCATION

IRP

IoAllocateIrp

IoBuildDeviceIoControlRequest

IoBuildSynchronousFsdRequest

IoCallDriver

IoFreeIrp

IoFreeMdl

IoMakeAssociatedIrp

IoSetCompletionRoutine

IoSetHardErrorOrVerifyDevice

mmUnlockPages

ObDereferenceObjectWithTag

ObReferenceObjectByPointerWithTag

PsGetCurrentThread