dokan是用户态的文件系统驱动,可以称之为fuse for windows。可以用来开发虚拟磁盘,即在“我的电脑”中虚拟出一个硬盘来,可以是硬盘,也可以是可移动磁盘或者网络硬盘。

CreateFile、FindFiles、GetFileInformation需要最优先实现,有了这两个接口,就可以浏览目录了。

进入CreateFile,需要判断请求的虚拟文件是目录还是文件,如果是目录,则需要设置DokanFileInfo->IsDirectory为True,并直接返回成功。虚拟文件的打开可以根据CreationDisposition、AccessMode、ShareMode三者组合。最简单的做法是在最开始处对做判断,因为它只有五种可能性,把文件不存在,但却需要以只读打开的都排除,然后就可以放心地应用:读使用”rb+”, 写使用”wb+”。

Create中返回的文件描述符或者类似的数据可以保存DokanFileInfo->context中,这个值可以在以后的其它函数调用中访问到:比如CloseFile, CleanUp, DeleteFile, ReadFile, WriteFile等等。

CreateDirectory和实际的文件操作一致。
OpenDirectory一般直接返回成功,除非目录无访问权限,可以人为地返回-1。
CloseFile用处不大,因为在CloseFile之前,有一道CleanUp调用,已经清除了打开的文件。
CleanUp和CloseFile好像会被一前一后地调用,在CleanUp中需要做的事情是根据DokanFileInfo->context保存的值关闭虚拟文件。并且DokanFileInfo->DeleteOnClose如果为True,则需要把当前请求的文件或者目录删除。文件删除的动作实际是在Cleanup中实现的。

DeleteDirectory和DeleteFile两个接口实现中,不能够真正去删除文件,而是在文件或者目录需要删除时,返回0即可,系统会继续调用上面说的cleanup来处理删除事件。

在文件的删除时,有可能操作系统传递过来的请求文件并未被关闭,但好在同时DokanFileInfo->context也会被一同传递来,所以可以先强行关闭打开的文件,然后做删除操作。

操作系统的应用程序每次读写文件都是通过ReadFile、WriteFile接口完成的,一般情况下一次求请的大小比较小,比如65535Bytes等,但也有例外,比如使用FastCopy等多线程文件快速复制工具时,它会直接向ReadFile请求32MB的大小。

ReadFile WriteFile一般情况下都会有DokanFileInfo->context参数传进来,就像平常我们写文件读写的代码一样,总是先fopen个FILE*出来,然后再读写。 但是也有例外,比如记事本在读文件的时候,就只是给个路径+文件名。 这个时候,需要在ReadFile WriteFile临时专门为这一次请求打开文件,在退出函数时,一定要关闭它。

FlushFileBuffers是个没用的东西,可以不实现。

GetFileInformation非常重要,资源管理器每次打开目录时,会查询当前目录每个文件的信息。如果给出的信息不恰当,比如文件时间如果是个变化的值(比如图省事,将所以文件的时间设置为当前时间),这样会导致系统不断地查询,非常的恐怖。 在返回的dwFileAttributes中,需要小心地设置文件类型,文件和目录千万要区别正确。 试过FILE_ATTRIBUTE_NORMAL+FILE_ATTRIBUTE_ARCHIVE-FILE_ATTRIBUTE_ENCRYPTED以及FILE_ATTRIBUTE_DIRECTORY就基本正常工作了,FILE_ATTRIBUTE_ENCRYPTED一定要去掉,不然系统会认为你虚拟出来的盘符是加密的,往其它盘复制文件时会提示不能处理加密文件而直接失败。

FindFiles函数中,我们需要用传递进来的函数指针FillFindData将我们需要显示的目录和文件填充到系统为我们准备好的地方。只要文件的属性dwFileAttributes像样,可以构造虚拟文件和目录(比如可以将数据库里的用户和组记录读出来,表示成一层层的目录)。

MoveFile就是移动文件及改名,没什么特殊的地方。

SetEndOfFile一般情况下使用不到,但是如果有软件调用了这个API则还是有用的,比如像fastCopy,为了尽可能地加快复制速度,它每次从内存将固定大小的数据保存到硬盘,比如大小为31MB的文件,实际上它写了32MB(文件尾部的数据其实是多余的),这是用readFile WriteFile实现的。但它最后会根据原文件的真实大小来做一次setEndOfFile将其裁剪到正确的大小。如果不实现setEndOfFile,fastcopy就没用了。

SetFileAttributes和SetFileTime如果不想实现,就让它返回0,最好不要为了禁用这两个api.因为像Word之类的软件,它很在意这两个函数,在保存文件时候不厌其烦地调用,所以为了让Word在虚拟盘上工作正常,必须忽悠它,否则不能保存做过编辑的文档。

GetDiskFreeSpace是返回驱动器的容量信息的,比如虚拟盘可以做容量限制。
GetVolumeInformation返回驱动器的卷标和文件系统类型,可以随便设置,文件类型可以随便取名,比如“XX文件系统”,和NTFS/FAT32是同等地位的。

