v
WDK(Windows Driver Kit)是一种完全集成的驱动程序开发系统,它包含 Windows DDK,用于测试 Windows 驱动器的可靠性和稳定性.
WDM 是 Win32设备驱动程序体系结构
v
CreateFile函数创建或打开下列对象,并返回一个可以用来访问这些对象的句柄。
文件
pipes
邮槽
通信资源
磁盘驱动器(仅适用于windowsNT)
控制台
文件夹(仅用于打开)
HANDLE CreateFile(
LPCTSTR lpFileName, //指向文件名的指针
DWORD dwDesiredAccess, //访问模式(写/读)
DWORD dwShareMode, //共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针
DWORD dwCreationDisposition, //如何创建
DWORD dwFlagsAndAttributes, //文件属性
HANDLE hTemplateFile //用于复制文件句柄
);
v
CreateFile打开一个设备,准备进行数据传输。返回一个与设备相关的句柄。
CloseHandle关闭一个由CreateFile打开的设备。
ReadFile从设备读取数据。
WriteFile向设备写数据。
"DeviceIoControl"对设备进行一些自定义的操作,比如更改设置等。
v
驱动程序对象(DriverObject)
该对象在驱动程序被启动时由I/O管理器创建,保存有该程序处理各种请求的过程入口、该程序所驱动的全部设备对象的链表等。
DriverObject 就是你所写的驱动对应的DRIVER_OBJECT, 是系统在加载你的驱动时候所分配的。RegisteryPath 是专用于你记录你的驱动相关参数的注册表路径。这两者都由系统分配并通过这两个参数传递给你。DriverObject 重要之处,在于它拥有一组函数指针,称为dispatch functions.
开发驱动的主要任务就是亲手撰写这些dispatch functions.当系统用到你的驱动,会向你的驱动发送IRP(这是windows 所有驱动的共同工作方式)。你的任务是在dispatch function 中处理这些请求。你可以让irp 失败,也可以成功返回,也可以修改这些irp,甚至可以自己发出irp。
设备对象(DeviceObject)
每发现一个可以驱动的设备,驱动程序调用IoCreateDevice创建一个该对象。该对象有一个指针Device Extension指向一块由驱动程序定义的结构,其中保存有关此设备的如端口号,中断向量等全部信息
设备对象则是指DEVICE_OBJECT.下边简称DO.
但是实际上每个irp 都是针对DO 发出的。只有针对由该驱动所生成的DO 的IRP, 才会发给该驱动来处理。具体的分发函数,决定于DO 下的DriverObject 域。
当一个应用程序打开文件并读写文件的时候,windows 系统将这些请求变成irp 发送给文件系统驱动。
v
服务控制管理程序 SCM
类似于linux的守护进程(在linux或者unix操作系统中在系统的引导的时候会开启很多服务,这些服务
就叫做守护进程)
windows服务在系统启动是加载,用户需在服务控制平台开启或者关闭服务
Driver Service是服务的一个特例,遵循windows服务的协议
v
编译环境配置安装:
安装DDK,输入路径,build编译出。Sys文件。
加载过程:
手动加载&编写程序加载。
NT驱动程序的加载:
1:为NT驱动创建新的服务.
2:开启此项服务
3:关闭此项服务
4:删除NT驱动创建的服务
(1)打开SCM管理器
SC_HANDLE WINAPI OpenSCManager();
成功返回SCM管理器句柄.否则返回NULL
(2)创建服务
SC_HANDLE WINAPI CreateService();
(3)打开服务
SC_HANDLE WINAPI OpenService();
(4)控制服务
BOOL WINAPI ControlService();
(5)关闭SCM管理器
BOOL WINAPI CloseServiceHandle();
v
NT式程序的基本结构:
基本数据结构上面有介绍。驱动对象和设备对象
DriverEntry:入口函数,对驱动程序进行初始化工作,它是由系统进程所调用。
驱动加载的时候,系统进程启动新的线程,调用执行体组件中的对象管理器,创建一个驱动对象。另外,系统进程调用执行体组件中的配置管理程序,查询此驱动程序对应的注册表中的项。
DriverEntry 中,应该做哪些工作。
第一步.生成一个控制设备。当然此前你必须给控制设置指定名称。
第二步.设置Dispatch Functions.
第三步.设置Fast Io Functions.
第四步.编写一个FileSystemNotify 回调函数,在其中绑定刚激活的FS CDO.
第五步.使用IoRegisterFsRegistrationChange 调用注册这个回调函数。
v
注意一下几点:
1) 习惯使用UNICODE_STRING 字符串。这些字符串用Rtl…系列的函数来操作。你应该阅读DDK 帮助,然后熟悉这些字符串的用法。
2) 用KdPrint(())来代替printf 输出信息。这些信息可以在DbgView 中看到。KdPrint(())自身是一个宏,为了完整传入参数所以使用了两重括弧。这个比DbgPrint 调用要稍好。因为在free 版不被编译。
3) 查看DDK 帮助了解生成设备对象IoCreateDevice 的用法。
v
首先需要了解的是:FastIo 是独立于普通的处理IRP 的分发函数之外的另一组接口。但是他们的作用是一样的,就是由驱动处理外部给予的请求。而且所处理的请求也基本相同。NT 下FASTIO 是一套IO 管理器 与DEVICE DRIVER 沟通的另外一套API,在进行基于IRP 为基础的接口调用前, IO 管理器会尝试使用FAST IO 接口来加速各种IO 操作.
其次,文件系统的普通分发例程和fastio 例程都随时有可能被调用。做好的过滤驱动显然应该同时过滤这两套接口。然而,一般都只介绍IRP 过滤的方法。Fastio 接口非常复杂。但是与IRP 过滤是基本一一对应的
v
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 线程将要把修改后的文件数据写入前调用.获取文件锁.
v
应用程序到驱动程序的步骤:
v
加载NT驱动的流程:
v
每个驱动程序有唯一的驱动对象与之对应;
驱动对象的布局:
每个驱动程序会创建一个或多个设备对象:
设备对象的结构:
v
IRP与派遣函数
IRP的处理机制类似windows应用程序中的消息处理机制,驱动程序接收到不同类型的IRP后,会进入不同的派遣函数,在派遣函数中IRP得到处理。
上层应用程序与地层驱动程序通信时,应用程序会发出I/O请求,操作系统讲I/O请求转化为相应的IRP数据。
内核方面的知识:
第六章:windows I/O系统
1,在windows模型下,用于控制外部设备的软件模块叫做设备驱动程序。
2,windowsI/O系统五大部件,I/O管理器,即插即用管理器,电源管理器,wmi例程以及设备驱动程序,
3,I/O管理器:三种基本内核对象:驱动对象,设备对象,文件对象。I/O管理器负责管理和协调这三种对象
4,设备驱动程序的分类
即插即用驱动程序(总线驱动,功能驱动,过滤驱动)
内核扩展驱动程序
文件系统驱动程序
5,三种过滤驱动程序:总线过滤驱动,上层过滤驱动,下层过滤驱动。