XiangXiangRen
总版主
总版主
  • 注册日期2003-02-22
  • 最后登录2015-09-01
  • 粉丝13
  • 关注0
  • 积分1042分
  • 威望472点
  • 贡献值1点
  • 好评度145点
  • 原创分13分
  • 专家分1分
阅读:3423回复:8

Windows文件系统过滤驱动开发教程(4)

楼主#
更多 发布于:2004-10-21 11:06
Windows文件系统过滤驱动开发教程

4.设备栈,过滤,文件系统的感知

前边都在介绍文件系统驱动的结构,却还没讲到我们的过滤驱动如何能捕获所有发给文件系统驱动的irp,让我们自己来处理?前面已经解释过了设备对象。现在来解释一下设备栈。

任何设备对象都存在于某个设备栈中。设备栈自然是一组设备对象。这些设备对象是互相关联的,也就是说,如果得到一个DO指针,你就可以知道它所处的设备栈。

任何来自应用的请求,最终被windows io mgr翻译成irp的,总是发送给设备栈的顶端那个设备。

原始irp                irp           irp          irp
-------------->      ------>      ------->     ----->
             DevTop         Dev2           ...      DevVolumne ... ???
<--------------      <------      <-------      <-----
原始irp(返回)       irp           irp          irp


上图向右的箭头表示irp请求的发送过程,向左则是返回。可见irp是从设备栈的顶端开始,逐步向下发送。DevVolumue表示我们实际要过滤的Volume设备,DevTop表示这个设备栈的顶端。我们只要在这个设备栈的顶端再绑定一个设备,那发送给Volume的请求,自然会先发给我们的设备来处理。

有一个系统调用可以把我们的设备绑定到某个设备的设备栈的顶端。这个调用是IoAttachDeviceToDeviceStack,这个调用2000以及以上系统都可以用(所以说到这点,是因为还有一个IoAttachDeviceToDeviceStackSafe,是2000所没有的。这常常导致你的filter在2000下不能用。)

我自己写了一个函数来帮我实现绑定功能:

//----------------------wdf.h中的内容----------------------------------
// 这个例程把源设备绑定到目标设备的设备栈中去,并返回源设备所直
//  接绑定的设备。注意源设备未必直接绑定在目标设备上。它应绑定在
//  目标设备的设备栈的顶端。
_inline wd_stat wd_dev_attach(in wd_dev *src,
     in wd_dev *dst,
     in out wd_dev **attached)
{
*attached = dst;
*attached = IoAttachDeviceToDeviceStack(src,dst);
if(*attached == NULL)
return wd_stat_no_such_dev;
return wd_stat_suc;
}


到这里,我们已经知道过滤对Volume的请求的办法。比如“C:”这个设备,我已经知道符号连接为“C:”,不难得到设备名。得到设备名后,又不难得到设备。这时候我们IoCreateDevice()生成一个Device Object,然后调用wd_dev_attach绑定,不是一切ok吗?所有发给“C:”的irp,就必然先发送给我们的驱动,我们也可以捕获所有对文件的操作了!

这确实是很简单的处理方法。我得到的FileMon的代码就是这样处理的,如果不想处理动态的Volume,你完全可以这样做。但是我们这里有更高的要求。当你把一个U盘插入usb口,一个“J:”之类的Volume动态诞生的时候,我们依然要捕获这个事件,并生成一个Device来绑定它。

一个新的存储媒质被系统发现并在文件系统中生成一个Volume的过程称为Mounting.其过程开始的时候,FS的CDO将得到一个IRP,其Major Function Code为IRP_MJ_FILE_SYSTEM_CONTROL,Minor Function Code为IRP_MN_MOUNT。换句话说,如果我们已经生成了一个设备绑定文件系统的CDO,那么我们就可以得到这样的IRP,在其中知道一个新的Volume正在Mount.这时候我们可以执行上边所说的操作。

现在的问题是如何知道系统中有那些文件系统,还有就是我应该在什么时候绑定它们的控制设备。

