首页 > 代码库 > 一个简单的文件系统过滤驱动框架

一个简单的文件系统过滤驱动框架

        很多人认为文件系统过滤驱动很复杂,其实也有一定道理,因为需要有很多细节需要考虑到,这是一个简单的文件系统过滤驱动,抛去了大部分细节,留下了一个简单的框架,其实这样文件系统过滤驱动就变得蛮简单的,很多接口可以不用实现,只要知道大致流程,其它都将会很清晰。

#define DBG 1

#include <ntifs.h>
#include "fsfilter.h"

PDEVICE_OBJECT g_Cdo;
PDRIVER_OBJECT g_MyDriver;

NTSTATUS 
DriverEntry ( 
    __in struct _DRIVER_OBJECT  *DriverObject,
    __in PUNICODE_STRING  RegistryPath 
    )
{
    int i = 0;
    UNICODE_STRING DeviceName;
    NTSTATUS Status;

    KdPrintThisFunction();

    g_MyDriver = DriverObject;

    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
        DriverObject->MajorFunction[i] = FsfPassThrough;
    }

    DriverObject->MajorFunction[IRP_MJ_CREATE] = FsfCreate;
    DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = FsfCreate;
    DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = FsfCreate;
    DriverObject->MajorFunction[IRP_MJ_READ] = FsfRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = FsfWrite;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsfFsControl;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsfCleanupClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsfCleanupClose;

    DriverObject->FastIoDispatch = (PFAST_IO_DISPATCH)ExAllocatePool(NonPagedPool, sizeof(FAST_IO_DISPATCH));
    if (DriverObject->FastIoDispatch == NULL) {
        KdPrint((FSF_MODULE_NAME_PREFIX "Allocate fast io dispatch rotine memory failed.\n"));
        return STATUS_FAILED_DRIVER_ENTRY;
    }

    RtlZeroMemory(DriverObject->FastIoDispatch, sizeof(FAST_IO_DISPATCH));

    DriverObject->FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
    DriverObject->FastIoDispatch->FastIoCheckIfPossible = FsfFastIoCheckIfPossible;
    DriverObject->FastIoDispatch->FastIoRead = FsfFastIoRead;
    DriverObject->FastIoDispatch->FastIoWrite = FsfFastIoWrite;
    DriverObject->FastIoDispatch->FastIoQueryBasicInfo = FsfFastIoQueryBasicInfo;
    DriverObject->FastIoDispatch->FastIoQueryStandardInfo = FsfFastIoQueryStandardInfo;
    DriverObject->FastIoDispatch->FastIoLock = FsfFastIoLock;
    DriverObject->FastIoDispatch->FastIoUnlockSingle = FsfFastIoUnlockSingle;
    DriverObject->FastIoDispatch->FastIoUnlockAll = FsfFastIoUnlockAll;
    DriverObject->FastIoDispatch->FastIoUnlockAllByKey = FsfFastIoUnlockAllByKey;
    DriverObject->FastIoDispatch->FastIoDeviceControl = FsfFastIoDeviceControl;
    DriverObject->FastIoDispatch->FastIoDetachDevice = FsfFastIoDetachDevice;
    DriverObject->FastIoDispatch->FastIoQueryNetworkOpenInfo = FsfFastIoQueryNetworkOpenInfo;
    DriverObject->FastIoDispatch->MdlRead = FsfFastIoMdlRead;
    DriverObject->FastIoDispatch->MdlReadComplete = FsfFastIoMdlReadComplete;
    DriverObject->FastIoDispatch->PrepareMdlWrite = FsfFastIoPrepareMdlWrite;
    DriverObject->FastIoDispatch->MdlWriteComplete = FsfFastIoWriteComplete;
    DriverObject->FastIoDispatch->FastIoReadCompressed = FsfFastIoReadCompressed;
    DriverObject->FastIoDispatch->FastIoWriteCompressed = FsfFastIoWriteCompressed;
    DriverObject->FastIoDispatch->MdlReadCompleteCompressed = FsfFastIoReadCompleteCompressed;
    DriverObject->FastIoDispatch->MdlWriteCompleteCompressed = FsfFastIoWriteCompleteCompressed;
    DriverObject->FastIoDispatch->FastIoQueryOpen = FsfFastIoQueryOpen;

    DriverObject->DriverUnload = FsfUnload;

    // 生成一个控制设备 CDO
    RtlInitUnicodeString(&DeviceName, L"\\FileSystem\\Filters\\FsFilter");
    Status = IoCreateDevice(DriverObject,
                            0,
                            &DeviceName,
                            FILE_DEVICE_DISK_FILE_SYSTEM,
                            FILE_DEVICE_SECURE_OPEN,
                            FALSE,
                            &g_Cdo);
    if (!NT_SUCCESS(Status)) {
        KdPrint((FSF_MODULE_NAME_PREFIX "Create the device failed.\n"));
        goto Fail;
    }

    // 设置文件系统加载和注销回调
    Status = IoRegisterFsRegistrationChange(DriverObject, FsfFsNotification);
    if (!NT_SUCCESS(Status)) {
        KdPrint((FSF_MODULE_NAME_PREFIX "Register file system chang notification failed!\n"));
        goto Fail;
    }

    return STATUS_SUCCESS;

