farsky16的专栏

宠辱不惊,看庭前花开花落;去留无意,望天空云卷云舒.

用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
farsky16的公告
文章分类
    存档

    原创  FileDisk源码分析 收藏

    一 安装和使用方法:
     1 安装:看install.txt文件;
     2 挂载:filedisk /mount 0 c:\proj\myfiledisk\a.img e:
     3 卸载:filedisk /umount e:
     详细看example.txt文件,在本站的下载中心有下载,包括核心层和应用层的源码。
     最多可以同时挂4个设备,分别定义4个设备号,如果同一设备号使用2次,会进入OPEN_FILE两次,出现"FileDisk: IOCTL_FILE_DISK_OPEN_FILE: Media already opened\n"的错误提示;

    二 基本知识:
     1 关于DefineDosDevice函数:
      在应用层开发中调用它来创建一个\??目录下的符号链接,如:
    BOOL okay = DefineDosDevice(DDD_RAW_TARGET_PATH, "test", "\\Device\\FileDisk0");
    调用成功后,将会在设备命名空间的\??目录下生成一个名为”test“的符号链接,该链接指向”“\\Device\\FileDisk0“这个对象。
      而在核心态的驱动程序中,需要调用以下的函数来创建相应的符号链接:
    IoCreateSymbolicLink(linkname, targname);
    Linkname是要创建的符号链接名,相当于上面函数中的”test”,targname是该链接指向的设备对象。

     2 filedisk的源映像可以是img,iso,flp等,这些都是磁盘上一个分区的平面映像,所以挂上后可以直接访问,但不能是整个硬盘的img映像或其它格式如rar等;

     3 filedisk的源映像文件名称必须是全路径,即使是在当前目录下也必须是全路径;

     4 源映像文件如果不存在且参数中没有指定只读,那么只要在参数中指定了大小则会主动创建它,使用前会提示先“格式化”,之后就可正常使用了;

    三 核心层源码分析:
     1 DriverEntry: 主函数入口;备份传入路径,查询注册表值,调用ZwCreateDirectoryObject创建设备目录,重复4次调用   FileDiskCreateDevice创建设备,初始化操作函数指针。

     2 FileDiskCreateDevice:调用IoCreateDevice创建设备,KeInitializeEvent初始化事件对象,PsCreateSystemThread创建内核线程,入口函数是FileDiskThread,传入的函数参数为IoCreateDevice返回的设备对象。

     3 FileDiskThread:首先调用KeSetPriorityThread更改自身线程的优先级为LOW_REALTIME_PRIORITY,然后开始for(;;),调用KeWaitForSingleObject函数等待事件对象有信号,如果等到,判断事件类型,有如下几种:
    IRP_MJ_READ:调用ZwReadFile读取文件,从内核到用户缓冲区;
    IRP_MJ_WRITE:调用ZwWriteFile写入文件,从用户到内核缓冲区;
    IRP_MJ_DEVICE_CONTROL:在FileDiskDeviceControl设置事件才会触发,主要有如下两种操作码:
     IOCTL_FILE_DISK_OPEN_FILE:调用FileDiskOpenFile。
     IOCTL_FILE_DISK_CLOSE_FILE:调用FileDiskCloseFile。

    FileDiskOpenFile:根据用户程序传入的映像文件全路径,调用ZwCreateFile在内核中打开它,如果文件不存在则再创建它,返回文件句柄。
    FileDiskCloseFile:调用ZwClose关闭文件。

     4 FileDiskCreateClose: 仅返回成功;对应Create,Close操作。

     5 FileDiskReadWrite:将IO包插入队列,然后调用KeSetEvent函数,激活事件对象;对应Read,Write操作。

     6 FileDiskDeviceControl:用户程序调用DeviceIoControl的响应函数,主要有如下两种操作:
     IOCTL_FILE_DISK_OPEN_FILE:设置好参数,将IO包插入队列,设置对象为有信号。
     IOCTL_FILE_DISK_CLOSE_FILE:将IO包插入队列,设置对象为有信号。
     其它的操作类型因为输入输出共用一个缓冲区,所以都采用系统默认处理,设置好需要输出的参数后,就直接从这个函数返回了。如:
     IOCTL_DISK_GET_DRIVE_GEOMETRY,IOCTL_CDROM_GET_DRIVE_GEOMETRY等;

     7 有4种操作是自定义的:FileDiskReadWrite函数两种,FileDiskDeviceControl函数两种,对应的操作码分别是:
     IRP_MJ_READ,IRP_MJ_WRITE,IOCTL_FILE_DISK_OPEN_FILE,IOCTL_FILE_DISK_CLOSE_FILE这4种,在FileDiskThread中等待这4种事件发生,如果等到,就调用相应的函数处理。


    四 应用层源码分析:
     1 mount:调用DefineDosDevice在应用层创建一个指向设备命名空间的符号链接,用CreateFile打开此链接,然后调用DeviceIoControl,控制码是IOCTL_FILE_DISK_OPEN_FILE,内核程序响应后,执行真正打开源映像文件的操作。
     
     2 umount: 上面大致一样,只是多一些步骤,不同的是控制码改为IOCTL_FILE_DISK_CLOSE_FILE,之后必须发送FSCTL_DISMOUNT_VOLUME;

    发表于 @ 2006年05月06日 22:59:00 | 评论( loading... ) | 编辑| 举报| 收藏

    旧一篇:gcc和vc编译器在语法上的比较 | 新一篇:DDK中网络驱动器例子NulMRx安装和使用

    • 发表评论
    • 评论内容:
    •  
    Copyright © farsky16
    Powered by CSDN Blog