参考了山寨ntfs源码和寒江做点笔记
看了ntfs.sys 的源码,好像在在次功能号 IRP_MN_MOUNT_VOLUME 中虽然创建了设备,但是并不是用用 attach 系列函数挂到卷设备上,而是初始化一个vcb结构。
/////////////////////////////////////////////
mountvolume()
{
DeviceObjectWeTalkTo = IrpSp->Parameters.MountVolume.DeviceObject; //这个是 真正卷设备卷设备
Vpb = IrpSp->Parameters.MountVolume.Vpb; //这个是 真正卷设备卷设备的vpb
Vpb->DeviceObject = (PDEVICE_OBJECT)VolDo;
//VolDo是我们ntfs创建的设备,它本身是一个vdo结构,不过第一个字段是设备对象
NtfsInitializeVcb( IrpContext, Vcb, DeviceObjectWeTalkTo, Vpb );
}
///////////////////////////////////
NtfsInitializeVcb( IrpContext, Vcb, DeviceObjectWeTalkTo, Vpb )
{
Vcb->TargetDeviceObject = TargetDeviceObject;//真正卷设备
Vcb->Vpb = Vpb;//这个 是 真正卷设备卷设备的vpb
}
可以看出ntfs把卷设备记录在 Vcb->TargetDeviceObject 中,以后的读写就会直接拿出来,然后 iocalldriver 下去。不过在这之前,会先把读写偏移转换成对应卷的偏移再传 ,符合下面一句话。另外, ntfs 生成的设备中的 vpb 是空的,而卷设备的vpb是有用的
(文件系统负责文件路径 -> 卷上某个扇区的解析,
卷管理器负责卷上某个扇区-> 具体扇区的解析 )
===========================================================
而关于卷
卷 diskvolume 1的 deviceobject=0x896dfc08
vpb=0x89737350
lkd> dt nt!_vpb 0x89737350
+0x000 Type : 10
+0x002 Size : 88
+0x004 Flags : 1
+0x006 VolumeLabelLength : 0
+0x008 DeviceObject : 0x896c2020 _DEVICE_OBJECT ntfs对应创建的设备( 或fat
+0x00c RealDevice : 0x896dfc08 _DEVICE_OBJECT 自身
+0x010 SerialNumber : 0x1885de47
+0x014 ReferenceCount : 0xbd2
+0x018 VolumeLabel : [32] 0
============================================================================
基于上面的知识,理解寒江中attach到ntfs生成的设备原理(事先已经attach到cdo上面)
当拦截到 IRP_MN_MOUNT_VOLUME时,由于ntfs的cdo在我们下面,所以
Vpb->DeviceObject = (PDEVICE_OBJECT)VolDo;这还没能执行( Vpb->DeviceObject的值无效,vpb是irp中的mount的)
不过 Vpb-> RealDevice 是真正卷设备(eg device/HarddiskVolumeX)的值且已经有效了,先把这个值记录下来。然后把这个irp往下传
让ntfs完成它自身的绑定,例如执行上面的 mountvolume(), NtfsInitializeVcb( IrpContext, Vcb, DeviceObjectWeTalkTo, Vpb );
当这个irp完成的时候。再取 Vpb-> RealDevice->vpb-> DeviceObject 便是ntfs生成的设备了,此时便可绑定。 done!
ps:在注册文件系统回调的时候有点乱,
ntfs中有IoRegisterDriverReinitialization(),IoRegisterFileSystem(),
寒江里面IoRegisterFsRegistrationChange(),
这些啥意思,都怎么区别,求牛人解。谢谢。。。