📄 cancelsafe.c
字号:
/*++
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 + -