zoukankan      html  css  js  c++  java
  • Windows文件系统过滤驱动开发教程(11)

    11.文件和目录的生成打开,关闭与删除

    我们已经分析了读,写与读类似。文件系统还有其他的操作。比如文件或目录的打开(打开已经存在的或者创建新的),关闭。文件或目录的移动,删除。

    实际上FILE_OBJECT并不仅仅指文件对象。在windows文件系统中,目录和文件都是用FileObject来抽象的。这里产生一个问题,对于一个已经有的FileObject,我如何判断这是一个目录还是一个文件呢?

    对于一个已经存在的FileObject,我没有找到除了发送IRP来向卷设备询问这个FileObject的信息之外更好的办法。自己发送IRP很麻 烦。不是我很乐意做的那种事情。但是FileObject都是在CreateFile的时候诞生的。在诞生的过程中,确实有机会得到这个即将诞生的 FileObject,是一个文件还是一个目录。

    Create的时候,获得当前IO_STACK_LOCATION,假设为irpsp,那么irpsp->Parameters.Create的结构为:

    struct {
    PIO_SECURITY_CONTEXT SecurityContext;
    ULONG Options;
    USHORT FileAttributes;
    USHORT ShareAccess;
    ULONG EaLength;
    };

    这个结构中的参数是与CreateFile这个api中的参数对应的,请自己研究。我先写一些函数包装来方便读取irpsp.

    _inline wd_ulong wd_irpsp_file_opts(wd_irpsp *irpsp)
    {
    return irpsp->Parameters.Create.Options;
    }

    _inline wd_ushort wd_irpsp_file_attrs(wd_irpsp *irpsp)
    {
    return irpsp->Parameters.Create.FileAttributes;
    }

    enum {wd_file_opt_dir = FILE_DIRECTORY_FILE};
    enum {wd_file_attr_dir = FILE_ATTRIBUTE_DIRECTORY};

    然后我们搞清上边Options和FileAttributes的意思。是不是Options里边有FILE_DIRECTORY_FILE标记就表示这 是一个目录?实际上,CreateOpen是一种尝试性的动作。无论如何,我们只有当CreateOpen成功的时候,判断FileObject才有意 义。否则是空谈。

    成功有两种可能,一是已经打开了原有的文件或者目录,另一种是新建立了文件或者目录。Options里边带有FILE_DIRECTORY_FILE表示 打开或者生成的对象是一个目录。那么,如果在Create的完成函数中,证实生成或者打开是成功的,那么返回得到的FILE_OBJECT,确实应该是一 个目录。

    当我经常要使用我过滤时得到的文件或者目录对象的时候,我一般在Create成功的的时候捕获他们,并把他们记录在一个“集合”中。这时你得写一个用来表 示“集合”的数据结构。你可以用链表或者数组,只是注意保证多线程安全性。因为Create的时候已经得到了属性表示FileObject是否是目录,你 就没有必要再发送IRP来询问FileObject的Attribute了。

    对了上边有FileAttributes。但是这个东西并不可靠。因为在生成或者打开的时候,你只需要设置Options。我认为这个字段并无法说明你打开的文件对象是目录。

    这你需要设置一下Create的完成函数。如果设置这里不再重复,请参考上边对文件读操作。

    wd_stat my_create_comp(in wd_dev *dev,
    in wd_irp *irp,
    in wd_void *context)
    {
    wd_irpsp *irpsp = wd_irp_cur_sp(irp);
    wd_file *file = wd_irpsp_file(irpsp);

    UNREFERENCED_PARAMETER(dev);

    if(wd_suc(wd_irp_status(irp))
    {
    // 如果成功了,把这个FileObject记录到集合里,这是一个
    // 刚刚打开或者生成的目录
    if(file &&
    (wd_irpsp_file_opts(irpsp) & wd_file_opt_dir))
    add_obj_to_set(file);
    }
    return wd_irp_status(irp);
    }

    这里顺便解释一下UNREFERENCED_PARAMETER宏。我曾经不理解这个宏的意思。其实就是因为本函数传入了三个参数,这些参数你未必会用 到。如果你不用的话,大家知道c编译器会发出一条警告。一般认为驱动应该去掉所有的警告,所以用了这个宏来“使用”一下没有用到过的参数。你完全可以不用 他们。

    现在所有的目录都被你记录。那么得到一个FileObject的时候,判断一下这个FileObject在不在你的集合里,如果在,就说明是目录,反之是文件。

    当这个FileObject被关闭的时候你应该把它从你的集合中删除。你可以捕获Close的IRP来做这个。记得本教程很早以前,我们已经安装过 my_close函数的来处理IRP(请回忆或者翻阅第3节的内容),那么很简单了,在该函数中从你的集合中删除该FileObject即可。作为保险的 做法,应该观察一下关闭是否成功。如果成功的话,再进行你的从集合中删除元素工作。

    因为判断FileObject是文件还是目录的问题,我们已经见识了文件的打开和关闭工作。现在看一下文件是如何被删除的。

    删除的操作,第一步是打开文件,打开文件的时候必须设置为可以删除。如果打开失败,则直接导致无法删除文件。第二步设置文件属性为用于删除,第三步关闭文件即可。关闭的时候,文件被系统删除。

    不过请注意这里的“删除”并非把文件删除到回收站。如果要测试,你必须按住shift彻底删除文件。文件删除到回收站只是一种改名操作。改名操作我们留到以后再讨论。

    第一步是打开文件,我应该可以在文件被打开的时候,捕获到的irpsp的参数,记得前边的参数结构,中间有:

    PIO_SECURITY_CONTEXT SecurityContext;

    相关的结构如下:

    typedef struct _IO_SECURITY_CONTEXT {
    PSECURITY_QUALITY_OF_SERVICE SecurityQos;
    PACCESS_STATE AccessState;
    ACCESS_MASK DesiredAccess;
    ULONG FullCreateOptions;
    } IO_SECURITY_CONTEXT, *PIO_SECURITY_CONTEXT;

    注意其中的DesiredAccess,其中必须有DELETE标记,才可以删除文件。

    第二步是设置为”关闭时删除”。这是通过发送一个IRP(Set Information)来设置的。捕获主功能码为IRP_MJ_SET_INFORMATION的IRP后:
    首先,IrpSp->Parameters.SetFile.FileInformationClass应该为FileDispositionInformation。

    然后,Irp->AssociatedIrp.SystemBuffer指向一个如下的结构:

    typedef struct _FILE_DISPOSITION_INFORMATION {
    BOOLEAN DeleteFile;
    } FILE_DISPOSITION_INFORMATION;

    如果DeleteFile为TRUE,那么这是一个删除文件的操作。文件将在这个FileObject Close的时候被删除。

    以上的我都未实际调试,也不再提供示例的代码。有兴趣的读者请自己完成。
  • 相关阅读:
    工作中遇到的java 内存溢出,问题排查
    java线上内存溢出问题排查步骤
    性能测试-java内存溢出问题排查
    164 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 04 终止finally执行的方法
    163 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 03 使用多重catch结构处理异常
    162 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 02 使用try-catch结构处理异常
    161 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 01 try-catch-finally简介
    160 01 Android 零基础入门 03 Java常用工具类01 Java异常 03 异常处理简介 01 异常处理分类
    159 01 Android 零基础入门 03 Java常用工具类01 Java异常 02 异常概述 02 异常分类
    158 01 Android 零基础入门 03 Java常用工具类01 Java异常 02 异常概述 01 什么是异常?
  • 原文地址:https://www.cnblogs.com/jasononline/p/1231776.html
Copyright © 2011-2022 走看看