访问预操作回调例程中的用户缓冲区

微筛选器驱动程序的 预操作回调例程 应在基于 IRP 的 I/O 操作中处理缓冲区,如下所示:

  • 检查缓冲区是否存在 MDL。 MDL 指针可以在操作FLT_PARAMETERSMdlAddressOutputMdlAddress 参数中找到。 微筛选器驱动程序可以调用 FltDecodeParameters 来查询 MDL 指针。

    获取有效 MDL 的一种方法是在回调数据中查找 I/O 参数块的 MinorFunction 成员 (FLT_IO_PARAMETER_BLOCK)中的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/ 中。

预操作回调例程应在快速 I/O 操作中处理缓冲区,如下所示:

  • 使用缓冲区地址访问缓冲区 (,因为快速 I/O 操作不能具有 MDL) 。

  • 为了确保用户空间缓冲区地址有效,微筛选器驱动程序必须使用例程(如 ProbeForReadProbeForWrite),将除块之外的所有缓冲区引用包含在 try/ 中。

对于可快速 I/O 或基于 IRP 的操作,所有缓冲区引用都应包含在 try/ 中,块除外。 尽管对于使用缓冲 I/O 的基于 IRP 的操作,你不必将这些引用括起来,但 尝试/块除外 是一种安全的预防措施。