Click here to Skip to main content
15,891,513 members
Articles / Programming Languages / C

File System Filter Driver Tutorial

,
Rate me:
Please Sign up or sign in to vote.
4.89/5 (118 votes)
10 Jun 2015CPOL9 min read 1.1M   12K   303  
This tutorial will show you how to develop a simple file system filter driver.
#include "FsFilter.h"

/////////////////////////////////////////////////////////////////////////////
// Fast-IO Handlers

BOOLEAN FsFilterFastIoCheckIfPossible(
    __in PFILE_OBJECT       FileObject,
    __in PLARGE_INTEGER     FileOffset,
    __in ULONG              Length,
    __in BOOLEAN            Wait,
    __in ULONG              LockKey,
    __in BOOLEAN            CheckForReadOperation,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoCheckIfPossible)) 
    {
        return (fastIoDispatch->FastIoCheckIfPossible)(
            FileObject,
            FileOffset,
            Length,
            Wait,
            LockKey,
            CheckForReadOperation,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoRead(
    __in PFILE_OBJECT       FileObject,
    __in PLARGE_INTEGER     FileOffset,
    __in ULONG              Length,
    __in BOOLEAN            Wait,
    __in ULONG              LockKey,
    __out PVOID             Buffer,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoRead)) 
    {
        return (fastIoDispatch->FastIoRead)(
            FileObject,
            FileOffset,
            Length,
            Wait,
            LockKey,
            Buffer,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoWrite(
    __in PFILE_OBJECT       FileObject,
    __in PLARGE_INTEGER     FileOffset,
    __in ULONG              Length,
    __in BOOLEAN            Wait,
    __in ULONG              LockKey,
    __in PVOID              Buffer,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoWrite)) 
    {
        return (fastIoDispatch->FastIoWrite)(
            FileObject,
            FileOffset,
            Length,
            Wait,
            LockKey,
            Buffer,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoQueryBasicInfo(
    __in PFILE_OBJECT       FileObject,
    __in BOOLEAN            Wait,
    __out PFILE_BASIC_INFORMATION Buffer,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoQueryBasicInfo)) 
    {

        return (fastIoDispatch->FastIoQueryBasicInfo)(
            FileObject,
            Wait,
            Buffer,
            IoStatus,
            nextDeviceObject);
    }
    
    return FALSE;
}

BOOLEAN FsFilterFastIoQueryStandardInfo(
    __in PFILE_OBJECT       FileObject,
    __in BOOLEAN            Wait,
    __out PFILE_STANDARD_INFORMATION Buffer,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoQueryStandardInfo)) 
    {
        return (fastIoDispatch->FastIoQueryStandardInfo)(
            FileObject,
            Wait,
            Buffer,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoLock(
    __in PFILE_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 PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoLock)) 
    {
        return (fastIoDispatch->FastIoLock)(
            FileObject,
            FileOffset,
            Length,
            ProcessId,
            Key,
            FailImmediately,
            ExclusiveLock,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoUnlockSingle(
    __in PFILE_OBJECT       FileObject,
    __in PLARGE_INTEGER     FileOffset,
    __in PLARGE_INTEGER     Length,
    __in PEPROCESS          ProcessId,
    __in ULONG              Key,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoUnlockSingle)) 
    {
        return (fastIoDispatch->FastIoUnlockSingle)(
            FileObject,
            FileOffset,
            Length,
            ProcessId,
            Key,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoUnlockAll(
    __in PFILE_OBJECT       FileObject,
    __in PEPROCESS          ProcessId,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoUnlockAll)) 
    {
        return (fastIoDispatch->FastIoUnlockAll)(
            FileObject,
            ProcessId,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoUnlockAllByKey(
    __in PFILE_OBJECT       FileObject,
    __in PVOID              ProcessId,
    __in ULONG              Key,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoUnlockAllByKey))
    {
        return (fastIoDispatch->FastIoUnlockAllByKey)(
            FileObject,
            ProcessId,
            Key,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoDeviceControl(
    __in PFILE_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 PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoDeviceControl)) 
    {
        return (fastIoDispatch->FastIoDeviceControl)(
            FileObject,
            Wait,
            InputBuffer,
            InputBufferLength,
            OutputBuffer,
            OutputBufferLength,
            IoControlCode,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

VOID FsFilterFastIoDetachDevice(
    __in PDEVICE_OBJECT     SourceDevice,
    __in PDEVICE_OBJECT     TargetDevice
    )
{
    //
    //  Detach from the file system's volume device object.
    //

    IoDetachDevice(TargetDevice);
    IoDeleteDevice(SourceDevice);
}

BOOLEAN FsFilterFastIoQueryNetworkOpenInfo(
    __in PFILE_OBJECT       FileObject,
    __in BOOLEAN            Wait,
    __out PFILE_NETWORK_OPEN_INFORMATION Buffer,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoQueryNetworkOpenInfo)) 
    {
        return (fastIoDispatch->FastIoQueryNetworkOpenInfo)(
            FileObject,
            Wait,
            Buffer,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoMdlRead(
    __in PFILE_OBJECT       FileObject,
    __in PLARGE_INTEGER     FileOffset,
    __in ULONG              Length,
    __in ULONG              LockKey,
    __out PMDL*             MdlChain,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlRead)) 
    {
        return (fastIoDispatch->MdlRead)(
            FileObject,
            FileOffset,
            Length,
            LockKey,
            MdlChain,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoMdlReadComplete(
    __in PFILE_OBJECT       FileObject,
    __in PMDL               MdlChain,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlReadComplete)) 
    {
        return (fastIoDispatch->MdlReadComplete)(
            FileObject,
            MdlChain,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoPrepareMdlWrite(
    __in PFILE_OBJECT       FileObject,
    __in PLARGE_INTEGER     FileOffset,
    __in ULONG              Length,
    __in ULONG              LockKey,
    __out PMDL*             MdlChain,
    __out PIO_STATUS_BLOCK  IoStatus,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, PrepareMdlWrite)) 
    {
        return (fastIoDispatch->PrepareMdlWrite)(
            FileObject,
            FileOffset,
            Length,
            LockKey,
            MdlChain,
            IoStatus,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoMdlWriteComplete(
    __in PFILE_OBJECT       FileObject,
    __in PLARGE_INTEGER     FileOffset,
    __in PMDL               MdlChain,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlWriteComplete)) 
    {
        return (fastIoDispatch->MdlWriteComplete)(
            FileObject,
            FileOffset,
            MdlChain,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoReadCompressed(
    __in PFILE_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 PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoReadCompressed)) 
    {
        return (fastIoDispatch->FastIoReadCompressed)(
            FileObject,
            FileOffset,
            Length,
            LockKey,
            Buffer,
            MdlChain,
            IoStatus,
            CompressedDataInfo,
            CompressedDataInfoLength,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoWriteCompressed(
    __in PFILE_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 PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoWriteCompressed)) 
    {
        return (fastIoDispatch->FastIoWriteCompressed)(
            FileObject,
            FileOffset,
            Length,
            LockKey,
            Buffer,
            MdlChain,
            IoStatus,
            CompressedDataInfo,
            CompressedDataInfoLength,
            nextDeviceObject );
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoMdlReadCompleteCompressed(
    __in PFILE_OBJECT       FileObject,
    __in PMDL               MdlChain,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlReadCompleteCompressed)) 
    {
        return (fastIoDispatch->MdlReadCompleteCompressed)(
            FileObject,
            MdlChain,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoMdlWriteCompleteCompressed(
    __in PFILE_OBJECT       FileObject,
    __in PLARGE_INTEGER     FileOffset,
    __in PMDL               MdlChain,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlWriteCompleteCompressed)) 
    {
        return (fastIoDispatch->MdlWriteCompleteCompressed)(
            FileObject,
            FileOffset,
            MdlChain,
            nextDeviceObject);
    }

    return FALSE;
}

BOOLEAN FsFilterFastIoQueryOpen(
    __in PIRP               Irp,
    __out PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
    __in PDEVICE_OBJECT     DeviceObject
    )
{
    //
    //  Pass through logic for this type of Fast I/O
    //

    PDEVICE_OBJECT    nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch   = nextDeviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoQueryOpen)) 
    {
        BOOLEAN result;
        PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );

        //
        //  Before calling the next filter, we must make sure their device
        //  object is in the current stack entry for the given IRP
        //

        irpSp->DeviceObject = nextDeviceObject;

        result = (fastIoDispatch->FastIoQueryOpen)(
            Irp,
            NetworkInformation,
            nextDeviceObject);

        //
        //  Always restore the IRP back to our device object
        //

        irpSp->DeviceObject = DeviceObject;
        return result;
    }

    return FALSE;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Apriorit Inc.
United States United States
ApriorIT is a software research and development company specializing in cybersecurity and data management technology engineering. We work for a broad range of clients from Fortune 500 technology leaders to small innovative startups building unique solutions.

As Apriorit offers integrated research&development services for the software projects in such areas as endpoint security, network security, data security, embedded Systems, and virtualization, we have strong kernel and driver development skills, huge system programming expertise, and are reals fans of research projects.

Our specialty is reverse engineering, we apply it for security testing and security-related projects.

A separate department of Apriorit works on large-scale business SaaS solutions, handling tasks from business analysis, data architecture design, and web development to performance optimization and DevOps.

Official site: https://www.apriorit.com
Clutch profile: https://clutch.co/profile/apriorit
This is a Organisation

33 members

Written By
Team Leader Apriorit
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions