読み取り/書き込みディスパッチ ルーチンの概要
DispatchRead、DispatchWrite、または DispatchReadWrite ルーチンを実装する場合は、次の点に注意する必要があります。
IRP で次の下位レベルのドライバーの I/O スタックの場所を設定する前に、有効にするために受信読み取り/書き込み IRP のパラメーターをチェックするには、階層化されたドライバーのチェーン内の最上位レベルのドライバーの責任です。
一般に、中間ドライバーと最下位レベル ドライバーは、チェーン内の最上位レベル ドライバーに依存して、有効なパラメーターを使用して転送要求を渡すことができます。 ただし、どのドライバーでも、IRP の I/O スタックの場所のパラメーターに正気チェックを実行できます。各デバイス ドライバーは、そのデバイスによって課される制限に違反する可能性がある条件のパラメーターをチェックする必要があります。
DispatchReadWrite ルーチンがエラーで IRP を完了する場合は、適切な NTSTATUS の種類の値を持つ I/O スタックの場所の Status メンバーを設定し、Information メンバーを 0 に設定し、IRP と PriorityBoost の IO_NO_INCREMENT を使用して IoCompleteRequest を呼び出す必要があります。
ドライバーがバッファー処理された I/O を使用する場合は、転送するデータを含む構造体を定義する必要があり、これらの構造体の一部を内部でバッファーする必要がある場合があります。
ドライバーが直接 I/O を使用する場合は、Irp->MdlAddress の MDL が 1 回の転送操作で処理する基になるデバイスのデータが多すぎる (またはページ区切りが多すぎる) バッファーを記述するかどうかをチェックする必要がある場合があります。 その場合、ドライバーは、元の転送要求をより小さな転送操作のシーケンスに分割する必要があります。
密接に結合されたクラス ドライバーは、基になるポート ドライバーの DispatchReadWrite ルーチンでこのような要求を分割する場合があります。 これを行うには、特に大容量記憶装置用の SCSI クラス ドライバーが必要です。 SCSI ドライバーの要件の詳細については、「ストレージ ドライバー」を参照してください。
下位レベルのデバイス ドライバーの DispatchReadWrite ルーチンは、別のドライバー ルーチンが IRP をデキューして転送用にデバイスを設定するまで、大きな転送要求を部分的な転送に分割することを延期する必要があります。
下位レベルのデバイス ドライバーは、それ自体のルーチンによる処理のために読み取り/書き込み IRP をキューする場合は、IRP をキューに入れます前に IoMarkIrpPending を呼び出す必要があります。 また、DispatchReadWrite ルーチンは、このような状況で STATUS_PENDING を使用して制御を返す必要があります。
DispatchReadWrite ルーチンが下位ドライバーに IRP を渡す場合は、IRP の次の下位ドライバーの I/O スタックの場所を設定する必要があります。 上位レベルのドライバーが、IoCallDriver で渡す前に IRP の IoCompletion ルーチンも設定するかどうかは、ドライバーの設計と、その下に階層化されたドライバーの設計によって異なります。
ただし、上位レベルのドライバーは、IRP やメモリなどのリソースを割り当てる場合、IoCallDriver を呼び出す前に IoSetCompletionRoutine を呼び出す必要があります。 下位のドライバーが要求を完了したが、IoCompletion ルーチンが元の IRP で IoCompleteRequest を呼び出す前に、その IoCompletion ルーチンはドライバー割り当てリソースを解放する必要があります。
上位レベルのドライバーが基になるリムーバブル メディア デバイス ドライバーを含む可能性がある下位ドライバーの IRP を割り当てる場合、割り当てるドライバーは、割り当てる各 IRP でスレッド コンテキストを確立する必要があります。