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


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

    3.分发例程,fast io

    上一节仅仅生成了控制设备对象。但是不要忘记,驱动开发的主要工作是撰写分发例程(dispatch functions.).接上一接,我们已经知道自己的DriverObject保存在上文代码的driver中。现在我写如下一个函数来指定一个默认的 dispatch function给它。

    //-----------------wdf.h中的代码----------------------
    typedef PDRIVER_DISPATCH wd_disp_fuc;
    _inline wd_void wd_drv_set_dispatch(in wd_drv* driver,
    in wd_disp_fuc disp)
    {
    wd_size i;
    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
    driver->MajorFunction[i] = disp;
    }

    在前边的wd_main中,我只要加

    wd_drv_set_dispatch(driver,my_dispatch_func);

    就为这个驱动指定了一个默认的Dispatch Function.所有的irp请求,都会被发送到这个函数。但是,我可能不希望这个函数处理过于复杂,而希望把一些常见的请求独立出来,如Read, Write,Create,Close,那我又写了几个函数专门用来设置这几个Dispatch Functions.

    //-----------------wdf.h中的代码----------------------
    _inline wd_void wd_drv_set_read(
    in wd_drv* driver,
    in wd_disp_fuc read)
    {
    driver->MajorFunction[IRP_MJ_READ] = read;
    }
    _inline wd_void wd_drv_set_write(
    in wd_drv* driver,
    in wd_disp_fuc write)
    {
    driver->MajorFunction[IRP_MJ_WRITE] = write;
    }

    wd_void wd_drv_set_create(in wd_drv* driver,
    in wd_disp_fuc create)
    {
    driver->MajorFunction[IRP_MJ_CREATE] = create;
    driver->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = create;
    driver->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = create;
    }

    wd_void wd_drv_set_file_sys_control(in wd_drv* driver,
    in wd_disp_fuc control)
    {
    driver->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = control;
    }

    wd_void wd_drv_set_clean_up(in wd_drv* driver,
    in wd_disp_fuc clean_up)
    {
    driver->MajorFunction[IRP_MJ_CLEANUP] = clean_up;
    }

    wd_void wd_drv_set_close(in wd_drv* driver,
    in wd_disp_fuc close)
    {
    driver->MajorFunction[IRP_MJ_CLOSE] = close;
    }

    别看我罗列n多代码,其实就是在设置driver->MajorFunction这个数组而已。因此在wd_main对dispatch functions的设置,就变成了下边这样的:

    // 开始设置几个分发例程
    wd_drv_set_dispatch(driver,my_disp_default);
    wd_drv_set_create(driver,my_disp_create);
    wd_drv_set_clean_up(driver,my_disp_clean_up);
    wd_drv_set_file_sys_control(driver,my_disp_file_sys_ctl);
    wd_drv_set_close(driver,my_disp_close);
    wd_drv_set_read(driver,my_disp_read);
    wd_drv_set_write(driver,my_disp_write);

    下面的任务都在写my_xxx系列的这些函数了。但是对于这个DriverObject的设置,还并不是仅仅这么简单。

    由于你的驱动将要绑定到文件系统驱动的上边,文件系统除了处理正常的IRP之外,还要处理所谓的FastIo.FastIo是Cache Manager调用所引发的一种没有irp的请求。换句话说,除了正常的Dispatch Functions之外,你还得为DriverObject撰写另一组Fast Io Functions.这组函数的指针在driver->FastIoDispatch.我不知道这个指针留空会不会导致系统崩溃。在这里本来是没有 空间的,所以为了保存这一组指针,你必须自己分配空间。

    下面是我常用的内存分配函数。

    //-----------------wdf.h中的代码----------------------
    // 最简单的分配内存的函数,可以指定分页非分页
    _inline wd_pvoid wd_malloc(wd_bool paged,wd_size size)
    {
    if(paged)
    return ExAllocatePool(PagedPool,size);
    else
    return ExAllocatePool(NonPagedPool,size);
    }

    // 释放内存
    _inline wd_void wd_free(wd_pvoid point)
    {
    ExFreePool(point);
    }

    _inline wd_void wd_memzero(
    wd_pvoid point,
    wd_size size)
    {
    RtlZeroMemory(point,size);
    }

    有了上边的基础,我就可以自己写一个初始化FastIoDispatch指针的函数。

    //-----------------wdf.h中的代码----------------------
    wd_bool wd_fio_disp_init(wd_drv *driver,wd_ulong size)
    {
    wd_fio_disp *disp = wd_malloc(wd_false,size);
    if(disp == wd_null)
    return wd_false;
    wd_memzero((wd_pvoid)disp,size);
    driver->FastIoDispatch = disp;
    driver->FastIoDispatch->SizeOfFastIoDispatch = size;
    return wd_true;
    }

    这个函数为FastIoDispacth指针分配足够的空间并填写它的大小。下面是再写一系列的函数来设置这个函数指针数组。实际上,FastIo接口函数实在太多了,所以我仅仅写出这些设置函数的几个作为例子:
    //-----------------wdf.h中的代码----------------------
    _inline wd_void wd_fio_disp_set_query_standard(
    wd_drv *driver,
    wd_fio_query_standard_func func)
    {
    driver->FastIoDispatch->FastIoQueryStandardInfo = func;
    }

    _inline wd_void wd_fio_disp_set_io_lock(
    wd_drv *driver,
    wd_fio_io_lock_func func)
    {
    driver->FastIoDispatch->FastIoLock = func;
    }

    _inline wd_void wd_fio_disp_set_io_unlock_s(
    wd_drv *driver,
    wd_fio_unlock_single_func func)
    {
    driver->FastIoDispatch->FastIoUnlockSingle = func;
    }

    ...

    好,如果你坚持读到了这里,应该表示祝贺了。我们回顾一下,wd_main中,应该做哪些工作。

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

    b.设置Dispatch Functions.

    c.设置Fast Io Functions.

    // ----------------wd_main 的近况----------------------------

    ...

    wd_dev *g_cdo = NULL;

    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_filters\");
    status = wdff_cdo_create(driver,0,&name,&g_cdo);

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

    wd_printf0(\"success: create cdo ok.rn\");

    // 开始设置几个分发例程
    wd_drv_set_dispatch(driver,my_disp_default);
    wd_drv_set_create(driver,my_disp_create);
    wd_drv_set_clean_up(driver,my_disp_clean_up);
    wd_drv_set_file_sys_control(driver,my_disp_file_sys_ctl);
    wd_drv_set_close(driver,my_disp_close);
    wd_drv_set_read(driver,my_disp_read);
    wd_drv_set_write(driver,my_disp_write);

    // 指定fast io处理函数
    if(!wd_fio_disp_init(driver,sizeof(wd_fio_disp)))
    {
    wd_dev_del(g_cdo);
    wd_printf0(\"error: fast io disp init failed.rn\");
    return wd_stat_insufficient_res;
    }

    // 下面指定的这些函数都定义在wdf_filter_fio.h中,其实这些函数都统
    // 一的返回了false
    wd_fio_disp_set_check(
    driver,
    my_fio_check);
    wd_fio_disp_set_read(
    driver,
    my_fio_read);
    wd_fio_disp_set_write(
    driver,
    my_fio_write);
    wd_fio_disp_set_query_basic(
    driver,
    my_fio_query_basic_info);

    ...

    }
    FastIo函数个数数量不明,我只觉得很多。因此不打算全部罗列,以\"...\"敷衍之。某些读者可能会认为这些代码无法调试安装。其实您可以参考sfilter中的示例自己完成这些代码。

    现在我们的my_xxx系列的函数还没有开始写,因此驱动也不能编译通过。在后边的内容中再逐步介绍。
  • 相关阅读:
    Mongodb地理位置索引
    PHP中目录解析函数
    PHP中的date函数中时区问题
    PHP 文件上传全攻略
    PHP上传图片重命名6种方案
    C#|executequery要求已打开且可用的connection,连接的当前状态为已关闭
    C#|只有 assignment、call、increment、decrement 和 new 对象表达式可用作语句
    Android报错|Android Call requires API level 19 (current min is 15)
    机器学习|用机器学习预测谁将夺得世界杯冠军(附代码)
    Python|词云wordcloud入门示例
  • 原文地址:https://www.cnblogs.com/jasononline/p/1231767.html
Copyright © 2020-2023  润新知