wd_bool my_care(wd_ulong type) {
return (((type) == wd_dev_disk_fs) || ((type) == wd_dev_cdrom_fs) || ((type) == wd_dev_network_fs)); }
下一个问题是我打算跳过文件系统识别器。文件系统识别器是文件系统驱动的一个很小的替身。为了避免没有使用到的文件系统驱动占据内核内存,windows系统不加载这些大驱动,而代替以该文件系统驱动对应的文件系统识别器。当新的物理存储媒介进入系统,io管理器会依次的尝试各种文件系统对它进行“识别”。识别成功,立刻加载真正的文件系统驱动,对应的文件系统识别器则被卸载掉。对我们来说,文件系统识别器的控制设备看起来就像一个文件系统控制设备。但我们不打算绑定它。
分辨的方法是通过驱动的名字。凡是文件系统识别器的驱动对象的名字(注意是DriverObject而不是DeviceObject!)都为“FileSystem\\Fs_Rec”.
//-------------------用这些代码来跳过文件系统识别器---------------------- wd_wchar name_buf[wd_dev_name_max_len]; wd_ustr name,tmp;
wd_ustr_init_em(&name,name_buf,wd_dev_name_max_len); wd_ustr_init(&tmp,L\
// 我不绑定识别器。所以如果是识别器,我直接返回成功。查看是否是识别 // 器的办法是看是否是FileSystemFs_Rec的设备。 wd_obj_get_name(wd_dev_drv(fs_dev),&name); if(wd_ustr_cmp(&name,&tmp,wd_true) == 0) {
wd_printf0(\return wd_stat_suc; }
wd_printf0(\
接下来我将要生成我的设备。这里要提到设备扩展的概念。设备对象是一个数据结构,为了表示不同的设备,里边将有一片自定义的空间,用来给你记录这个设备的特有信息。我们为我们所生成的设备确定设备扩展如下:
// 文件过滤系统驱动的设备扩展 typedef struct _my_dev_ext {
// 我们绑定的文件系统驱动 wd_dev * attached_to;
// 上边这个设备的设备名。 wd_ustr dev_name;
// 这是上边的unicode字符串的缓冲区
wd_wchar name_buf[wd_dev_name_max_len]; } my_dev_ext;
之所以如此简单,是因为我们现在还没有多少东西要记录。只要记得自己绑定在哪个设备上就好了。如果以后需要更多的信息,再增加不迟。扩展空间的大小是在wdf_dev_create(也就是这个设备生成)的时候指定的。得到设备对象指针后,我用下面这个函数来获取设备扩展指针:
// --------------wdf.h中的内容------------------ _inline wd_void * wd_dev_ext(wd_dev *dev) {
return (dev->DeviceExtension); }
生成设备后,为了让系统看起来,你的设备和原来的设备没什么区别,你必须设置一些该设备的标志位与你所绑定的设备相同。
_inline wd_void wd_dev_copy_flag(wd_dev *new_dev, wd_dev *old_dev) {
if(old_dev->Flags & DO_BUFFERED_IO) new_dev->Flags &= DO_BUFFERED_IO; if(old_dev->Flags & DO_DIRECT_IO) new_dev->Flags &= DO_DIRECT_IO;
if (old_dev->Characteristics & FILE_DEVICE_SECURE_OPEN) new_dev->Characteristics &= FILE_DEVICE_SECURE_OPEN; }
DO_BUFFERED_IO,DO_DIRECT_IO这两个标志的意义在于外部向这些设备发送读写请求的时候,所用的缓冲地址将有所不同。这点以后在过滤文件读写的时候再讨论。现在一切事情都搞完,你应该去掉你的新设备上的DO_DEVICE_INITIALIZING标志,以表明的的设备已经完全可以用了。
// --------------wdf.h中的内容------------------
_inline wd_void wd_dev_clr_init_flag(wd_dev *dev) {
dev->Flags &= ~DO_DEVICE_INITIALIZING; }
现在我写一个函数来完成以上的这个过程。你只要在上一节中提示的位置调用这个函数,就
完成对文件系统控制设备的绑定了。
//-----------绑定一个文件系统驱动设备------------------------- wd_stat my_attach_fs_dev(wd_dev *fs_dev) {
wd_wchar name_buf[wd_dev_name_max_len]; wd_ustr name,tmp; wd_dev *new_dev; wd_stat status; my_dev_ext *ext;
wd_ustr_init_em(&name,name_buf,wd_dev_name_max_len); wd_ustr_init(&tmp,L\
// 如果不是我关心的类型,我直接返回成功 if(!my_care(wd_dev_get_type(fs_dev))) {
wd_printf0((\return wd_stat_suc; }
wd_printf0(\
// 我不绑定识别器。所以如果是识别器,我直接返回成功。查看是否是识别 // 器的办法是看是否是FileSystem\\Fs_Rec的设备。 wd_obj_get_name(wd_dev_drv(fs_dev),&name); if(wd_ustr_cmp(&name,&tmp,wd_true) == 0) {
wd_printf0(\return wd_stat_suc; }
wd_printf0(\
// 现在来生成一个设备用来绑定
status = wd_dev_create(g_drv,sizeof(my_dev_ext),NULL, wd_dev_get_type(fs_dev), 0,wd_false,&new_dev); if(!wd_suc(status)) {
wd_printf0(\return status; }
wd_printf0(\
// 接着设置设备的各种标志与之要绑定的标志一致 wd_dev_copy_flag(new_dev,fs_dev);
ext = (my_dev_ext *)wd_dev_ext(new_dev);
wd_printf0(\
status = wd_dev_attach(new_dev,fs_dev,&ext->attached_to); wd_printf0(\
if(!wd_suc(status)) {
wd_printf0(\UNREFERENCED_PARAMETER(new_dev); wd_dev_del(new_dev); return status; }
wd_printf0(\
wd_ustr_init_em(&ext->dev_name,ext->name_buf,wd_dev_name_max_len); wd_ustr_copy(&ext->dev_name,&name); wd_dev_clr_init_flag(new_dev);
return status; }
6.IRP的传递,File System Control Dispatch
我们现在不得不开始写dispatch functions.因为你的设备已经绑定到文件系统控制设备上去了。windows发给文件系统的请求发给你的驱动。如果你不能做恰当的处理,你的系统的就会崩溃。
最简单的处理方式是把请求不加改变的传递到我们所绑定的设备上去。如何获得我们所绑定的设备?上一节已经把该设备记录在我们的设备扩展里。
//------------我用这个函数快速得到我所绑定的设备----------- // 得到绑定的设备
_inline wd_dev *my_dev_attached(wd_dev *dev) {
return ((wdff_dev_ext *)wd_dev_ext(dev))->attached_to; }
相关推荐: