windows驱动学习之路——文件系统驱动之SFilter框架
、基本概念
文件系统的设备对象:
像FAT32、NTFS这样的文件系统(FS),主要分成两类设备。
1、首先文件系统驱动本身往往生成一个控制设备(CDO),这个设备的主要任务是修改整个驱动的内部配置。
一般一个文件系统只对应一个CDO。
2、文件系统的卷设备。
这里要先说卷设备,一般一个卷(真正的卷设备)对应一个逻辑盘。
“C:“是设备的符号链接名,而不是真正的设备名。 它对应的设备名为”\Device\HarddiskVolume1”。
这个是卷管理器生成的。
但是当有一个卷使用了某种文件系统时,则该文件系统会对应地为该设备生成一个没有名字的设备对象,就是文件系统的卷设备。
文件系统变动回调:
当系统中有任何文件系统被**或者被注销时,注册过的回调函数会被调用。
文件系统的**:
当系统中没有任何卷采用了NTFS文件系统时,Windows并没有加载NTFS文件系统驱动,此时可以称为NTFS未**。
当一个新的使用了NTFS的卷被加载系统中时,则NTFS就被加载了,此时可以说NTFS被**。
第二次再加载新的NTFS的卷时就和文件系统**没什么关系了,因为对应的文件系统已经被**在系统中。
当文件系统的**相反的过程则称为文件系统的卸载
卷挂载和解挂载:
一个新的存储媒质被系统发现并在文件系统中生成一个卷的过程称为挂载,与之相反的过程被称为解挂载。
文件系统识别器:
文件系统驱动的一个很小的替身。为了避免没有使用到的文件系统驱动占据内核内存,windows系统不加载
这些大驱动,而以该文件系统驱动对应的文件系统识别器来代替。当新的物理存储媒介进入系统后,IO管理器会依次尝试各种文件系统对它进行"识别",若识别成功,则立即加载真正的文件系统驱动,对应的文件系统识别器则被卸载掉。
文件系统识别器的控制设备看起来就像一个文件系统控制设备,绑定它也许会带来问题,也许不会。有时跳过是最简单的办法,有时或许又有特别的需求需要绑定,但无论如何都必须有判断的方法。
二、整体流程
1、生成一个控制设备,此前必须给控制设备指定名称(\FileSystem\Filters\username),用来与外界的通信接口(现在还用不到,预留)
2、设置普通分发函数。
3、设置快速IO分发函数。
4、使用IoRegisterFsRegistrationChange调用注册这个回调函数。
5、编写一个文件系统变动回调函数,在其中绑定刚**的文件系统控制设备。
6、处理文件系统控制请求(IRP主功能号为IRP_MJ_FILE_SYSTEM_CONTROL),在其监控卷设备的Mount(次版本号IRP_MN_MOUNT_VOLUME)绑定文件系统的卷设备和Dismount(FsControlCode == FSCTL_DISMOUNT_VOLUME)。
该图仅表现出新卷挂载的情况。对于已经挂载的卷设备,在文件系统变动回调的最后,遍历已挂载卷设备然后绑定。(来自https://www.52pojie.cn/forum.php?mod=viewthread&tid=870204&extra=page%3D1%26filter%3Dtypeid%26typeid%3D34)
注意要点
1、文件系统驱动是针对每个卷生成一个设备对象,而不是针对每个文件的。
对文件读写的IRP,都发到卷设备对象上了。
2、发送给控制设备的请求(IRP)一般是文件系统控制IRP(主功能号IRP_MJ_FILE_SYSTEM_CONTROL)。
而发送给卷设备的IRP一般都是文件操作IRP,控制设备的IRP一般用来捕获卷设备的生成信息。
最终目标是为了绑定文件系统的卷设备,但前提是先绑定文件系统控制设备。
3、需要为驱动对象写另一组快速IO分发函数,这组函数的指针在driver->FastIoDispatch中,而且这里本来是没有空间的,所以为了保存这一组指针,必须自己分配空间。
快速IO分发函数必须在非分页内存空间中(ExAllocatePoolWithTag(NonPagePool, *))。
文件系统过滤驱动,如果不设置,上层依然会调用,而且会导致蓝屏。
4、IoRegisterFsRegistrationChange可以注册对**文件系统的回调,但是对调用这个函数时,早就已经**的文件系统,
回调是否会被调用?
早期windows版本 2000是不会调用的。
windows2000sp4/xp是会被调用的,让注册变动回调的人以为所有的已存在文件系统会重新"**"一次。
5、必须要跳过文件系统识别器。
6、文件系统卷设备的绑定,irpSp->Parameters.MountVolume.Vpb
指向一个被挂载的卷的卷参数块的指针。支持可移动介质的文件系统,可能替换掉预先传入的这个参数。
再这样的文件系统上,在卷被挂载之后,这个指针可能不再有效。过滤这种文件系统的过滤驱动必须按下面的方法使用这个参数。
在把IRP发送到下层驱动之前,保存irpSp->Parameters.MountVolume.Vpb->RealDevice的值。
在这个卷被成功挂载之后,过滤驱动可以用这个存储设备的指针重新获得正确的VPB指针,irpSp->Parameters.MountVolume.Vpb->DeviceObject才是需要绑定的设备对象。
7、对于已经附加过过滤设备的卷设备,不要二次附加。
从寒江独钓windows内核编程书中提取出来的。