⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cancelsafe.c

📁 这是一款驱动过滤程序 能轻松过滤文本文档 幻灯片等程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1999 - 2002  Microsoft Corporation

Module Name:

    cancelSafe.c

Abstract:

    This is the main module of the cancelSafe miniFilter driver.

Environment:

    Kernel mode

--*/

#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>


//
//  Debug flags and helper functions
//

#define CSQ_TRACE_ERROR                     0x00000001
#define CSQ_TRACE_LOAD_UNLOAD               0x00000002
#define CSQ_TRACE_INSTANCE_CALLBACK         0x00000004
#define CSQ_TRACE_CONTEXT_CALLBACK          0x00000008
#define CSQ_TRACE_CBDQ_CALLBACK             0x00000010
#define CSQ_TRACE_PRE_READ                  0x00000020
#define CSQ_TRACE_ALL                       0xFFFFFFFF

#define DebugTrace(Level, Data)               \
    if ((Level) & Globals.DebugLevel) {       \
        DbgPrint Data;                        \
    }

//
//  Memory Pool Tags
//

#define INSTANCE_CONTEXT_TAG              'IqsC'
#define QUEUE_CONTEXT_TAG                 'QqsC'

//
//  Magic file name
//

const UNICODE_STRING CsqFile = RTL_CONSTANT_STRING( L"csqdemo.txt" );


//
//  Prototypes
//


//
//  Queue context data structure
//

typedef struct _QUEUE_CONTEXT {

    FLT_CALLBACK_DATA_QUEUE_IO_CONTEXT CbdqIoContext;

} QUEUE_CONTEXT, *PQUEUE_CONTEXT;

//
//  Instance context data structure
//

typedef struct _INSTANCE_CONTEXT {

    //
    //  Instance for this context.
    //

    PFLT_INSTANCE Instance;

    //
    //  Cancel safe queue members
    //

    FLT_CALLBACK_DATA_QUEUE Cbdq;
    LIST_ENTRY QueueHead;
    FAST_MUTEX Lock;

    //
    //  Flag to control the life/death of the work item thread
    //

    volatile LONG WorkerThreadFlag;

    //
    //  Notify the worker thread that the instance is being torndown
    //

    KEVENT TeardownEvent;

} INSTANCE_CONTEXT, *PINSTANCE_CONTEXT;


typedef struct _CSQ_GLOBAL_DATA {

    ULONG  DebugLevel;

    PFLT_FILTER  FilterHandle;

    NPAGED_LOOKASIDE_LIST OueueContextLookaside;

} CSQ_GLOBAL_DATA;



//
//  Global variables
//

CSQ_GLOBAL_DATA Globals;


//
//  Local function prototypes
//

NTSTATUS
DriverEntry (
    __in PDRIVER_OBJECT DriverObject,
    __in PUNICODE_STRING RegistryPath
    );

NTSTATUS
Unload (
    __in FLT_FILTER_UNLOAD_FLAGS Flags
    );

VOID
ContextCleanup (
    __in PFLT_CONTEXT Context,
    __in FLT_CONTEXT_TYPE ContextType
    );

NTSTATUS
InstanceSetup (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_SETUP_FLAGS Flags,
    __in DEVICE_TYPE VolumeDeviceType,
    __in FLT_FILESYSTEM_TYPE VolumeFilesystemType
    );

NTSTATUS
InstanceQueryTeardown (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
    );

VOID
InstanceTeardownStart (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_TEARDOWN_FLAGS Flags
    );

VOID
InstanceTeardownComplete (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_TEARDOWN_FLAGS Flags
    );

VOID
InitializeDebugLevel (
    __in PUNICODE_STRING RegistryPath
    );

VOID
CsqAcquire(
    __in PFLT_CALLBACK_DATA_QUEUE DataQueue,
    __out PKIRQL Irql
    );
VOID
CsqRelease(
    __in PFLT_CALLBACK_DATA_QUEUE DataQueue,
    __in KIRQL Irql
    );
NTSTATUS
CsqInsertIo(
    __in PFLT_CALLBACK_DATA_QUEUE DataQueue,
    __in PFLT_CALLBACK_DATA Data,
    __in_opt PVOID Context
    );
VOID
CsqRemoveIo(
    __in PFLT_CALLBACK_DATA_QUEUE DataQueue,
    __in PFLT_CALLBACK_DATA Data
    );