IoRegisterFsRegistrationChange()是一个非常有用的系统调用。这个调用注册一个回调函数。当系统中有任何文件系统被激活或者是被注销的时候,你注册过的回调函数就会被调用。

//----------------------wdf.h中的内容----------------------------------
wd_stat wdff_reg_notify(
in wd_drv *driver,
in wdff_notify_func func
)
{
return IoRegisterFsRegistrationChange(driver,func);
}

你有必要为此写一个回调函数。

//-------------------我的回调处理函数----------------------------------
wd_void my_fs_notify(
in wd_dev *dev,
in wd_bool active)
{
wd_wchar name_buf[wd_dev_name_max_len];
wd_ustr name;
wd_ustr_init_em(&name,name_buf,wd_dev_name_max_len);

// 如果注册了,就应该得到通知
wd_printf0("notify: a file sys have been acitved!!! \r\n");

// 得到文件系统对象的名字,然后打印出来
wd_obj_get_name(dev,&name);
wd_printf0("notify : file sys name = %wZ\r\n",&name);

if(active)
{
wd_printf0("notify: try to attach.\r\n");
// ... 请在这里绑定文件系统的控制设备
}
else
{
wd_printf0("notify: unactive.\r\n");
// ...
}
}

应该如何绑定一个文件系统CDO?我们在下面的章节再详细描述。

现在我们应该再在wd_main函数中加上下边的内容:

if(wdff_reg_notify(driver,my_fs_notify) != wd_stat_suc)
{
wd_printf0("error: reg notify failed.\r\n");
wd_fio_disp_release(driver);
wd_dev_del(g_cdo);
g_cdo = wd_null;
return wd_stat_insufficient_res;
};

wd_printf0("success: reg notify ok.\n");

我们再次回顾一下,wd_main中,应该做哪些工作。

a.生成一个控制设备。当然此前你必须给控制设置指定名称。

b.设置Dispatch Functions.

c.设置Fast Io Functions.

d.编写一个my_fs_notify回调函数,在其中绑定刚激活的FS CDO.

e.使用wdff_reg_notify调用注册这个回调函数。

最新喜欢:

yuanycyuanyc forgetalexforget...
king-z
驱动牛犊
驱动牛犊
  • 注册日期2004-10-12
  • 最后登录2008-08-05
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望3点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-10-22 17:36
顶!
IoriKingdom
驱动小牛
驱动小牛
  • 注册日期2004-06-17
  • 最后登录2010-04-26
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望23点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-10-23 17:43
支持支持
天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,曾益其所不能。
ldljlzw
驱动中牛
驱动中牛
  • 注册日期2002-03-16
  • 最后登录2014-01-02
  • 粉丝1
  • 关注0
  • 积分1021分
  • 威望372点
  • 贡献值0点
  • 好评度187点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-11-05 10:22
预上去
meng20020311
驱动牛犊
驱动牛犊
  • 注册日期2005-01-04
  • 最后登录2005-02-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2005-01-31 16:28
顶。。。。。。。。
jjw
jjw
驱动牛犊
驱动牛犊
  • 注册日期2001-11-01
  • 最后登录2008-11-05
  • 粉丝0
  • 关注0
  • 积分-6分
  • 威望5点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2005-04-12 20:21
好文章,再推一把4444
jjw
shencheng
驱动牛犊
驱动牛犊
  • 注册日期2006-08-05
  • 最后登录2007-05-27
  • 粉丝0
  • 关注0
  • 积分50分
  • 威望6点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2007-01-11 11:24
hao
chunvv
驱动牛犊
驱动牛犊
  • 注册日期2005-04-30
  • 最后登录2011-03-24
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望245点
  • 贡献值0点
  • 好评度39点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2007-03-22 00:12
顶。。。。。。。。
zhang2007
驱动牛犊
驱动牛犊
  • 注册日期2007-06-17
  • 最后登录2008-10-23
  • 粉丝0
  • 关注0
  • 积分90分
  • 威望11点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2007-10-16 00:22
不错!
游客

返回顶部