之前用的驱动例子是一个功能型驱动,只不过它操作的是一个虚拟设备。这个驱动创建的FDO(功能设备对象)是附在虚拟总线驱动创建的虚拟PDO之上的。这次来介绍一下不同于功能型驱动的过滤驱动。过滤驱动可以在功能型驱动的上面,称之为上层过滤驱动,或者高层,反正就这个意思。过滤驱动在功能型驱动下面,称之为下层过滤驱动。看示意图:
从名字上就可以知道过滤驱动是干啥用的。就是起过滤作用。比如:
1. 可以对写入硬盘的数据做加密,然后读取的时候解密,这样对于用户来说,根本不知道有加密解密的过程,然后存在硬盘上的数据是加密的。
2. 可以对已有驱动做一些扩展,或者改变已有驱动的功能。比如已有驱动一次只能写1024字节的数据,那么过滤驱动可以扩展到任何长度,然后分段调用已有驱动就是了。
我们来尝试给之前用的驱动加个过滤驱动。这个过滤驱动代码,我是从前面的驱动copy过来的,然后修改一下。
其实过滤驱动跟功能型驱动从代码上看也没有太多不同,需要注意的是:
1. 因为过滤驱动是附在FDO上的,那么通常过滤驱动都不需要一个名字,因为caller不会直接调用过滤驱动;
2. 因为不知道下层驱动是缓冲模式还是直接模式操作内存,那么通常过滤驱动会同时支持缓冲和直接方式。
看一下AddDevice里面创建过滤驱动设备对象的代码:
NTSTATUS CreateFDO(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
{
NTSTATUS status;
PDEVICE_OBJECT fido;
//创建FDO(Function Device Object)
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,//过滤驱动,无需名字
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&fido);
if( !NT_SUCCESS(status))
return status;
KdPrint(("Create filter device\n"));
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fido->DeviceExtension;
pdx->fdo = fido;
//将FDO附加在PDO上面,并且将Extension中的NextStackDevice指向FDO的下层设备。如果PDO上面有过滤驱动的话,NextStackDevice就是过滤驱动,如果没有就是PDO。
pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fido, pdo);
if (pdx->NextStackDevice == NULL)
{
KdPrint(("attach failed\n"));
IoDeleteDevice(fido);
return STATUS_DEVICE_REMOVED;
}
fido->Flags |= DO_BUFFERED_IO | DO_DIRECT_IO| DO_POWER_PAGABLE;//
fido->