




已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
文件系统驱动文件系统驱动主要生成两类设备:文件系统控制设备,文件系统的卷设备文件系统控制设备:主要任务是修改整个驱动的内部配置文件系统的卷设备:一个卷对应一个逻辑盘发送给控制设备的请求(IRP),一般是文件系统控制IRP(主功能号为IRP_MJ_FILE_SYSTEM_CONTROL);发送给卷设备的IRP一般则是文件操作IRP。过滤的目标最终是为了得到文件操作的IRP,但是控制设备的IRP,一般用来捕获卷设备的生成信息,所以我们要先绑定文件系统的控制设备,达到绑定文件系统的卷设备的目的(1)生成自己的一个控制设备,当然必须给控制设备指定名称(2)设置普通分发函数(3)设置快速IO分发函数(4)编写一个文件系统变动回调函数,在其中绑定刚激活的文件系统控制设备(动态绑定)(5)使用IoRegisterFsRegistrationChange调用注册这个回调函数文件系统控制设备的绑定过滤设备扩展typedefstruct_SFILTER_DEVICE_EXTENSIONULONGTypeFlag;/绑定的文件系统设备(真实设备)/PDEVICE_OBJECTAttachedToDeviceObject;/与文件系统设备相关的真实设备(磁盘),这个在绑定时使用/PDEVICE_OBJECTStorageStackDeviceObject;/如果绑定了一个卷,那么这是物理磁盘卷名;否则这是绑定的控制设备名/UNICODE_STRINGDeviceName;/用来保存名字字符串的缓冲区/WCHARDeviceNameBufferMAX_DEVNAME_LENGTH;/Theextensionusedbyotheruser./UCHARUserExtension1;SFILTER_DEVICE_EXTENSION,*PSFILTER_DEVICE_EXTENSION;绑定文件系统控制设备SfAttachToFileSystemDevice文件系统控制设备已经被绑定,绑定的目的是为了获得发送给文件系统控制设备的文件系统控制请求。这些IRP的主功能号是IRP_MJ_FILE_SYSTEM_CONTROL,每个主功能号下一般都有次功能号从这些控制IRP中能得到足够的信息,确定一个卷被挂载,这样才有可能去绑定文件系统的卷设备当有卷被挂载或解挂载时,SfFsControl()就会被系统回调。现在的任务是在这个函数中获得卷设备的相关信息并对它实行绑定,才能捕获各种针对文件的IRP,从而获得临控各种文件操作的能力主功能号为IRP_MJ_FILE_SYSTEM_CONTROL时,有以下几个不同次功能号的IRP要处理(1)次功能号为IRP_MN_MOUNT_VOLUME,说明一个卷被挂载,应该调用SfFsControlMountVolume来绑定一个卷(2)次功能号为IRP_MN_LOAD_FILE_SYSTEM,这个请求比较特殊,它一般出现在文件系统识别器要求加载真正的文件系统时,此时说明前面绑定了一个文件系统识别器,现在应该在这里开始绑定真正的文件系统控制设备了(3)次功能号为IRP_MN_USER_FS_REQUEST,此时可以从irpSp-Parameters.FileSystemControl.FsControlCode得到一个控制码。当控制码为FSCTL_DISMOUNT_VOLUME时,说明是一个磁盘在解挂载(1)生成一个控制设备。当然此前必须给控制设备指定名称(2)设置分发函数和快速IO分发函数(3)编写一个文件系统变动回调函数,在其中绑定刚激活的文件系统的控制设备,并注册这个回调函数(4)编写默认的分发函数(5)处理文件系统控制请求(IRP主功能号为IRP_MJ_FILE_SYSTEM_CONTROL),在其中监控卷设备的Mount和Dismount文件系统卷设备的绑定从IRP中获得VPB指针:指针irpSp-Parameters.MountVolume.Vpb是一个VPB,VPB是卷参数(VolumeParameterBlock),一个重要的数据结构,它在这里的主要作用是把实际存储媒介设备对象和文件系统上的卷设备对象联系起来下面的代码用VPB来做一下倒手工作,首先,从irpSp中获得文件系统卷设备的VPB,然后从VPB中获得一个存储设备对象storageStackDeviceObject=irpSp-Parameters.MountVolume.Vpb-RealDevice以后可以从这个存储设备对象再得到原来的VPB。这里记下存储设备,实际上是为了从存储设备对象找回VPB,再找回文件系统卷设备。为什么要进行上面的倒手工作?这里的IRP是一个Mount请求,而文件系统卷设备对象实际上是这个请求完成之后才可用。因此,在这个请求还没完成之前irpSp-Parameter.MountVolume.Vpb-DeviceObject是没有意义的,必须等这个IRP完成后irpSp-Parameter.MountVolume.Vpb-DeviceObject才是需要绑定的设备对象但是这个IRP传递过程中,irpSp-Parameter.MountVolume.Vpb可能被修改。换句话说,有可能IRP完成之后,这个指针就已经不是原来那个了,对这种情况的处理,WDK文档有如下说明:IrpSp-Parameter.MountVolume.Vpb指向一个被挂载的卷参数块(VPB)的指针。支持可移动介质的文件系统,可能替换掉预先传入的这个参数。在这样的文件系统上,在卷被挂载之后,这个指针可能不再有效。过滤这种文件系统的过滤驱动必须按下面的方法使用这个参数:在把IRP发送到下层驱动之前,保存IrpSp-Parameter.MountVolume.Vpb-RealDevice的值。这个卷被成功挂载之后,过滤驱动可以用这个存储设备的指针重新获得正确的VPB指针。为此,必须先获得IrpSp-Parameter.MountVolume.Vpb-RealDevice的值保存起来,等待IRP完成之后,再从RealDevice中去获得那个VPB设置完成函数并等待IRP完成SfFsControlMountVolume完成函数相应实现SfFsControlCompletion绑定卷的实现:在SfFsControlMountVolume,调用ExInitializeWorkItem实现SfFsControlMountVolumeCompleteWorkerVOIDSfFsControlMountVolumeCompleteWorker(INPFSCTRL_COMPLETION_CONTEXTContext)ASSERT(Context!=NULL);SfFsControlMountVolumeComplete(Context-DeviceObject,Context-Irp,Context-NewDeviceObject);ExFreePoolWithTag(Context,SFLT_POOL_TAG);SfFsControlMountVolumeComplete-SfAttachMountedDevice-SfAttachDeviceToDeviceStack经过上面操作,我们就完成了:文件系统设备对象的创建文件系统分发函数的分配文件系统控制设备的绑定文件系统卷设备的绑定文件读/写操作的过滤设置一个读处理函数:DriverObject-MajorFunctionIRP_MJ_READ=SfRead;设备对象的区分处理:如何判断?绑定Volume的代码已经在设备扩展中设置了域StorageDev,如果不是(比如控制设备的绑定就没设置过),那么判断StorageDev中是否为空,就可以知道这是否是一个文件系统卷设备。由此可见,过滤设备上的设备扩展是非常有用的,实际上,就是用来在绑定时保存任意信息,将来在过滤时能得到这些信息的一个上下文PSFILTER_DEVICE_EXTENSIONdevExt=DeviceObject-DeviceExtension;if(devExt-StorageDev!=NULL).解析读请求中的文件信息:(1)被操作的是哪个文件IRP当前栈空间下有一个文件对象指针,指向一个文件对象,从文件对象中可以得到文件对象的名字,不过在读操作的过程中去获得这个文件对象的名字是很不合理的(2)读文件的偏移量PIO_STACK_LOCATIONirpsp=IoGetCurrentIrpStackLocation(irp);LARGE_INTEGERoffset;ULONGlength;offset.QuadPart=irpsp-Parameters.Read.ByteOffset.QuadPart;(3)读取的文件的长度length=irpsp-Parameters.Read.Length;如果是写操作,则偏移量和长度为:offset.QuadPart=irpsp-Parameters.Write.ByteOffset.QuadPart;length=irpsp-Parameters.Write.Length;读请求的完成如果是读请求,也有几个不同的次功能号,可以用如下的代码得到:PIO_STACK_LOCATIONirpsp=IoGetCurrentIrpStackLocation(irp);UCHARminor_code=irpsp-MinorFunction;主功能号为IRP_MJ_READ,则次功能号为:IRP_MN_NORMALIRP_MN_MDLIRP_MN_MDL_COMPLETE其它操作的过滤文件对象的生存周期从IRP中获得文件对象的指针PIO_STACK_LOCATIONirpsp=IoGetCurrentIrpStackLocation(irp);PFILE_OBJECTfile_obj=irpsp-FileObject;文件对象是在主功能号为IRP_MJ_CREATE的IRP完后之后诞生的,并在主功能号为IRP_MJ_CLOSE的IRP完成之后被销毁的文件的打开和关闭对于一个已经存在的文件对象,判断是目录还是文件?一般的做法是在生成(或者打开)成功时捕获这个信息,并记录在一个哈希表中,这时读者得写一个用来表示哈希表的数据结构。当然为了简便也可以完全不用哈希表,而是简单地使用链表甚至数组,只是注意保证操作时的多线程安全性,把所有认为是目录的文件对象放到一个集合里,那么在以后的过滤中,要判断一个文件对象是否是目录,只要判断它是否在这个集合中即可文件的删除window对文件的删除操作,第一步是发送一个请求打开文件,打开文件时必须设置为有删除的访问权限:如果打开失败,则直接导致无法删除文件。第二步是发出一个设置请求(主功能号是IRP_MJ_SET_INFORMATION),表示这个文件将被删除。第三步是关闭文件,关闭文件时被系统删除。路径过滤的实现取得文件路径的三种情况:(1)在文件打开之前从打开文件的请求中提取路径。换句话说,这个文件并不一定真实存在,只是windows在试图去打开(或者生成)某个文件了,也就是从FileObject-FileName中提取文件路径。(2)在文件打开IRP处理结束后获取路径。(3)在文件过滤其他IRP时(如改名,查询,设置,读,写),得到文件对象所对应的文件路径。把sfilter编译成一个静态链接库TARGETNAME=sfilterTARGETPATH=objTARGETTYPE=LIBRARYDRIVERTYPE=FSSOURCES=sfilter.c#include “HelloWDM.h”#include “FastIO.h”extern “C” NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) / 定义一个Unicode 字符串。 UNICODE_STRING nameString; UNICODE_STRING dosNameLink; PDEVICE_OBJECT gSFilterControlDeviceObject; PDEVICE_OBJECT FilterDevice; RtlInitUnicodeString(&nameString, L”FileSystemFiltersSFilter” ); / 生成控制设备 NTSTATUS status = IoCreateDevice( DriverObject, 0, &nameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &gSFilterControlDeviceObject ); / 如果因为路径没找到而生成失败 if (status = STATUS_OBJECT_PATH_NOT_FOUND) / 这是因为一些低版本的操作系统没有FileSystemFilters这个目录 / 如果没有,我们则改变位置,生成到FileSystem下. RtlInitUnicodeString( &nameString, L”FileSystemSFilterCDO” ); status = IoCreateDevice( DriverObject, 0, &nameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &gSFilterControlDeviceObject ); / 成功后,用KdPrint 打印一个log. if (!NT_SUCCESS( status ) KdPrint( “SFilter!DriverEntry: Error creating control device object ”%wZ”, status=%08xn”, &nameString, status ); return status; else if (!NT_SUCCESS( status ) / 失败也打印一个。并直接返回错误 KdPrint( “SFilter!DriverEntry: Error creating control device object ”%wZ”, status=%08xn”, &nameString, status ); /安装分发函数 for (int i=0; iMajorFunction= SfPassThrough; DriverObject-MajorFunctionIRP_MJ_CREATE = FsDeviceCreate; DriverObject-MajorFunctionIRP_MJ_CLOSE = FsDeviceClose; DriverObject-MajorFunctionIRP_MJ_CLEANUP = FsDeviceClose; DriverObject-DriverUnload = DriverUnload; /创建连接名 RtlInitUnicodeString(&dosNameLink, L”DosDevicesSFilter”); status = IoCreateSymbolicLink(&dosNameLink, &nameString); if (!NT_SUCCESS(status) KdPrint(“IoCreateSymbolicLink:Error Create cdo, status = %08xn”, status); return status; /Fast IO InitFastIo(DriverObject); /准备绑定C:设备 RtlInitUnicodeString(&nameString, L”DosDevicesC:”); if (!AttachToDiskDevice(&nameString, &FilterDevice) KdPrint(“DrierEntry Failed.n”); IoDeleteDevice(FilterDevice); return STATUS_DEVICE_CONFIGURATION_ERROR; return status;extern “C” NTSTATUS FsDeviceCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); if (g_CDO = DeviceObject) KdPrint(“CDO Created!n”); Irp-IoStatus.Information = 0; Irp-IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; return SfPassThrough(DeviceObject, Irp);extern “C” NTSTATUS FsDeviceClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) if (g_CDO = DeviceObject) KdPrint(“CDO Closed!n”); Irp-IoStatus.Information = 0; Irp-IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; return SfPassThrough(DeviceObject, Irp);extern “C” NTSTATUS SfPassThrough(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); /不处理 /ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject); if (g_CDO = DeviceObject) KdPrint(“ERROR CDO:%08xn”), irpSp-MajorFunction, irpSp-MinorFunction); _asm int 3; Irp-IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp-IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(PDEVICE_EXTENSION)DeviceObject-DeviceExtension)-AttachedToDevice, Irp);/挂载到指定的磁盘设备extern “C” BOOLEAN AttachToDiskDevice(IN PUNICODE_STRING pDiskName, OUT PDEVICE_OBJECT *pOurDevice) NTSTATUS status; PDEVICE_EXTENSION DevEx; PDEVICE_OBJECT DiskDeviceObject; PDEVICE_OBJECT NewDeviceObject; IO_STATUS_BLOCK ioStatus; OBJECT_ATTRIBUTES objectAttributes; PFILE_OBJECT fileObject = NULL; HANDLE ntFileHandle; InitializeObjectAttributes(&objectAttributes, pDiskName, OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwCreateFile(&ntFileHandle, SYNCHRONIZE|FILE_ANY_ACCESS, &objectAttributes, &ioStatus, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, NULL, 0); if (!NT_SUCCESS(status) KdPrint(“FileMon: Could not open driven”); return FALSE; KdPrint(“Open Device is OKn”); status = ObReferenceObjectByHandle(ntFileHandle, FILE_READ_DATA, NULL, KernelMode, (PVOID *)&fileObject, NULL); if (!NT_SUCCESS(status) KdPrint(“Filemon: Could not get fileobject from handlen”); ZwClose(ntFileHandle); return FALSE; DiskDeviceObject =IoGetRelatedDeviceObject(fileObject); if (!DiskDeviceObject) KdPrint(“Filemon: Could not get related device objectn”); goto ErrHand; status = IoCreateDevice(g_CDO-DriverObject, sizeof(DEVICE_EXTENSION), NULL, DiskDeviceObject-DeviceType, FILE_DEVICE_SECURE_OPEN, FALSE, &NewDeviceObject); if(!NT_SUCCESS(status) goto ErrHand; NewDeviceObject-Flags &= DO_DEVICE_INITIALIZING; *pOurDevice = NewDeviceObject; DevEx = (PDEVICE_EXTENSION)NewDeviceObject-DeviceExtension; DevEx-AttachedToDevice = DiskDeviceObject; DevEx-DeviceName.Length = 0; DevEx-DeviceName.MaximumLength = sizeof(DevEx-DeviceNameBuffer); DevEx-DeviceName.Buffer = DevEx-DeviceNameBuffer; SfGetObjectName(g_CDO, &(DevEx-DeviceName); /执行挂载 DevEx-AttachedToDevice = IoAttachDeviceToDeviceStack(NewDeviceObject, DiskDeviceObject); if (!DevEx-AttachedToDevice) goto ErrHand; KdPrint(“Attach Device is OKn”); ObDereferenceObject(fil
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 云南“美美与共”民族中学联盟联考(一)高二物理-答案
- 陕西省延安市富县2024-2025学年八年级(下)期末物理试卷(含答案)
- 代为办理退休手续协议5篇
- 广东省惠州市惠阳区第四中学2025-2026学年八年级上学期9月月考地理试卷(含答案)
- 安徽省阜阳市临泉田家炳实验中学(临泉县教师进修学校)2025-2026学年高二上学期9月月考历史试题(含答案)
- 2025-2026学年河北省石家庄市桥西区联邦外国语学校八年级(上)开学数学试卷(含部分答案)
- 印刷厂产品质量抽检办法
- 艺术留学咨询申请方案
- 购房销售合同5篇
- 手卫生操作培训课件
- 2025至2030全球及中国护理教育行业项目调研及市场前景预测评估报告
- 培训课件的字体版权
- 注塑加工项目可行性研究报告
- 中医治未病课件版
- 痛风中医辨证论治课件
- 【课件】工作危害分析法(JHA)专项培训课件丨
- 2025-2030年中国礼品盒行业市场现状供需分析及投资评估规划分析研究报告
- 带储热的液态空气储能系统性能的多维度剖析与优化策略
- 水体环境完整版本
- 新北师大版四年级数学上册第二单元(线与角)课后练习题及答案1
- DB1311T 091-2025 旧水泥混凝土路面多锤头碎石化施工技术规范
评论
0/150
提交评论