旧筛选器驱动程序移植指南

鼓励开发人员将旧筛选器驱动程序移植到筛选器管理器模型,以便为其筛选器驱动程序获取更好的功能,并提高系统的可靠性。 经验丰富的开发人员会发现,将旧版筛选器驱动程序移植到微筛选器驱动程序相对简单。 Microsoft 筛选器驱动程序开发人员建议采用以下方法:

  • 从可靠的回归测试套件开始,验证旧筛选器驱动程序和移植微筛选器驱动程序之间的行为。

  • 创建微筛选器驱动程序 shell,并将功能从旧筛选器驱动程序系统上移至微筛选器驱动程序。 例如,获取连接工作,然后一次处理一个操作,每次操作后测试一次。

  • 更改用户模式/内核模式通信最后,以便您可以使用现有工具来测试微筛选器驱动程序。

  • 在启用了驱动程序验证器中的筛选器验证程序 i/o 验证选项的情况 PREfast 的情况编译和测试。

在迁移过程中,应查看所有旧筛选器驱动程序代码,以充分利用筛选器管理器功能。 具体而言,请记住以下事项:

  • 基于 IRP 的 i/o 和快速 i/o 操作可以在适当的时候执行相同的操作,这有助于减少代码重复。

  • 在注册操作时,微筛选器驱动程序可以明确选择忽略所有分页 i/o 和缓存 i/o,这样就无需对代码进行检查。

  • 实例通知可大大简化附加/分离逻辑。

  • 仅注册微筛选器驱动程序必须处理的操作;您可以忽略其他所有内容。

  • 利用筛选器管理器上下文和名称管理支持。

  • 利用筛选器管理器对发出非递归 i/o 的支持。

  • 与旧版筛选器驱动程序不同,微筛选器驱动程序不能依赖于本地变量来维护从 preoperation 处理到 postoperation 处理的上下文。 请考虑分配后备链表列表以存储操作状态。

  • 请确保在使用名称或上下文完成后释放引用。

  • 用户模式下的完成端口添加了一种用于生成队列的强大技术。 您可能只需要与单个命名端口建立单一连接。

下表列出了旧筛选器驱动程序中的常见操作以及它们如何映射到筛选器管理器模型。

旧筛选器驱动程序模型 筛选器管理器模型

无完成例程的传递操作

如果你的微筛选器驱动程序绝不能处理此类型的 i/o 操作,则不要为此操作注册 preoperation 或 postoperation 回调例程。

否则,请从为此操作注册的 preoperation 回调例程返回 FLT_PREOP_SUCCESS_NO_CALLBACK。

请参阅 返回 FLT_PREOP_SUCCESS_NO_CALLBACK

使用完成例程传递操作

从 preoperation 回调例程返回 FLT_PREOP_SUCCESS_WITH_CALLBACK。

请参阅 返回 FLT_PREOP_SUCCESS_WITH_CALLBACK

Preoperation 回调例程中的挂起操作

根据需要调用 FltLockUserBuffer ,以确保所有用户缓冲区均已正确锁定,以便可以在工作线程中访问它们。

通过调用 FltAllocateDeferredIoWorkItemFltQueueDeferredIoWorkItem等支持例程,将工作排队到工作线程中。

从 preoperation 回调例程返回 FLT_PREOP_PENDING。

准备好将 i/o 操作返回到筛选器管理器后,请调用 FltCompletePendedPreOperation

请参阅 在 Preoperation 回调例程中挂起 I/o 操作

Postoperation 回调例程中的挂起操作

在 preoperation 回调例程中调用 FltLockUserBuffer ,以确保已正确锁定用户缓冲区以便可以在工作线程中访问它们。

通过调用 FltAllocateGenericWorkItemFltQueueGenericWorkItem等支持例程,将工作排队到工作线程中。

从 postoperation 回调例程返回 FLT_POSTOP_MORE_PROCESSING_REQUIRED。

准备好将 i/o 操作返回到筛选器管理器后,请调用 FltCompletePendedPostOperation

请参阅 在 Postoperation 回调例程中挂起 I/o 操作

同步操作

从 preoperation 回调例程返回 FLT_PREOP_SYNCHRONIZE。

请参阅 返回 FLT_PREOP_SYNCHRONIZE

在 preoperation 回调例程中完成操作

在操作的FLT_CALLBACK_DATA结构的IoStatus成员中设置最终操作状态和信息。

从 preoperation 回调例程返回 FLT_PREOP_COMPLETE。

请参阅 在 Preoperation 回调例程中完成 I/o 操作

在 preoperation 回调例程中挂起操作后完成该操作

在操作的FLT_CALLBACK_DATA结构的IoStatus成员中设置最终操作状态和信息。

从处理 i/o 操作的工作线程调用 FltCompletePendedPreOperation ,将 FLT_PREOP_COMPLETE 传递为 CallbackStatus 参数。

请参阅 在 Preoperation 回调例程中完成 I/o 操作

完成完成例程中的所有完成工作

从 postoperation 回调例程返回 FLT_POSTOP_FINISHED_PROCESSING。

请参阅 编写 Postoperation 回调例程

在安全 IRQL 上完成工作

从 postoperation 回调例程调用 FltDoCompletionProcessingWhenSafe

请参阅确保以保险箱 IRQL 执行完成处理

向完成例程通知事件

从此操作的 preoperation 回调例程返回 FLT_PREOP_SYNCHRONIZE。

筛选器管理器将在与 preoperation 回调例程相同的线程上下文中调用 postoperation 回调例程,以 IRQL < = APC_LEVEL。

请参阅 返回 FLT_PREOP_SYNCHRONIZE

未能成功创建操作

从 postoperation 回调例程调用 FltCancelFileOpen ,以进行创建操作。

在操作FLT_CALLBACK_DATA结构的IoStatus成员中设置相应的错误 NTSTATUS 值。

返回 FLT_POSTOP_FINISHED_PROCESSING。

请参阅 Postoperation 回调例程中的 I/o 操作失败

通过 i/o 操作的快速 i/o 路径禁止 i/o

从 preoperation 回调例程返回 FLT_STATUS_DISALLOW_FAST_IO 操作。

请参阅 在 Preoperation 回调例程中禁用快速 I/o 操作

修改 i/o 操作的参数

在操作的FLT_CALLBACK_DATA结构的Iopb成员中设置修改后的参数值。

调用 FltSetCallbackDataDirty,将 FLT_CALLBACK_DATA 结构标记为已更新,除非修改了 FLT_CALLBACK_DATA 结构的 IoStatus 成员的内容。

请参阅 修改 I/o 操作的参数

锁定操作的用户缓冲区

使用在 访问 I/o 操作的用户缓冲区中所述的技术和指导原则。