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

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

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

2.hello world,驱动对象与设备对象

这里所说的驱动对象是一种数据结构,在DDK中名为DRIVER_OBJECT。任何驱动程序都对应一个DRIVER_OBJECT.如何获得本人所写的驱动对应的DRIVER_OBJECT呢?驱动程序的入口函数为DriverEntry,因此,当你写一个驱动的开始,你会写下如下的代码:

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
}

这个函数就相当与喜欢c语言的你所常用的main().IN是无意义的宏,仅仅表明后边的参数是一种输入,而对应的OUT则代表这个参数是一种返回。这里没有使用引用,因此如果想在参数中返回结果,一律传入指针。

DriverObject就是你所写的驱动对应的DRIVER_OBJECT,是系统在加载你的驱动时候所分配的。RegisteryPath是专用于你记录你的驱动相关参数的注册表路径。

DriverObject重要之处,在于它拥有一组函数指针,称为dispatch functions.

开发驱动的主要任务就是亲手撰写这些dispatch functions.当系统用到你的驱动,会向你的DO发送IRP(这是windows所有驱动的共同工作方式)。你的任务是在dispatch function中处理这些请求。你可以让irp失败,也可以成功返回,也可以修改这些irp,甚至可以自己发出irp。

设备对象则是指DEVICE_OBJECT.下边简称DO.

但是实际上每个irp都是针对DO发出的。只有针对由该驱动所生成的DO的IRP,
才会发给该驱动来处理。

当一个应用程序打开文件并读写文件的时候,windows系统将这些请求变成irp发送给文件系统驱动。

文件系统过滤驱动将可以过滤这些irp.这样,你就拥有了捕获和改变文件系统操作的能力。

象Fat32,NTFS这样的文件系统(File System,简称FS),可能生成好几种设备。首先文件系统驱动本身往往生成一个控制设备(CDO).这个设备的主要任务是修改整个驱动的内部配置。因此一个Driver只对应一个CDO.

另一种设备是被这个文件系统Mount的Volume。一个FS可能有多个Volume,也可能一个都没有。解释一下,如果你有C:,D:,E:,F:四个分区。C:,D:为NTFS,E:,F:为Fat32.那么C:,D:则是Fat的两个Volume设备对象.

实际上"C:"是该设备的符号连接(Symbolic Link)名。而不是真正的设备名。可以打开Symbolic Links Viewer,能看到:

C: \Device\HarddiskVolume1

因此该设备的设备名为“\Device\HarddiskVolume1”.

这里也看出来,文件系统驱动是针对每个Volume来生成一个DeviceObject,而不是针对每个文件的。实际上对文件的读写的irp,都发到Volume设备对象上去了。并不会生成一个“文件设备对象”。

掌握了这些概念的话,我们现在用简单的代码来生成我们的CDO,作为我们开发文件系统驱动的第一步牛刀小试。

我不喜欢用微软风格的代码。太长而且难看。我对大部分数据结构和函数进行了重定义。为此我写了一个名为wdf.h的头文件帮助我转换。有兴趣的读者可以发邮件向索取这个文件。没有也没有关系,我总是会写出wd_xxx系列的东西在DDK中的原形。


// -----------------wdf_filter.c中的内容-------------------------

#include "wdf.h"

wd_stat wdff_cdo_create(in wd_drv *driver,
in wd_size exten_len,
in wd_ustr *name,
out wd_dev **device)
{
    return wd_dev_create(
                driver,
                exten_len,
                name,
                wd_dev_disk_fs,
                wdf_dev_secure_open,
                wd_false,
                device);
}

wd_stat wd_main(in wd_drv* driver,
in wd_ustr* reg_path)
{
wd_ustr name;
wd_stat status = wd_stat_suc;

// 然后我生成控制设备,虽然现在我的控制设备什么都不干
wd_ustr_init(&name,L"\\FileSystem\\Filters\\our_fs_filter");
status = wdff_cdo_create(driver,0,&name,&g_cdo);

if(!wd_suc(status))
{
if(status == wd_stat_path_not_found)
{
// 这种情况发生于\FileSystem\Filters路径不存在。这个路径是
// 在xp上才加上的。所以2000下会运行到这里
wd_ustr_init(&name,L"\\FileSystem\\our_fs_filter");
status = wdff_cdo_create(driver,0,&name,&g_cdo);
};
if(!wd_suc(status))
{
wd_printf0("error: create cdo failed.\r\n");
return status;
}
}

wd_printf0("success: create cdo ok.\r\n");
return status;
}

为了让代码看起来象上边的那样,我不得不做了很多转换。如

#define DriverEntry wd_main

一种爽的感觉,终于可以在写看起来更象是main()的函数中工作了。 wd_dev_create 这个函数内部调用的是IoCreateDevice.而wd_suc实际上是SUCCESS()这样的宏。

// ----------------------wdf.h中的内容------------------------------
#include "ntifs.h"

#define in IN
#define out OUT
#define optional OPTIONAL
#define wd_ustr UNICODE_STRING
#define wdp_ustr PUNICODE_STRING
#define wd_main DriverEntry

// 设备、驱动对象类型
typedef DRIVER_OBJECT wd_drv;
typedef DEVICE_OBJECT wd_dev;
typedef DRIVER_OBJECT wd_pdrv;
typedef PDEVICE_OBJECT wd_pdev;

enum {
wd_dev_disk_fs = FILE_DEVICE_DISK_FILE_SYSTEM,
wd_dev_cdrom_fs = FILE_DEVICE_CD_ROM_FILE_SYSTEM,
wd_dev_network_fs = FILE_DEVICE_NETWORK_FILE_SYSTEM
};

// 状态相关的类型和宏
typedef NTSTATUS wd_stat;

enum {
wd_stat_suc = STATUS_SUCCESS,
wd_stat_path_not_found = STATUS_OBJECT_PATH_NOT_FOUND,
wd_stat_insufficient_res = STATUS_INSUFFICIENT_RESOURCES,
wd_stat_invalid_dev_req = STATUS_INVALID_DEVICE_REQUEST,
wd_stat_no_such_dev = STATUS_NO_SUCH_DEVICE,
wd_stat_image_already_loaded = STATUS_IMAGE_ALREADY_LOADED,
wd_stat_more_processing = STATUS_MORE_PROCESSING_REQUIRED,
wd_stat_pending = STATUS_PENDING
};

_inline wd_bool wd_suc(wd_stat state)
{
return NT_SUCCESS(state);
}

#define wd_printf0 DbgPrint

_inline wd_void wd_ustr_init(in out wd_ustr* str,
in const wd_wchar* chars)
{
RtlInitUnicodeString(str,chars);
};

_inline wd_void wd_ustr_init_em(
in out wd_ustr*str,
in wd_wchar *chars,
in wd_size size)
{
RtlInitEmptyUnicodeString(str,chars,size);
};


wdf.h这个文件我仅仅节选了需要的部分。以上您已经拥有了一个简单的“驱动”的完整的代码。它甚至可以编译,安装(请修改sfilter.inf文件,其方法不过是将多处sfilter改为"our_fs_filter",希望这个过程中您不会出现问题)。然后把wdf.h和wdf_filter.c放在您新建立的目录下,这个目录下还应该有另两个文件。一个是Makefile,请从sfilter目录下拷贝。另一个是SOURCES,请输入如下内容:
TARGETNAME=our_fs_filter
TARGETPATH=obj
TARGETTYPE=DRIVER
DRIVERTYPE=FS
BROWSER_INFO=1
SOURCES=wdf_filter.c

使用ddk编译之后您将得到our_fs_filter.sys.把这个文件与前所描述的inf文件同一目录,按上节所叙述方法安装。

这个驱动不起任何作用,但是你已经成功的完成了"hello world".

最新喜欢:

yuanycyuanyc forgetalexforget...
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
沙发#
发布于:2004-10-20 21:23
请继续努力写,以方便大家。

为了鼓励你对本站的贡献,特授权高级会员权限.谢谢你对本站的支持。
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
XiangXiangRen
总版主
总版主
  • 注册日期2003-02-22
  • 最后登录2015-09-01
  • 粉丝13
  • 关注0
  • 积分1042分
  • 威望472点
  • 贡献值1点
  • 好评度145点
  • 原创分13分
  • 专家分1分
板凳#
发布于:2004-10-21 09:18
不知道这里发帖子如何让代码变得好看一点。常常出现方括弧,斜线不见了,然后又出现文字全变成了斜体,搞不懂啊
chufuxuan
驱动牛犊
驱动牛犊
  • 注册日期2003-01-09
  • 最后登录2016-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-10-21 09:54
发帖时把下面的复选框“是否关闭BBCode功能?”和“不使用smileys?”选上,就好了
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
地下室#
发布于:2004-10-21 09:54
下周改一下。

http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
IoriKingdom
驱动小牛
驱动小牛
  • 注册日期2004-06-17
  • 最后登录2010-04-26
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望23点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-10-23 17:25
兄弟为国为民,值得学习
天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,曾益其所不能。
jjw
jjw
驱动牛犊
驱动牛犊
  • 注册日期2001-11-01
  • 最后登录2008-11-05
  • 粉丝0
  • 关注0
  • 积分-6分
  • 威望5点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2005-04-12 20:19
好文章,再推一把1111
jjw
CII_GZH
驱动中牛
驱动中牛
  • 注册日期2005-06-16
  • 最后登录2007-08-27
  • 粉丝0
  • 关注0
  • 积分257分
  • 威望127点
  • 贡献值0点
  • 好评度33点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2005-07-11 14:41
我喜欢。
学习
alibaba00
驱动牛犊
驱动牛犊
  • 注册日期2005-07-22
  • 最后登录2011-06-08
  • 粉丝0
  • 关注0
  • 积分334分
  • 威望39点
  • 贡献值0点
  • 好评度25点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2005-07-22 15:29
大家一致推荐我来看看,收获不小啊.
yuanyuan
驱动大牛
驱动大牛
  • 注册日期2003-01-15
  • 最后登录2010-08-04
  • 粉丝0
  • 关注0
  • 积分1025分
  • 威望300点
  • 贡献值0点
  • 好评度232点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2005-07-23 09:43
顶一下
xhjjxm
驱动小牛
驱动小牛
  • 注册日期2005-08-03
  • 最后登录2010-07-28
  • 粉丝0
  • 关注0
  • 积分1011分
  • 威望208点
  • 贡献值0点
  • 好评度87点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2005-08-11 10:53
支持!
starl1985
驱动小牛
驱动小牛
  • 注册日期2009-02-04
  • 最后登录2016-01-09
  • 粉丝2
  • 关注2
  • 积分134分
  • 威望1021点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2009-05-07 10:13
很基础,很重要,很易懂!!谢谢香香人。。。
多看DDK,勤搜索
Dongn
驱动牛犊
驱动牛犊
  • 注册日期2009-03-27
  • 最后登录2009-05-07
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望281点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2009-05-07 10:25
majinxin2003
驱动牛犊
驱动牛犊
  • 注册日期2008-11-17
  • 最后登录2011-01-24
  • 粉丝1
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2009-05-07 14:16
感觉有点类似楚狂人写的那本书~~~~
游客

返回顶部