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. ASP.NET MVC View向Controller提交数据

    我们知道使用MVC的一个很重的的用途就是把Controller和View之间进行解耦,通过控制器来调用不同的视图,这就注定了Controller和View之间的传值是一个很重的知识点,这篇博文主要解释 ...

  2. node.js作为“简单HTTP服务器”

    场景 当我学习一个JavaScript库的时候,需要一个非常简单的HTTP服务器把当前工作路径变为网站根目录,由此来访问网页的静态信息.现在,除了下边的脚本server.js,假设你已经拥有: 一个工 ...

  3. dfs Codeforces Round #356 (Div. 2) D

    http://codeforces.com/contest/680/problem/D 题目大意:给你一个大小为X的空间(X<=m),在该空间内,我们要尽量的放一个体积为a*a*a的立方体,且每 ...

  4. Inno Setup入门(十一)——完成安装后执行某些程序

    有些时候我们的程序虽然能够很好的完成安装,但是程序的配置工作可能需要其他的一些程序来辅助完成,如果不执行这些程序,主程序就不能很好的完成工作,甚至不能完成工作,一个很明显的例子是,目前许多程序是通过N ...

  5. Log4j 简介及初步应用

    使用2.5版本有问题,暂时没有解决,也许是JDK版本不兼容的原因.因此使用的是log4j-1.2.8.jar 1.三个组件 日志记录器  ——  Logger.输出目的地 —— Appender.输出 ...

  6. zf-关于交换工具配置文件,交换的“列名字段”前面加个“0,1,2”的意思。

  7. 全文检索工具推荐FileLocator

    全文检索工具推荐FileLocator https://www.baidu.com/link?url=_vaDZaJ_OePrAX-BTUD5hjTymnvN7_1oIAnWyS25hqxAg0nUH ...

  8. Android OpenGL ES(十二):三维坐标系及坐标变换初步 .

    OpenGL ES图形库最终的结果是在二维平面上显示3D物体(常称作模型Model)这是因为目前的打部分显示器还只能显示二维图形.但我们在构造3D模型时必须要有空间现象能力,所有对模型的描述还是使用三 ...

  9. servlet & javabean

    1.servelet 什么是Servlet?① Servlet就是JAVA 类② Servlet是一个继承HttpServlet类的类③这个在服务器端运行,用以处理客户端的请求 Servlet相关包的 ...

  10. 覆盖问题<shui>

    题目链接 /* hang[maxn]标记每行是否可以被攻击,并计算前缀和 lie [maxn]标记每列是否可以被攻击,并计算前缀和 */ #include<cstdio> // #incl ...