PFLT_CALLBACK_DATA
CsqPeekNextIo(
    __in PFLT_CALLBACK_DATA_QUEUE DataQueue,
    __in_opt PFLT_CALLBACK_DATA Data,
    __in_opt PVOID PeekContext
    );
VOID
CsqCompleteCanceledIo(
    __in PFLT_CALLBACK_DATA_QUEUE DataQueue,
    __inout PFLT_CALLBACK_DATA Data
    );

FLT_PREOP_CALLBACK_STATUS
PreRead (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext
    );

VOID
PreReadWorkItemRoutine(
    __in PFLT_GENERIC_WORKITEM WorkItem,
    __in PFLT_FILTER Filter,
    __in PVOID Context
    );

NTSTATUS
PreReadPendIo(
    __in PINSTANCE_CONTEXT InstanceContext
    );

NTSTATUS
PreReadProcessIo(
    __inout PFLT_CALLBACK_DATA Data
    );

VOID
PreReadEmptyQueueAndComplete(
    __in PINSTANCE_CONTEXT InstanceContext
    );

//
//  Assign text sections for each routine.
//

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, InitializeDebugLevel)
#pragma alloc_text(PAGE, Unload)
#pragma alloc_text(PAGE, ContextCleanup)
#pragma alloc_text(PAGE, InstanceSetup)
#pragma alloc_text(PAGE, InstanceQueryTeardown)
#pragma alloc_text(PAGE, InstanceTeardownStart)
#pragma alloc_text(PAGE, InstanceTeardownComplete)
#endif


//
//  Filter driver initialization and unload routines
//