GetFileInformation 有时候传递过来的DokanFileInfo->context不是空的,所以一定要使用它来查询文件大小。 假设DokanFileInfo->context保存的是fopen打开的fd, 如果使用传递过来的文件名去GetFileAttribute或者Stat()真实文件,有可能会因为缓存的缘故查询到的文件大小不是实时的。这一点在对文件大小变化敏感的软件上特别重要,比较变态的Word,在保存的时候,它会先保存到临时文件,保存过程中,写一点数据,马上查询文件大小是否有变化是否和写的数据大小一致。如果这时GetFIleInformation马马虎虎地返回个大小,Word就罢工了,它会以为当前磁盘是不稳定的,或者容量比较用光,而拒绝保存。

利用dokan作虚拟磁盘开发的更多相关文章

  1. [Python] 利用Django进行Web开发系列(一)

    1 写在前面 在没有接触互联网这个行业的时候,我就一直很好奇网站是怎么构建的.现在虽然从事互联网相关的工作,但是也一直没有接触过Web开发之类的东西,但是兴趣终归还是要有的,而且是需要自己动手去实践的 ...

  2. [Python] 利用Django进行Web开发系列(二)

    1 编写第一个静态页面——Hello world页面 在上一篇博客<[Python] 利用Django进行Web开发系列(一)>中,我们创建了自己的目录mysite. Step1:创建视图 ...

  3. Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用

    前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...

  4. php利用zookeeper作dispatcher服务器

    ===== https://blog.eood.cn/php_share_memory 最常见的apc 可以缓存php的opcode提高应用的性能,可以在同个php-fpm进程池间共享数据 常见功能: ...

  5. 跟我一起学WCF(2)——利用.NET Remoting技术开发分布式应用

    一.引言 上一篇博文分享了消息队列(MSMQ)技术来实现分布式应用,在这篇博文继续分享下.NET平台下另一种分布式技术——.NET Remoting. 二..NET Remoting 介绍 2.1 . ...

  6. 转载:如何利用Vim进行Erlang开发

    转自:http://ovalpo.info/how_to_use_vim_for_erlang_dev/ 如何利用Vim进行Erlang开发 by Martin J. Logan on Septemb ...

  7. 利用Sails.js+MongoDB开发博客系统

    http://yoyoyohamapi.me/categories/利用Sails-js-MongoDB开发博客系统/ 利用Sails.js+MongoDB开发博客系统 Apr 14, 2016 利用 ...

  8. 利用connect建立前端开发服务器

    利用connect建立前端开发服务器 对于前后端完全分离的系统,开发时候我们需要给前端配置服务器,当然我们可以选择Nginx之类的服务器进行配置,但我们也能使用NodeJS构建高自由度的前端开发服务器 ...

  9. Microsoft Tech Summit 2018 课程简述:利用 Windows 新特性开发出更好的手绘视频应用

    概述 Microsoft Tech Summit 2018 微软技术暨生态大会将于10月24日至27日在上海世博中心举行,这也会是国内举办的最后一届 Tech Summit,2019 年开始会以 Mi ...

随机推荐

  1. windows 装 centos

    windows下压缩一下空间 直接装centos 找到分配给linux的/boot目录,然后修改grub/menu.lst文件,更换一下位置即可

  2. Java 反射实例

    实体类:Userpackage com.reflect.model; public class User{ private User(int id, String username, String p ...

  3. no ia32-libs

    sudo apt-get install lib32stdc++6 sudo apt-get install lib32z1 http://blog.csdn.net/wangbin_jxust/ar ...

  4. 熟练使用NTFS的文件链接技术

    硬链接和软链接介绍: 硬连接指向的是i节点(iNode),而软连接指向的是路径(Path) ,又称符号链接.硬链接可理解为对i节点的引用,最初的文件名与所有的硬链接地位是对等的,比如为文件a建立了硬链 ...

  5. Java学习笔记之I/O

    package com.chinasofti.javase20160819; import java.io.BufferedReader; import java.io.BufferedWriter; ...

  6. Mybatis 一对一,一对多,多对一,多对多的理解

    First (一对一) 首先我来说下一对一的理解,就是一个班主任只属于一个班级,一个班级也只能有一个班主任.好吧这就是对于一对一的理解 怎么来实现呢? 这里我介绍了两种方式: 一种是:使用嵌套结果映射 ...

  7. servlet多次跳转报IllegalStateException异常

    当发生在如下错误的时候,有一个方案可行, "java.lang.IllegalStateException: Cannot forward after response has been c ...

  8. 封装sdk API 应用

    1 #include "QWinApp.h" 2 #include "QGlobal.h" 3 int WINAPI _tWinMain(HINSTANCE h ...

  9. selenium2.0集成测试案例

    webDriver模拟点击对web工程测试还是挺方便的. package suite; import java.util.concurrent.TimeUnit; import org.junit.A ...

  10. 大学二三事——那些人(1)

    校歌墙的对面是一座历史比较悠久的建筑,以前叫做12号楼,后来改成了"诚"字楼. 在诚字楼一楼昏暗的走廊上,你总是能看见一位大概四五十岁的大叔,有时他会指着挂在墙上的学校简介,一个人 ...