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_PNP、IRP_MJ_READ、IRP_MJ_WRITE、IRP_MJ_FLUSH_BUFFERS、またはIRP_MJ_SHUTDOWNできます。
[in] DeviceObject
次の下位ドライバーのデバイス オブジェクトへのポインター。 このオブジェクトは、読み取り、書き込み、フラッシュ、またはシャットダウン操作のターゲット デバイスを表します。
[in, out] Buffer
データの読み取り先またはデータの書き込み元となるバッファーへのポインター。 この引数の値は、フラッシュ要求とシャットダウン要求の 場合は NULL です 。
[in, optional] Length
Buffer が指すバッファーの長さ (バイト単位)。 ディスクなどのデバイスの場合、この値はセクター サイズの整数倍である必要があります。 Windows 8以降、セクター サイズは 4,096 バイトまたは 512 バイトです。 以前のバージョンの Windows では、セクター サイズは常に 512 バイトです。 このパラメーターは、読み取り要求と書き込み要求では必須ですが、フラッシュ要求とシャットダウン要求ではゼロにする必要があります。
[in, optional] StartingOffset
入力/出力メディアの開始オフセットへのポインター。 フラッシュ要求とシャットダウン要求の場合、この引数の値は 0 です。
[in, optional] IoStatusBlock
呼び出されるドライバーが要求された操作に関する最終的な状態を返す I/O 状態ブロックのアドレスへのポインター。
戻り値
IoBuildAsynchronousFsdRequest は、IRP へのポインターを返します。IRP を割り当てることができない場合は NULL ポインターを返します。
注釈
中間ドライバーまたは最上位レベルのドライバーは 、IoBuildAsynchronousFsdRequest を呼び出して、下位レベルのドライバーに送信される要求の IRP を設定できます。 呼び出し元のドライバーは、 IRP の IoCompletion ルーチンを提供する必要があります。そのため、IRP は IoFreeIrp を使用して割り当てを解除できます。 IRP の割り当て解除の詳細については、「例」を参照してください。
ビルドされる IRP には、操作を開始して IRP を完了するのに十分な情報のみが含まれています。 非同期要求はコンテキストに依存しないため、他のコンテキスト情報は追跡されません。
下位レベルのドライバーでは、このルーチンに指定されたパラメーターに制限が課される場合があります。 たとえば、ディスク ドライバーでは、 Length と StartingOffset に指定された値を、デバイスのセクター サイズの整数の倍数にする必要がある場合があります。
中間または最上位レベルのドライバーは、 IoBuildDeviceIoControlRequest、 IoAllocateIrp、または IoBuildSynchronousFsdRequest を呼び出して、下位レベルのドライバーに送信する要求を設定することもできます。 IoMakeAssociatedIrp を呼び出すことができるのは、最上位レベルのドライバーのみです。
IoBuildAsynchronousFsdRequest 呼び出し中に、I/O マネージャーは、呼び出し元のスレッド オブジェクトを指すように IRP 構造体の Tail.Overlay.Thread メンバーを設定しますが、呼び出し元の代わりにスレッド オブジェクトへのカウントされた参照を受け取りません。 呼び出し元がターゲット デバイスのドライバーに IRP を送信した後、このドライバーは Tail.Overlay.Thread メンバーを使用してスレッド オブジェクトにアクセスする場合があります。 たとえば、記憶域ドライバーは 、IoSetHardErrorOrVerifyDevice ルーチンを呼び出し、入力パラメーターとして IRP へのポインターを指定します。 この呼び出し中、 IoSetHardErrorOrVerifyDevice はTail.Overlay.Thread メンバーを使用してスレッド オブジェクトにアクセスします。 この方法でスレッド オブジェクトにアクセスすると、IRP を割り当てるために IoBuildAsynchronousFsdRequest を呼び出したドライバーは、IRP の処理中にスレッド オブジェクトが有効なままであることを確認します。
スレッド オブジェクトを有効に保つために、 IoBuildAsynchronousFsdRequest を呼び出すドライバーは、IRP を送信する前にスレッド オブジェクトのカウントされた参照を取得できます。 たとえば、このドライバーは ObReferenceObjectByPointerWithTag ルーチンを呼び出し、オブジェクト パラメーターとして、IRP 構造体の Tail.Overlay.Thread メンバーからのオブジェクト ポインターを指定できます。 後で、このドライバーの完了ルーチンは、 ObDereferenceObjectWithTag などのルーチンを呼び出すことによって、オブジェクトを逆参照できます。
ドライバーは、あるスレッドで IoBuildAsynchronousFsdRequest を呼び出し、この呼び出しによって割り当てられた IRP を別のスレッドで送信する場合があります。 IRP を送信する前に、このドライバーは、送信スレッドのスレッド オブジェクトを指す IRP の Tail.Overlay.Thread メンバーを設定する必要があります。 通常、ドライバーは PsGetCurrentThread ルーチンを呼び出してスレッド オブジェクト ポインターを取得します。
IoBuildAsynchronousFsdRequest を呼び出して IRP を割り当てるドライバーは、IRP の Tail.Overlay.Thread メンバーが指すスレッド オブジェクトに対してカウントされた参照を取得する必要はありません。 ドライバーは、代わりに別の手法を使用して、IRP が処理されている間、このスレッド オブジェクトが有効なままであることを保証する場合があります。 たとえば、ドライバーがスレッドを作成した場合、スレッドは IRP が完了してそれ自体が終了するまで待機できます。
例
IoFreeIrp を呼び出す前に、次がすべて当てはまる場合に、IoBuildAsynchronousFsdRequest によってビルドされた IRP のバッファーを解放する追加の手順が必要です。
バッファーはシステム メモリ プールから割り当てられています。
ターゲット デバイスのデバイス オブジェクトでは、DO_DIRECT_IO フラグが [DeviceObject-Flags>] フィールドに設定されます。
Irp-MdlAddress> フィールドは NULL 以外です。
この IRP のバッファーを解放する前に、パラメーター値として Irp-MdlAddress> を使用して MmUnlockPages ルーチンを呼び出します。 この呼び出しは、 IoBuildAsynchronousFsdRequest が MDL のプール ページに追加した追加の参照カウントをデクリメントします。 それ以外の場合、IoFreeMdl の後続の呼び出しでは、これらのプール ページの参照カウントが 1 ではなく 2 になるため、チェックバグが発生します。 次のコード例は、この場合の MmUnlockPages、 IoFreeMdl、 および IoFreeIrp 呼び出しを示しています。
if (((DeviceObject->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) &&
(Irp->MdlAddress != NULL))
{
MmUnlockPages(Irp->MdlAddress);
}
IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);
要件
要件 | 値 |
---|---|
対象プラットフォーム | ユニバーサル |
Header | wdm.h (Wdm.h、Ntddk.h、Ntifs.h を含む) |
Library | NtosKrnl.lib |
[DLL] | NtosKrnl.exe |
IRQL | IRQL <= APC_LEVEL |
DDI コンプライアンス規則 | ForwardedAtBadIrqlFsdAsync(wdm)、 HwStorPortProhibitedDDIs(storport)、 IoBuildFsdComplete(wdm)、 IoBuildFsdForward(wdm)、 IoBuildFsdFree(wdm) |