看一眼这玩意的官方说明:
IoGetTopLevelIrp 例程返回当前线程的 TopLevelIrp 字段的值。
IoGetTopLevelIrp 可以返回 NULL、任意特定于文件系统的值 (如指向当前 IRP) 的指针,或下表中列出的标志之一。
如果当前线程在文件系统上方没有资源, IoGetTopLevelIrp 将返回 NULL。
如果文件系统是当前线程的顶级组件, IoGetTopLevelIrp 将返回指向当前 IRP 的指针。
如果文件系统以外的组件是当前线程的顶级组件, IoGetTopLevelIrp 将返回以下标志之一:
展开表
标志 含义 FSRTL_FSP_TOP_LEVEL_IRP 这是递归调用。 FSRTL_CACHE_TOP_LEVEL_IRP 缓存管理器是当前线程的顶级组件。 FSRTL_MOD_WRITE_TOP_LEVEL_IRP 修改后的页面编写器是当前线程的顶级组件。 FSRTL_FAST_IO_TOP_LEVEL_IRP 缓存管理器是当前线程的顶级组件,当前线程位于快速 I/O 路径中。
官方的解释对于初次使用这个API 的同学来说非常不好理解,简单理解就是:
如果IoGetTopLevelIrp 返回null,那么这个IRP就是用户模式触发的文件操作,这里的用户模式不是指Ring3应用层的概念,既可以是Ring3层的操作,也可以是用户写的Ring0内核驱动进行ZwCreateFile等的文件操作,反正不是系统内部自己的行为。
有什么用呢?注意,这个API 在MiniFilter文件过滤器开发中用的比较多,目的就是判定一个IRP操作是不是用户发起的,或者用来判断这个IRP是不是MiniFilter发起的循环重入,用法如下:
FLT_PREOP_CALLBACK_STATUS PreOperationCallback(PFLT_CALLBACK_DATA Data)
{
// 若为分页I/O或非用户模式产生的IRP,直接跳过处理
if ((Data->Iopb->IrpFlags & IRP_PAGING_IO) || IoGetTopLevelIrp())
{
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
// 处理用户模式触发的IRP,继续其他逻辑操作
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}