NTSTATUS
DriverEntry (
    __in PDRIVER_OBJECT DriverObject,
    __in PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    This is the initialization routine for this filter driver. It registers
    itself with the filter manager and initializes all its global data structures.

Arguments:

    DriverObject - Pointer to driver object created by the system to
        represent this driver.

    RegistryPath - Unicode string identifying where the parameters for this
        driver are located in the registry.

Return Value:

    Returns STATUS_SUCCESS.

--*/
{
    NTSTATUS Status;

    //
    //  Filters callback routines
    //

    FLT_OPERATION_REGISTRATION callbacks[] = {

        { IRP_MJ_READ,
          FLTFL_OPERATION_REGISTRATION_SKIP_PAGING_IO,
          PreRead,
          NULL },

        { IRP_MJ_OPERATION_END }
    };

    //
    // Filters context registration data structure
    //

    const FLT_CONTEXT_REGISTRATION contextRegistration[] = {

        { FLT_INSTANCE_CONTEXT,
          0,
          ContextCleanup,
          sizeof( INSTANCE_CONTEXT ),
          INSTANCE_CONTEXT_TAG },

        { FLT_CONTEXT_END }
    };

    //
    // Filters registration data structure
    //

    FLT_REGISTRATION filterRegistration = {

        sizeof( FLT_REGISTRATION ),             //  Size
        FLT_REGISTRATION_VERSION,               //  Version
        0,                                      //  Flags
        contextRegistration,                    //  Context
        callbacks,                              //  Operation callbacks
        Unload,                                 //  Filters unload routine
        InstanceSetup,                          //  InstanceSetup routine
        InstanceQueryTeardown,                  //  InstanceQueryTeardown routine
        InstanceTeardownStart,                  //  InstanceTeardownStart routine
        InstanceTeardownComplete,               //  InstanceTeardownComplete routine
        NULL, NULL, NULL                        //  Unused naming support callbacks
    };

    //
    //  Initialize global debug level
    //

    InitializeDebugLevel( RegistryPath );

    DebugTrace( CSQ_TRACE_LOAD_UNLOAD,
                ("[Csq]: CancelSafe!DriverEntry\n") );

    //
    //  Initialize global lookaside list
    //

    ExInitializeNPagedLookasideList( &Globals.OueueContextLookaside,
                                     NULL,
                                     NULL,
                                     0,
                                     sizeof( QUEUE_CONTEXT ),
                                     QUEUE_CONTEXT_TAG,
                                     0 );

    //
    //  Register with the filter manager
    //

    Status = FltRegisterFilter( DriverObject,
                                &filterRegistration,
                                &Globals.FilterHandle );

    if (!NT_SUCCESS( Status )) {

        DebugTrace( CSQ_TRACE_LOAD_UNLOAD | CSQ_TRACE_ERROR,
                    ("[Csq]: Failed to register filter (Status = 0x%x)\n",
                    Status) );

        return Status;
    }

    //
    //  Start filtering I/O
    //

    Status = FltStartFiltering( Globals.FilterHandle );

    if (!NT_SUCCESS( Status )) {

        DebugTrace( CSQ_TRACE_LOAD_UNLOAD | CSQ_TRACE_ERROR,
                    ("[Csq]: Failed to start filtering (Status = 0x%x)\n",
                    Status) );

        FltUnregisterFilter( Globals.FilterHandle );

        return Status;
    }


    DebugTrace( CSQ_TRACE_LOAD_UNLOAD,
                ("[Csq]: Driver loaded complete\n") );

    return Status;
}

VOID
InitializeDebugLevel (
    __in PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    This routine tries to read the filter DebugLevel parameter from
    the registry.  This value will be found in the registry location
    indicated by the RegistryPath passed in.

Arguments:

    RegistryPath - The path key passed to the driver during DriverEntry.

Return Value:

    None.

--*/
{
    OBJECT_ATTRIBUTES attributes;
    HANDLE driverRegKey;
    NTSTATUS Status;
    ULONG resultLength;
    UNICODE_STRING valueName;
    UCHAR buffer[sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( LONG )];

    Globals.DebugLevel = CSQ_TRACE_ERROR;

    //
    //  Open the desired registry key
    //

    InitializeObjectAttributes( &attributes,
                                RegistryPath,
                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL );

    Status = ZwOpenKey( &driverRegKey,
                        KEY_READ,
                        &attributes );

    if (NT_SUCCESS( Status )) {

        //
        //  Read the DebugFlags value from the registry.
        //

        RtlInitUnicodeString( &valueName, L"DebugLevel" );

        Status = ZwQueryValueKey( driverRegKey,
                                  &valueName,
                                  KeyValuePartialInformation,
                                  buffer,
                                  sizeof(buffer),
                                  &resultLength );

        if (NT_SUCCESS( Status )) {

            Globals.DebugLevel = *((PULONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data));
        }
    }

    //
    //  Close the registry entry
    //

    ZwClose( driverRegKey );
}

NTSTATUS
Unload (
    __in FLT_FILTER_UNLOAD_FLAGS Flags
    )
/*++

Routine Description:

    This is the unload routine for this filter driver. This is called
    when the minifilter is about to be unloaded. We can fail this unload
    request if this is not a mandatory unloaded indicated by the Flags
    parameter.

Arguments:

    Flags - Indicating if this is a mandatory unload.

Return Value:

    Returns the final status of this operation.

--*/
{
    UNREFERENCED_PARAMETER( Flags );

    PAGED_CODE();

    DebugTrace( CSQ_TRACE_LOAD_UNLOAD,
                ("[Csq]: CancelSafe!Unload\n") );

    FltUnregisterFilter( Globals.FilterHandle );
    Globals.FilterHandle = NULL;

    ExDeleteNPagedLookasideList( &Globals.OueueContextLookaside );

    return STATUS_SUCCESS;
}


//
//  Context cleanup routine.
//

VOID
ContextCleanup (
    __in PFLT_CONTEXT Context,
    __in FLT_CONTEXT_TYPE ContextType
    )
/*++

Routine Description:

    FltMgr calls this routine immediately before it deletes the context.

Arguments:

    Context - Pointer to the minifilter driver's portion of the context.

    ContextType - Type of context. Must be one of the following values:
        FLT_FILE_CONTEXT (Microsoft Windows Vista and later only.),
        FLT_INSTANCE_CONTEXT, FLT_STREAM_CONTEXT, FLT_STREAMHANDLE_CONTEXT,
        FLT_TRANSACTION_CONTEXT (Windows Vista and later only.), and
        FLT_VOLUME_CONTEXT

Return Value:

    None.

--*/
{
    UNREFERENCED_PARAMETER( Context );
    UNREFERENCED_PARAMETER( ContextType );

    PAGED_CODE();

    DebugTrace( CSQ_TRACE_CONTEXT_CALLBACK,
                ("[Csq]: CancelSafe!ContextCleanup\n") );
}

//
//  Instance setup/teardown routines.
//

NTSTATUS
InstanceSetup (

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -