【文章标题】: WinMount虚拟磁盘深入研究(-)之filedisk源代码详细分析
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
    我的驱动入门三终结版,还再学习中。由于个人也有些事情要处理,研究起刘涛涛WinMount的虚拟
磁盘,而且这方面的书籍,貌似乎没见过,只有傻傻的几K代码存在,没注释什么的,整体框架也没说。  
  
  虚拟光驱用实现文件来模拟磁盘的原理,是文件系统驱动程序。
  把filedisk驱动安装,查看install.txt文件。
  1.Copy the driver (filedisk.sys) to %systemroot%\system32\drivers\.
  2.Import filedisk.reg to the Registry.
  3.Reboot.
  4.Use the program filedisk.exe to mount/umount files, for an example
  of use see the file example.txt.
  
  可以不用重起机子的方法,找一个动载加载驱动工具:DriverMonitor不错了。然后在“开始菜单”->
"运行"输入 "net start filedisk" 出现:“ 请求的服务已经启动”。这个必须得成功才行哦。
  
  接下来注意点。cmd后 出现这个目录 C:\Documents and Settings \Administrator>,在接下来敲入
  filedisk /mount 0 c:\temp\filedisk.img 8M f:  
  C:\Documents and Settings \Administrator>filedisk /mount 0 c:\temp\filedisk.img 8M r: 回车一下。  
  出现"FileDisk:系统找不到指定路径" 。原因就出在这 "c:\temp\filedisk.img" 中的C:\temp要这个目录才行。至于 filedisk.img不是必须,会自动创建。 如果有出现"FileDisk:函数不正确" 中的“filedisk /mount 0 ”中"0"代号已经被使用。可以改为"1".  查看一下,结果就出现一个还未格式化 8M R磁盘,查看C:\temp下生成一个filedisk.img也8M。想卸载
掉"filedisk /umount r:". 还可以创建很大的虚拟磁盘,你把"8M"改换其他的就是了。
  
  以上如果都没出现结果,基本上就没兴趣继续研究下去了,我看到了很多人初学filedisk都遇到以上这
些问题(包括我在内)  ,把我折腾了半天。  
  先来分析驱动层代码,后来分析应用层代码。更详细的请看附件里的源代码。我对代码工程方式重新布
局,用起来更方便。
  
  ===================================//先来分析驱动层代码
  1.对filedisk.h进行分析
  #define FILE_DEVICE_FILE_DISK       0x8000//用户定义范围0x8000~
  #define IOCTL_FILE_DISK_OPEN_FILE   CTL_CODE(FILE_DEVICE_FILE_DISK, 0x800, 

METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
  #define IOCTL_FILE_DISK_CLOSE_FILE  CTL_CODE(FILE_DEVICE_FILE_DISK, 0x801, 

METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
  #define IOCTL_FILE_DISK_QUERY_FILE  CTL_CODE(FILE_DEVICE_FILE_DISK, 0x802, 

METHOD_BUFFERED, FILE_READ_ACCESS)
  
  typedef struct _OPEN_FILE_INFORMATION {
      LARGE_INTEGER   FileSize;//文件大小
      BOOLEAN         ReadOnly;//只读属性
      USHORT          FileNameLength;//文件名长度
      UCHAR           FileName[1];//文件名
      UCHAR           DeviceType;//判断是K\G\M
  } OPEN_FILE_INFORMATION, *POPEN_FILE_INFORMATION;
  
  定义控制代码分别是“打开文件”、“关闭文件”、“查询?”
  2.看一下filedisk核心层\filedisk.c
  分析定义和声明的变量,接着从入口处分析,最后分析其他派谴例程。 定义几个IoCtrl合并宏,并定义几个结构体:MRB结构体、分区参数表等。  NTSTATUS DriverEntry()从入口点出发,嘿嘿。
  具体部分已经详细在源代码注释了。
  
  typedef struct _DEVICE_EXTENSION {
    BOOLEAN               media_in_device;
    HANDLE               file_handle;
    FILE_STANDARD_INFORMATION   file_information;
    BOOLEAN               read_only;
    PSECURITY_CLIENT_CONTEXT   security_client_context;
    LIST_ENTRY             list_head;
    KSPIN_LOCK             list_lock;
    KEVENT               request_event;
    PVOID               thread_pointer;
    BOOLEAN               terminate_thread;
  } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
      
      media_in_device是指这个设备是否已经指定了一个文件作为存储媒质。这是一个用文件来虚拟磁

盘的驱动。那么一个磁盘应该对应一个实际存在的文件。读写这个磁盘的请求最终转变为对文件的读写。

如果一个磁盘设备对象还没有指定文件,那么这个内容是FALSE.
  
         file_handle是文件句柄。也就是这个虚拟磁盘所对应的文件。
  
      file_information是这个文件的一些信息。
  
      read_only是否只读。
  
      security_client_context 访问文件的时候需要使用的一个线程客户安全性上下文。
  
  typedef struct _DISK_GEOMETRY {
               LARGE_INTEGER Cylinders;     // 磁柱个数
          MEDIA_TYPE MediaType;         // 媒质类型
          ULONG TracksPerCylinder;     // 每个磁柱上的磁道数
          ULONG SectorsPerTrack;         // 每个磁道上的扇区数
          ULONG BytesPerSector;         // 每个扇区上的字节数
      } DISK_GEOMETRY, *PDISK_GEOMETRY;
  
  
  核心层总体思路:从注册表获取关于驱动信息,接着由应用程序DeviceIoControl所发送的控制代码,

执行相应的派谴例程。最后进行对IRP进行处理就OK了。               
  
  ===================================//后来分析应用层代码
  这个是真的是不知道名字网友分析,我只能对他\她严重表示感谢。注释的很详细,非本人注释,本人
只是注释一点。我提一下整体思路就好了。先分析一些重要变量名接着分析5个函数,最后从main()函数分析,具体请看
  //变量分析
      char*                   Command;//命令行,比如你输入的“filedisk /umount r:”
      int                     DeviceNumber;//虚拟的盘数,比如 0-4个
      char*                   FileName;//用来虚拟磁盘所用的全文件名.比如:“c:\temp\filedisk.img ”
      char*                   Option;//可选比如“/ro| / cd”;ro:只读方式MOUNT,cd:虚拟CD_ROM
         char                    DriveLetter;//虚拟的盘符,比如"r:"盘
      BOOLEAN                 CdImage = FALSE;
         POPEN_FILE_INFORMATION  OpenFileInformation;//打开文件信息
      Command = argv[1];
   
  int Syntax(void);//syntax[sinteks]语法, 有秩序的排列, 句子构造, 句法意思。意思就是举例语
                   //式,怎么使用这个 filedisk.的语法格式  
 void PrintLastError(char* Prefix)//打印出错信息,特别是里面的一个formatmessage()函数是用来  
  
  int FileDiskMount(int DeviceNumber,POPEN_FILE_INFORMATION  OpenFileInformation,char 
                                        DriveLetter,BOOLEAN CdImage)
                 //这个函数很明显是安装上一个虚拟盘。首先判断是否存在该卷,存在则输出错误信息,不存在则创建。
          // 通过DeviceIoControl对驱动程序发送IRP消息。  
  int Umount(char DriveLetter)//这个函数很明显是卸载掉虚拟盘。判断要UnMount的盘存在否。
                            //DefineDosDevice()这个函数很帅。         
    //  1、锁定当前卷,通过发送FSCTL_LOCK_VOLUME到设备驱动实现
    //  2、关闭所有该卷上打开的所有文件,通过发送IOCTL_FILE_DISK_CLOSE_FILE到设备驱动实现
    //  3、卸载该卷,通过发送FSCTL_DISMOUNT_VOLUME到设备驱动实现
    //  4、解除该卷的锁定,通过发送FSCTL_UNLOCK_VOLUME到设备驱动实现
    //  5、关闭设备
    //  6、删除虚拟盘符  
  
  int main(int argc, char* argv[])//需要命令行。首先定义一下重要变量名,就上面说的重要变量名
。然后根据解析命令行,调用相应的函数来完成我们所需要的操作。  顺便联想一下。int main(int argc,char * argv[])参数的使用。  比如命令行输入: cfile computer C_Langle .此时argc=3. argv[]指向3个字符串,这些理解了。后面就没问题了。它是根据 argc来判断参数应该使用的命令。
  
  应用层总体思路:
  (argc==5 || argc==6)因为其中有一个是可选的,进行操作是Mount。分析代码时,请一边看结果,一
边分析代码 更容易些。接着对这个option选项中的[size[k|M|G] | /ro | /cd]分别进行处理。最后开始调用Mount
操作。 argc==3,是进行UnMount操作。
  
  只要打开filedisk核心层.dsw,VC自动把filedisk应用层和核心层这两个工程打开。
  
--------------------------------------------------------------------------------
【经验总结】
  下次继续分析,如何驱动加密、扩充容量、隐藏分区等等....... 
  
  
  参考书籍《filedisk源代码作者》      
          《一些不知名网友解决方案》比如:驱网pdodge注释部分核心层程序、未知网友注释部分应用层程序、
          《Windows磁盘驱动基础教程》张云飞注释部分核心层程序
           在此表示感谢!
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年12月26日 13:26:06