操作前コールバック ルーチン内でユーザー バッファーへアクセスする
ミニフィルター ドライバーの操作前コールバック ルーチンは、IRP ベースの I/O 操作でバッファーを次のように処理する必要があります。
バッファーに MDL が存在するかどうかを確認します。 MDL ポインターは、操作用の FLT_PARAMETERS の MdlAddress パラメーターまたは OutputMdlAddress パラメーターにあります。 ミニフィルター ドライバーでは、FltDecodeParameters を呼び出して MDL ポインターのクエリを実行できます。
有効な MDL を取得する 1 つの方法は、コールバック データ内の I/O パラメーター ブロック FLT_IO_PARAMETER_BLOCK の MinorFunction メンバー内で IRP_MN_MDL フラグを探すことです。 次の例は、IRP_MN_MDL フラグを確認する方法を示しています。
NTSTATUS status; PMDL *ReadMdl = NULL; PVOID ReadAddress = NULL; if (FlagOn(CallbackData->Iopb->MinorFunction, IRP_MN_MDL)) { ReadMdl = &CallbackData->Iopb->Parameters.Read.MdlAddress; }
ただし、IRP_MN_MDL フラグは、読み取り操作と書き込み操作に対してのみ設定できます。 FltDecodeParameters を使用して MDL を取得することをお勧めします。これは、このルーチンが任意の操作に対して有効な MDL を確認するためです。 次の例では、MDL パラメーターのみが返されます (有効な場合)。
NTSTATUS status; PMDL *ReadMdl = NULL; PVOID ReadAddress = NULL; status = FltDecodeParameters(CallbackData, &ReadMdl, NULL, NULL, NULL);
バッファーの MDL が存在する場合は、MmGetSystemAddressForMdlSafe を呼び出してバッファーのシステム アドレスを取得し、このアドレスを使用してバッファーにアクセスします。
前の例の続きとして、次のコードはシステム アドレスを取得します。
if (*ReadMdl != NULL) { ReadAddress = MmGetSystemAddressForMdlSafe(*ReadMdl, NormalPagePriority); if (ReadAddress == NULL) { CallbackData->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; CallbackData->IoStatus.Information = 0; } }
バッファーの MDL がない場合は、バッファー アドレスを使用してバッファーにアクセスします。 ユーザー空間バッファー アドレスが確実に有効になるようにするために、ミニフィルター ドライバーでは、ProbeForRead や ProbeForWrite などのルーチンを使用して、try/except ブロック内のすべてのバッファー参照を囲む必要があります。
操作前コールバック ルーチンでは、高速 I/O 操作でバッファーを次のように処理する必要があります。
バッファー アドレスを使用してバッファーにアクセスします (高速 I/O 操作では MDL を使用できないため)。
ユーザー空間バッファー アドレスが確実に有効になるようにするために、ミニフィルター ドライバーでは、ProbeForRead や ProbeForWrite などのルーチンを使用して、try/except ブロック内のすべてのバッファー参照を囲む必要があります。
高速 I/O または IRP ベースにできる操作の場合は、バッファー参照を try/except ブロックで囲む必要があります。 バッファー I/O を使用する IRP ベースの操作ではこれらの参照を囲む必要がありませんが、try/except ブロックは安全対策です。