Fail:
    if (DriverObject->FastIoDispatch != NULL) {
        ExFreePool(DriverObject->FastIoDispatch);
    }

    if (g_Cdo != NULL) {
        IoDeleteDevice(g_Cdo);
    }

    return Status;
}

NTSTATUS
FsfPassThrough (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __inout struct _IRP *Irp
    )
{
    PFSF_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;

    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
}

VOID
FsfUnload (
    __in struct _DRIVER_OBJECT *DriverObject
    )
{
    PDEVICE_OBJECT MyDevice;

    KdPrintThisFunction();

    IoUnregisterFsRegistrationChange(DriverObject, FsfFsNotification);

    MyDevice = DriverObject->DeviceObject;
    while (MyDevice != NULL) {
        PDEVICE_OBJECT TempDevice = MyDevice->NextDevice;

        // 如果是不是我的控制设备,则面要解除附加
        if (!IsMyControlDeivce(MyDevice)) {
            // 如果是文件系统控制设备的过滤设备或文件系统卷设备的过滤设备
            if (IsMyFilterDevice(MyDevice)) {
                PFSF_DEVICE_EXTENSION DeviceExtension = MyDevice->DeviceExtension;
                IoDetachDevice(DeviceExtension->AttachedToDeviceObject);
                KdPrintWithFuncPrefix("Deattach the fs cdo or volime filter.\n");
            }
        }
        
        IoDeleteDevice(MyDevice);
        MyDevice = TempDevice;
    }

}

NTSTATUS
FsfReadCompletion (
    __in PDEVICE_OBJECT DeviceObject,
    __in PIRP Irp,
    __in_xcount_opt("varies") PVOID Context
    )
{
    PKEVENT WaitEvent = Context;

    KeSetEvent(WaitEvent, IO_NO_INCREMENT, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
FsfCreate (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __inout struct _IRP *Irp
    )
{
    PFSF_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
    KEVENT WaitEvent;
    NTSTATUS Status;
    POBJECT_NAME_INFORMATION NameInfo;
    char Buffer[512] = {0};
    ULONG ReturnLength = 0;

    //KdPrintThisFunction();

    // 如果是我的控制设备,则直接完成
    if (IsMyControlDeivce(DeviceObject)) {
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_SUCCESS;

        return STATUS_SUCCESS;
    }

    // 如果是我的文件系统控制设备的过滤设备(控制设备过滤设备没有保存存储卷设备),则直接下发
    if (DeviceExtension == NULL) {
        return FsfPassThrough(DeviceObject, Irp);
    }

    KeInitializeEvent(&WaitEvent, NotificationEvent, FALSE);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, FsfReadCompletion, &WaitEvent, TRUE, TRUE, TRUE);
    Status = IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
    if (Status == STATUS_PENDING) {
        KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, FALSE);
    }

    NameInfo = (POBJECT_NAME_INFORMATION)Buffer;
    ObQueryNameString(IoStackLocation->FileObject, NameInfo, sizeof(Buffer), &ReturnLength);

    // 打印出文件名
    KdPrint(("Create: %S.\n", NameInfo->Name.Buffer));

    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return Irp->IoStatus.Status;
}

NTSTATUS
FsfRead (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __inout struct _IRP *Irp
    )
{
    PFSF_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
    LARGE_INTEGER Offset;
    ULONG Length;

    // 如果是我的控制设备,则直接完成
    if (IsMyControlDeivce(DeviceObject)) {
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_SUCCESS;

        return STATUS_SUCCESS;
    }

    // 如果是我的文件系统控制设备的过滤设备(控制设备过滤设备没有保存存储卷设备),则直接下发
    if (DeviceExtension == NULL) {
        return FsfPassThrough(DeviceObject, Irp);
    }

    // 下面是对文件系统卷设备的过滤处理
    Offset.QuadPart = IoStackLocation->Parameters.Read.ByteOffset.QuadPart;
    Length = IoStackLocation->Parameters.Read.Length;
    //KdPrintWithFuncPrefix("Read - ");
    //KdPrint(("Offset (0x%08x, 0x%08x), Length (0x%08x).\n", Offset.HighPart, Offset.LowPart, Length));

    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
}

NTSTATUS
FsfWrite (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __inout struct _IRP *Irp
    )
{
    PFSF_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
    LARGE_INTEGER Offset;
    ULONG Length;

    // 如果是我的控制设备,则直接完成
    if (IsMyControlDeivce(DeviceObject)) {
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_SUCCESS;

        return STATUS_SUCCESS;
    }

    // 如果是我的文件系统控制设备的过滤设备(控制设备过滤设备没有保存存储卷设备),则直接下发
    if (DeviceExtension == NULL) {
        return FsfPassThrough(DeviceObject, Irp);
    }

    // 下面是对文件系统卷设备的过滤处理
    Offset.QuadPart = IoStackLocation->Parameters.Write.ByteOffset.QuadPart;
    Length = IoStackLocation->Parameters.Write.Length;
    //KdPrintWithFuncPrefix("Write - ");
    //KdPrint(("Offset (0x%08x, 0x%08x), Length (0x%08x).\n", Offset.HighPart, Offset.LowPart, Length));

    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
}

/*
 * 卷挂载完成事件
 * 在这里直接进行绑定有一定的风险,因为此时中断级别很高,是 DISPATCH_LEVEL,
 * 所以进行了推迟绑定,这里只是设置一下事件。
 */
NTSTATUS
FsfMountVolumeCompletion (
    __in PDEVICE_OBJECT DeviceObject,
    __in PIRP Irp,
    __in_xcount_opt("varies") PVOID Context
    )
{
    PKEVENT WaitEvent = (PKEVENT)Context;

    KeSetEvent(WaitEvent, IO_NO_INCREMENT, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
FsfControlMountVolume (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __inout struct _IRP *Irp
    )
{
    PDEVICE_OBJECT StorageDevice;
    PDEVICE_OBJECT MyDevice;
    NTSTATUS Status;
    PFSF_DEVICE_EXTENSION DeviceExtension;
    ULONG ReturnLength = 0;
    KEVENT CompletionEvent;
    PFSF_DEVICE_EXTENSION MyCdoFilterDeviceExtension = DeviceObject->DeviceExtension;
    char Buff[512];
    POBJECT_NAME_INFORMATION NameInfo;

    // 记录下实际存储媒介设备对象,即磁盘卷设备对象,以便后面可以取回 VPB
    // Vpb->DeviceObject 才是文件系统卷设备, 这是我们需要挂接的设备,在该 IRP 完成后,它就是有意思的对象了
    StorageDevice = IoGetCurrentIrpStackLocation(Irp)->Parameters.MountVolume.Vpb->RealDevice;
    Status = IoCreateDevice(g_MyDriver,
                            sizeof(FSF_DEVICE_EXTENSION),
                            NULL,
                            DeviceObject->DeviceType,
                            0,
                            FALSE,
                            &MyDevice);

    DeviceExtension = MyDevice->DeviceExtension;
    DeviceExtension->StorageDevice = StorageDevice;
    DeviceExtension->TypeFlag = FSF_DEVICE_FLAG;

    // 记录下存储设备的名字
    RtlInitEmptyUnicodeString(&DeviceExtension->AttachedToDeviceName, 
                              DeviceExtension->AttachedToDeviceNameBuff, 
                              sizeof(DeviceExtension->AttachedToDeviceNameBuff));
    NameInfo = (POBJECT_NAME_INFORMATION)Buff;
    ObQueryNameString(StorageDevice,
                      NameInfo, 
                      sizeof(Buff), 
                      &ReturnLength);
    RtlCopyUnicodeString(&DeviceExtension->AttachedToDeviceName, &NameInfo->Name);

    // 调用下层驱动并等待其完成
    KeInitializeEvent(&CompletionEvent, NotificationEvent, FALSE);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, FsfMountVolumeCompletion, &CompletionEvent, TRUE, TRUE, TRUE);
    // 发送给我的控制设备所附加的下层对象
    KdPrint(("Call next fs cdo (0x%08x).\n", MyCdoFilterDeviceExtension->AttachedToDeviceObject));
    Status = IoCallDriver(MyCdoFilterDeviceExtension->AttachedToDeviceObject, Irp);
    if (Status == STATUS_PENDING) {
        KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, FALSE);
    }

    if (NT_SUCCESS(Irp->IoStatus.Status)) {
        // 这里可以检查 Irp 中 vpb 值是否改变,有些可插拔设备是会改变的

        PDEVICE_OBJECT FsVolumeDevice = StorageDevice->Vpb->DeviceObject;

        // 由于设备的一些标志在前面没有初始化过,此时文件系统卷设备已经可以,可以根据它来初始化我们的过滤驱动标识了
        if (FsVolumeDevice->Flags & DO_BUFFERED_IO) {
            MyDevice->Flags |= DO_BUFFERED_IO;
        }

        if (FsVolumeDevice->Flags & DO_DIRECT_IO) {
            MyDevice->Flags |= DO_DIRECT_IO;
        }

        MyDevice->Flags &= ~DO_DEVICE_INITIALIZING;

        IoAttachDeviceToDeviceStackSafe(MyDevice, FsVolumeDevice, &DeviceExtension->AttachedToDeviceObject);

        KdPrintWithFuncPrefix("Attached a fs volume deivce.\n");
    } else {
        IoDeleteDevice(MyDevice);
        KdPrintWithFuncPrefix("Attach fs volume deivce failed");
        KdPrint((" (0x%08x).\n", Irp->IoStatus.Status));
    }
    
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return Irp->IoStatus.Status;
}

/*
 * 当文件系统的卷被挂载或解挂载时,这个函数会被调用。
 * 本驱动的控制设备和文件系统控制设备的过滤设备共用这些例程。
 * 暂不考虑控制设备发过来的请求,一般也不会有这样的请求产生。
 */
NTSTATUS
FsfFsControl (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __inout struct _IRP *Irp
    )
{
    PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
    PFSF_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;

    KdPrintThisFunction();

    // 如果是我的控制设备,则直接完成
    if (IsMyControlDeivce(DeviceObject)) {
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_SUCCESS;
        KdPrintWithFuncPrefix("Is my cdo.\n");
        return STATUS_SUCCESS;
    }

    // 主要处理文件系统控制设备的过滤设备
    switch (IoStackLocation->MinorFunction) {
    case IRP_MN_MOUNT_VOLUME:
        // 文件系统卷被挂载
        return FsfControlMountVolume(DeviceObject, Irp);
    case IRP_MN_LOAD_FILE_SYSTEM:
        KdPrintWithFuncPrefix("Load file system.\n");
        break;
    case IRP_MN_USER_FS_REQUEST:
        KdPrintWithFuncPrefix("User fs request.\n");
        if (IoStackLocation->Parameters.FileSystemControl.FsControlCode == FSCTL_DISMOUNT_VOLUME) {
            // 暂不处理文件系统卷被卸载的情况
        }
        break;
    }

    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
}

NTSTATUS
FsfCleanupClose (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __inout struct _IRP *Irp
    )
{
    PFSF_DEVICE_EXTENSION DeviceExtension;

    //KdPrintThisFunction();

    // 如果是我的控制设备,则直接完成
    if (IsMyControlDeivce(DeviceObject)) {
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_SUCCESS;

        return STATUS_SUCCESS;
    }

    DeviceExtension = DeviceObject->DeviceExtension;

    IoSkipCurrentIrpStackLocation(Irp);

    return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
}

BOOLEAN
FsfFastIoCheckIfPossible (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in ULONG Length,
    __in BOOLEAN Wait,
    __in ULONG LockKey,
    __in BOOLEAN CheckForReadOperation,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoRead (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in ULONG Length,
    __in BOOLEAN Wait,
    __in ULONG LockKey,
    __out PVOID Buffer,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoWrite (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in ULONG Length,
    __in BOOLEAN Wait,
    __in ULONG LockKey,
    __in PVOID Buffer,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoQueryBasicInfo (
    __in struct _FILE_OBJECT *FileObject,
    __in BOOLEAN Wait,
    __out PFILE_BASIC_INFORMATION Buffer,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoQueryStandardInfo (
    __in struct _FILE_OBJECT *FileObject,
    __in BOOLEAN Wait,
    __out PFILE_STANDARD_INFORMATION Buffer,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoLock (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in PLARGE_INTEGER Length,
    __in PEPROCESS ProcessId,
    __in ULONG Key,
    __in BOOLEAN FailImmediately,
    __in BOOLEAN ExclusiveLock,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoUnlockSingle (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in PLARGE_INTEGER Length,
    __in PEPROCESS ProcessId,
    __in ULONG Key,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoUnlockAll (
    __in struct _FILE_OBJECT *FileObject,
    __in PEPROCESS ProcessId,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoUnlockAllByKey (
    __in struct _FILE_OBJECT *FileObject,
    __in PVOID ProcessId,
    __in ULONG Key,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoDeviceControl (
    __in struct _FILE_OBJECT *FileObject,
    __in BOOLEAN Wait,
    __in_opt PVOID InputBuffer,
    __in ULONG InputBufferLength,
    __out_opt PVOID OutputBuffer,
    __in ULONG OutputBufferLength,
    __in ULONG IoControlCode,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

VOID
FsfFastIoDetachDevice (
    __in struct _DEVICE_OBJECT *SourceDevice,
    __in struct _DEVICE_OBJECT *TargetDevice
    )
{
}

BOOLEAN
FsfFastIoQueryNetworkOpenInfo (
    __in struct _FILE_OBJECT *FileObject,
    __in BOOLEAN Wait,
    __out struct _FILE_NETWORK_OPEN_INFORMATION *Buffer,
    __out struct _IO_STATUS_BLOCK *IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoMdlRead (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in ULONG Length,
    __in ULONG LockKey,
    __out PMDL *MdlChain,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoMdlReadComplete (
    __in struct _FILE_OBJECT *FileObject,
    __in PMDL MdlChain,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoPrepareMdlWrite (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in ULONG Length,
    __in ULONG LockKey,
    __out PMDL *MdlChain,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoWriteComplete (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in PMDL MdlChain,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoReadCompressed (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in ULONG Length,
    __in ULONG LockKey,
    __out PVOID Buffer,
    __out PMDL *MdlChain,
    __out PIO_STATUS_BLOCK IoStatus,
    __out struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
    __in ULONG CompressedDataInfoLength,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoWriteCompressed (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in ULONG Length,
    __in ULONG LockKey,
    __in PVOID Buffer,
    __out PMDL *MdlChain,
    __out PIO_STATUS_BLOCK IoStatus,
    __in struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
    __in ULONG CompressedDataInfoLength,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoReadCompleteCompressed (
    __in struct _FILE_OBJECT *FileObject,
    __in PMDL MdlChain,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoWriteCompleteCompressed (
    __in struct _FILE_OBJECT *FileObject,
    __in PLARGE_INTEGER FileOffset,
    __in PMDL MdlChain,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

BOOLEAN
FsfFastIoQueryOpen (
    __inout struct _IRP *Irp,
    __out PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
    __in struct _DEVICE_OBJECT *DeviceObject
    )
{
    return FALSE;
}

/*
 * 文件系统激活和注销时的回调
 * DeviceObject: 为文件系统控制设备,但为了提高效率,也有可能是文件系统识别器设备(该设备一般由 Fs_Rec 生成);
 * FsActive:     是激活还是注销
 */
VOID
FsfFsNotification (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __in BOOLEAN FsActive
    )
{
    UNICODE_STRING DriverName;
    POBJECT_NAME_INFORMATION NameInfo;
    ULONG ReturnLength = 0;
    NTSTATUS Status = STATUS_SUCCESS;
    PDEVICE_OBJECT NewDeviceObject;
    PFSF_DEVICE_EXTENSION DeviceExtension;
    char Buff[512];

    KdPrintThisFunction();

    // 检查是不是想要处理文件系统设备类型
    if (DeviceObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM /*&&
        DeviceObject->DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM*/) {
        return;
    }

    if (FsActive) {
        // 如果是激活

        KdPrintWithFuncPrefix("Active.\n");

        // 检查该设备是否为微软的文件系统识别器设备(是否是 \FileSystem\Fs_Rec 驱动生成的设备, 这种方法现在可行,但不能保证一直有效)
        RtlInitUnicodeString(&DriverName, L"\\FileSystem\\Fs_Rec");
        NameInfo = (POBJECT_NAME_INFORMATION)Buff;
        ObQueryNameString(DeviceObject->DriverObject, NameInfo, sizeof(Buff), &ReturnLength);
        if (RtlCompareUnicodeString(&NameInfo->Name, &DriverName, TRUE) == 0) {
            KdPrintWithFuncPrefix("A file system recognizer here!.\n");
            return;
        }



        // 创建过滤设备, 匿名,类型和属性与文件系统设备相同
        Status = IoCreateDevice(g_MyDriver,
                                sizeof(FSF_DEVICE_EXTENSION),
                                NULL,
                                DeviceObject->DeviceType,
                                0,
                                FALSE,
                                &NewDeviceObject);
        if (!NT_SUCCESS(Status)) {
            return;
        }

        // 设置新设备的属性
        if (DeviceObject->Flags & DO_BUFFERED_IO) {
            NewDeviceObject->Flags |= DO_BUFFERED_IO;
        }

        if (DeviceObject->Flags & DO_DIRECT_IO) {
            NewDeviceObject->Flags |= DO_DIRECT_IO;
        }

        if (DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) {
            NewDeviceObject->Characteristics |= FILE_DEVICE_SECURE_OPEN;
        }

        DeviceExtension = NewDeviceObject->DeviceExtension;
        IoAttachDeviceToDeviceStackSafe(NewDeviceObject, DeviceObject, &DeviceExtension->AttachedToDeviceObject);
        // 在扩展中打上标志,以识别为该驱动的文件系统控制设备过滤驱动
        DeviceExtension->TypeFlag = FSF_DEVICE_FLAG;

        // 记录控制设备的名字
        RtlInitEmptyUnicodeString(&DeviceExtension->AttachedToDeviceName, DeviceExtension->AttachedToDeviceNameBuff, sizeof(DeviceExtension->AttachedToDeviceNameBuff));
        ObQueryNameString(DeviceObject, NameInfo, sizeof(Buff), &ReturnLength);
        RtlCopyUnicodeString(&DeviceExtension->AttachedToDeviceName, &NameInfo->Name);

        KdPrintWithFuncPrefix("Create and attach the fs control device ");
        KdPrint(("(0x%08x).\n", DeviceObject));

        NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;


        // 前面绑定文件系统控制设备只是为了去监听那些还未被挂载进系统的卷,对于已挂载的文件系统卷需要手动枚举
        // 文件系统驱动生成两种设备,一种为文件系统控制设备(一般来说只生成一个 CDO),即此函数传入的设备对象参数,另一种为文件系统卷设备,即我们最终需要挂接并过滤的
        // 文件系统卷设备有可能有多个,文件系统驱动会为每一个该文件系统类型的磁盘卷生成一个文件系统卷设备
        {
            ULONG DeviceCount = 0;
            PDEVICE_OBJECT *DeviceList;
            PDEVICE_OBJECT StorageDevice;
            PDEVICE_OBJECT MyDevice;
            PFSF_DEVICE_EXTENSION DeviceExtension;
            ULONG i = 0;

            IoEnumerateDeviceObjectList(DeviceObject->DriverObject, NULL, 0, &DeviceCount);
            DeviceList = (PDEVICE_OBJECT *)ExAllocatePool(NonPagedPool, DeviceCount * sizeof(PDEVICE_OBJECT));
            IoEnumerateDeviceObjectList(DeviceObject->DriverObject, DeviceList, DeviceCount * sizeof(PDEVICE_OBJECT), &DeviceCount);
            for (; i < DeviceCount; i++) {
                PDEVICE_OBJECT DeviceObjectEntry = DeviceList[i];

                // 如果该设备对象是文件系统驱动的控制对象,则略过, 如果是其它设备类型的也略过,如 U 盘类型呀,因为上面我们只关注 Disk 类型
                // 暂不考虑已经被我们挂接过的设备
                if (DeviceObjectEntry == DeviceObject || DeviceObjectEntry->DeviceType != DeviceObject->DeviceType) {    
                    continue;
                }

                // 得到卷设备驱动
                IoGetDiskDeviceObject(DeviceObjectEntry, &StorageDevice);
                Status = IoCreateDevice(g_MyDriver,
                                        sizeof(FSF_DEVICE_EXTENSION),
                                        NULL,
                                        DeviceObject->DeviceType,
                                        0,
                                        FALSE,
                                        &MyDevice);

                DeviceExtension = MyDevice->DeviceExtension;
                DeviceExtension->StorageDevice = StorageDevice;
                DeviceExtension->TypeFlag = FSF_DEVICE_FLAG;

                // 记录下存储设备的名字
                RtlInitEmptyUnicodeString(&DeviceExtension->AttachedToDeviceName, 
                                          DeviceExtension->AttachedToDeviceNameBuff, 
                                          sizeof(DeviceExtension->AttachedToDeviceNameBuff));
                NameInfo = (POBJECT_NAME_INFORMATION)Buff;
                ObQueryNameString(StorageDevice,
                                  NameInfo, 
                                  sizeof(Buff), 
                                  &ReturnLength);
                RtlCopyUnicodeString(&DeviceExtension->AttachedToDeviceName, &NameInfo->Name);

                // 由于设备的一些标志在前面没有初始化过,此时文件系统卷设备已经可以,可以根据它来初始化我们的过滤驱动标识了
                if (DeviceObjectEntry->Flags & DO_BUFFERED_IO) {
                    MyDevice->Flags |= DO_BUFFERED_IO;
                }

                if (DeviceObjectEntry->Flags & DO_DIRECT_IO) {
                    MyDevice->Flags |= DO_DIRECT_IO;
                }

                MyDevice->Flags &= ~DO_DEVICE_INITIALIZING;

                IoAttachDeviceToDeviceStackSafe(MyDevice, DeviceObjectEntry, &DeviceExtension->AttachedToDeviceObject);
                KdPrintWithFuncPrefix("Create and attach a fs volume device ");
                KdPrint(("(0x%08x).\n", MyDevice));
            }
        }
    } else {
        // 如果是注销

        // 遍历该设备上的所有附加设备,如果是我的设备,则去掉附加并删除
        PDEVICE_OBJECT MyDeivce = DeviceObject->AttachedDevice;

        KdPrintWithFuncPrefix("Inactive.\n");

        while (MyDeivce != NULL) {
            PDEVICE_OBJECT TempDevice = MyDeivce->AttachedDevice;

            if (IsMyControlDeivce(MyDeivce)) {
                IoDetachDevice(MyDeivce);
                IoDeleteDevice(MyDeivce);
                return;
            }

            MyDeivce = TempDevice;
        }
    }
}


一个简单的文件系统过滤驱动框架