FastIO
当阅读过滤驱动代码自己实践时,我想法是绑定完卷设备后,把所有的IRP都原封不动向下发,只是在passthru中打印个信息,表示经过了我的驱动,想看下效果。
用Device Tree查看,已成功绑定了D盘这个分区。用Dbgview查看,也能查看到输出信息。但是,绑定的D盘中,除了txt文件外,无法打开文件或运行程序,无法查看文件信息(创建日期,大小等),当一进行上述操作时,就BSOD,显示错误码:
STOP:0x0000008E(0xC0000005, 0x8057D74B,0xF54C7C30,0x00000000)
0xC0000005 表示内存访问违规,如使用了野指针,或指针未初始化即使用等。
用WinDbg调试得到信息:
Starting MyPassThr
Access violation - code c0000005 (!!! second chance !!!)
nt!NtReadFile+0x2c1:
8057d74b ff5608 call dword ptr [esi+8]
Type information missing error for Device
究其原因,是因为没处理 FastIO!因为I/O管理器在进行I/O操作时,首先查看该设备是否支持fast io。也就是fast io dispach 的那张表项是否为空,如果不为空,则调用之,当发现函数返回值为FALSE时,才生成一个IRP,然后下传。
所以,我添加处理了FastIoRead分发例程,然后直接return FALSE。即能进行FastIO操作的都停止FastIO操作,生成IRP下发。之后即解决了BSOD问题。
NT 下FASTIO 是一套IO MANAGER 与DEVICE DRIVER 沟通的另外一套API. 在进行基于IRP 为基础的接口调用前, IO MANAGER 会尝试使用FAST IO 接口来加速各种IO 操作. FASTIO 本身的文档并不多见, 本篇就是要介绍一下FASTIO 接口:
FastIoCheckIfPossible, 此调用并不是IO MANAGER 直接调用. 而是被FsRtlXXX 系列函数调用. 用于确认读写操作是否可以用FASTIO 接口进行.
FastIoRead/FastIoWrite, 很明显, 是读写处理的调用.
FastIoQueryBasicInfo/FastIoQueryStandardInfo, 用于获取各种文件信息. 例如创建,修改日期等.
FastIoLock/FastIoUnlockSingle/FastIoUnlockAll/FastIoUnlockAllByKey,用于对文件的锁定操作.
在NT 中有2 种锁定需要存在。1.排他性锁. 2.共享锁. 排他性锁在写操作前获取,不准其他进程获得写操作权限, 而共享锁则代表需要读文件某区间. 禁止有写动作出现. 在同一地址上, 如果有多个共享锁请求, 那是被允许的.
FastIoDeviceControl 用于提供NtDeviceIoControlFile 的支持.
AcquireFileForNtCreateSection/ReleaseFileForNtCreateSection 是NTFS 在映射文件内容到内存页面前进行的操作.
FastIoDetachDevice, 当REMOVABLE 介质被拿走后, FILE SYSTEM 的DEVICE 对象会在任意的时刻被销毁. 只有正确处理这个调用才能把上层DEVICE 和将要销毁的DEVICE 脱钩. 如果不解决这个函数, 系统会当.
FastIoQueryNetworkOpenInfo, 当CIFS 也就是网上邻居,更准确的说是网络重定向驱动尝试获取文件信息,会使用这个调用. 该调用是因为各种历史原因而产生. 当时设计CIFS 时为避免多次在网上传输文件信息请求, 在NT4 时传输协议增加了一个FileNetworkOpenInformation 的网络文件请求. 而FSD 则增加了这个接口. 用于在一次操作中获得所有的文件信息. 客户段发送FileNetworkOpenInformation, 服务器端的FSD 用本接口完成信息填写.
FastIoAcquireForModWrite, Modified Page Writer 会调用这个接口来获取文件锁. 如果实现这个接口. 则能使得文件锁定范围减小到调用指定的范围. 不实现此接口, 整个文件被锁.
FastIoPrepareMdlWrite, FSD 提供MDL. 以后向此MDL 写入数据就代表向文件写入数据. 调用参数中有FILE_BOJECT 描述要写的目标文件.
FastIoMdlWriteComplete, 写操作完成. FSD 回收MDL.
FastIoReadCompressed, 当此调用被调用时, 读到的数据是压缩后的.应该兼容于标准的NT 提供的压缩库. 因为调用者负责解压缩.
FastIoWriteCompressed,当此调用被调用时, 可以将数据是压缩后存储.
FastIoMdlReadCompressed/FastIoMdlReadCompleteCompressed, MDL 版本的压缩读. 当后一个接口被调用时,MDL 必须被释放.
FastIoMdlWriteCompressed/FastIoMdlWriteCompleteCompressed, MDL 版本的压缩写.当后一个接口被调用时,MDL 必须被释放.
FastIoQueryOpen, 这不是打开文件的操作. 但是却提供了一个IRP_MJ_CREATE 的IRP. 我在以前版本的
SECUSTAR 的软件中错误地实现了功能. 这个操作是打开文件/获取文件基本信息/关闭文件的一个操作.
FastIoReleaseForModWrite,释放FastIoAcquireForModWrite 调用所占有的LOCK.
FastIoAcquireForCcFlush/FastIoReleaseForCcFlush FsRtl 会调用此接口,在LAZY WRITE 线程将要把修改后的文件数据写入前调用.获取文件锁.
转自:http://blog.csdn.net/syf442/article/details/4738107