操作前コールバック ルーチン内でユーザー バッファーへアクセスする

ミニフィルター ドライバーの操作前コールバック ルーチンは、IRP ベースの I/O 操作でバッファーを次のように処理する必要があります。

  • バッファーに MDL が存在するかどうかを確認します。 MDL ポインターは、操作用の FLT_PARAMETERSMdlAddress パラメーターまたは OutputMdlAddress パラメーターにあります。 ミニフィルター ドライバーでは、FltDecodeParameters を呼び出して MDL ポインターのクエリを実行できます。

    有効な MDL を取得する 1 つの方法は、コールバック データ内の I/O パラメーター ブロック FLT_IO_PARAMETER_BLOCKMinorFunction メンバー内で 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 がない場合は、バッファー アドレスを使用してバッファーにアクセスします。 ユーザー空間バッファー アドレスが確実に有効になるようにするために、ミニフィルター ドライバーでは、ProbeForReadProbeForWrite などのルーチンを使用して、try/except ブロック内のすべてのバッファー参照を囲む必要があります。

操作前コールバック ルーチンでは、高速 I/O 操作でバッファーを次のように処理する必要があります。

  • バッファー アドレスを使用してバッファーにアクセスします (高速 I/O 操作では MDL を使用できないため)。

  • ユーザー空間バッファー アドレスが確実に有効になるようにするために、ミニフィルター ドライバーでは、ProbeForReadProbeForWrite などのルーチンを使用して、try/except ブロック内のすべてのバッファー参照を囲む必要があります。

高速 I/O または IRP ベースにできる操作の場合は、バッファー参照を try/except ブロックで囲む必要があります。 バッファー I/O を使用する IRP ベースの操作ではこれらの参照を囲む必要がありませんが、try/except ブロックは安全対策です。