(转载)Windows文件系统过滤驱动开发教程 联系客服

发布时间 : 星期一 文章(转载)Windows文件系统过滤驱动开发教程更新完毕开始阅读1b486c1614791711cc79175f

return;

irpsp = wd_irp_next_sp(irp); wd_irpsp_file_set(irpsp,file);

wd_irp_comp(irp,my_req_comp,context);

请注意wd_irp_next_sp,我是得到了这个irp的下一个IO_STACK_LOCATION,然后我设置了FileObject.接下来应该设置了完成后,我就可以发送请求了!请求发送完毕后,一旦系统完成请求就会调用你的my_req_comp.

再看看my_req_comp如何收场:

wd_stat my_req_comp(in wd_dev *dev, in wd_irp *irp,

in wd_void *context) {

// 请注意,无论成功还是失败,我都得在这里彻底销毁irp wd_irp_send_by_myself_free(irp);

// 返回这个,仅仅是因为irp我已经销毁,不想让系统再次销毁它而已。 return wd_stat_more_processing; }

wd_stat_more_prcessing就是STATUS_MORE_PROCESSING_REQUIRED。之所以返回这个,是因为我已经把irp给删除了。我不想windows系统再对这个irp做什么。所以干脆说我还要继续处理,这样避免了io管理器再去动用这个irp的可能。

最后是那个irp删除函数的代码:

_inline wd_void wd_irp_send_by_myself_free(wd_irp *irp) {

if (irp->MdlAddress) {

MmUnmapLockedPages(MmGetSystemAddressForMdl(irp->MdlAddress), irp->MdlAddress);

MmUnlockPages(irp->MdlAddress); IoFreeMdl(irp->MdlAddress); }

IoFreeIrp(irp); };

因为我自己没有分配过MdlAddress下去过。所以如果下边返回了MDL,我得附带清理它。

好了,祝愿你心情愉快。如果你何我一样懒惰的话,不妨就用上边的简单方法自己发irp来

读文件了。

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的时候被删除。

以上的我都未实际调试,也不再提供示例的代码。有兴趣的读者请自己完成。

本文来自CSDN博客,转载http://blog.csdn.net/joshua_yu/archive/2006/01/30/589981.aspx

请标出处明: