📄 cancelsafe.c
字号:
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_SETUP_FLAGS Flags,
__in DEVICE_TYPE VolumeDeviceType,
__in FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
/*++
Routine Description:
This routine is called whenever a new instance is created on a volume. This
gives us a chance to decide if we need to attach to this volume or not.
Arguments:
FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
opaque handles to this filter, instance and its associated volume.
Flags - Flags describing the reason for this attach request.
VolumeDeviceType - Device type of the file system volume.
Must be one of the following: FILE_DEVICE_CD_ROM_FILE_SYSTEM,
FILE_DEVICE_DISK_FILE_SYSTEM, and FILE_DEVICE_NETWORK_FILE_SYSTEM.
VolumeFilesystemType - File system type of the volume.
Return Value:
STATUS_SUCCESS - attach
STATUS_FLT_DO_NOT_ATTACH - do not attach
--*/
{
PINSTANCE_CONTEXT InstCtx = NULL;
NTSTATUS Status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER( Flags );
UNREFERENCED_PARAMETER( VolumeDeviceType );
UNREFERENCED_PARAMETER( VolumeFilesystemType );
PAGED_CODE();
DebugTrace( CSQ_TRACE_INSTANCE_CALLBACK,
("[Csq]: CancelSafe!InstanceSetup\n") );
//
// Allocate and initialize the instance context.
//
Status = FltAllocateContext( FltObjects->Filter,
FLT_INSTANCE_CONTEXT,
sizeof( INSTANCE_CONTEXT ),
NonPagedPool,
&InstCtx );
if (!NT_SUCCESS( Status )) {
DebugTrace( CSQ_TRACE_INSTANCE_CALLBACK | CSQ_TRACE_ERROR,
("[Csq]: Failed to allocate instance context (Volume = %p, Instance = %p, Status = 0x%x)\n",
FltObjects->Volume,
FltObjects->Instance,
Status) );
goto InstanceSetupCleanup;
}
Status = FltCbdqInitialize( FltObjects->Instance,
&InstCtx->Cbdq,
CsqInsertIo,
CsqRemoveIo,
CsqPeekNextIo,
CsqAcquire,
CsqRelease,
CsqCompleteCanceledIo );
if (!NT_SUCCESS( Status )) {
DebugTrace( CSQ_TRACE_INSTANCE_CALLBACK | CSQ_TRACE_ERROR,
("[Csq]: Failed to initialize callback data queue (Volume = %p, Instance = %p, Status = 0x%x)\n",
FltObjects->Volume,
FltObjects->Instance,
Status) );
goto InstanceSetupCleanup;
}
//
// Initialize the internal queue head and lock of the cancel safe queue.
//
InitializeListHead( &InstCtx->QueueHead );
ExInitializeFastMutex( &InstCtx->Lock );
//
// Initialize other members of the instance context.
//
InstCtx->Instance = FltObjects->Instance;
InstCtx->WorkerThreadFlag = 0;
KeInitializeEvent( &InstCtx->TeardownEvent, NotificationEvent, FALSE );
//
// Set the instance context.
//
Status = FltSetInstanceContext( FltObjects->Instance,
FLT_SET_CONTEXT_KEEP_IF_EXISTS,
InstCtx,
NULL );
if( !NT_SUCCESS( Status )) {
DebugTrace( CSQ_TRACE_INSTANCE_CALLBACK | CSQ_TRACE_ERROR,
("[Csq]: Failed to set instance context (Volume = %p, Instance = %p, Status = 0x%x)\n",
FltObjects->Volume,
FltObjects->Instance,
Status) );
goto InstanceSetupCleanup;
}
InstanceSetupCleanup:
if ( InstCtx != NULL ) {
FltReleaseContext( InstCtx );
}
return Status;
}
NTSTATUS
InstanceQueryTeardown (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
/*++
Routine Description:
This is called when an instance is being manually deleted by a
call to FltDetachVolume or FilterDetach thereby giving us a
chance to fail that detach request.
Arguments:
FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
opaque handles to this filter, instance and its associated volume.
Flags - Indicating where this detach request came from.
Return Value:
Returns the status of this operation.
--*/
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
DebugTrace( CSQ_TRACE_INSTANCE_CALLBACK,
("[Csq]: CancelSafe!InstanceQueryTeardown\n") );
return STATUS_SUCCESS;
}
VOID
InstanceTeardownStart (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
/*++
Routine Description:
This routine is called at the start of instance teardown.
Arguments:
FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
opaque handles to this filter, instance and its associated volume.
Flags - Reason why this instance is been deleted.
Return Value:
None.
--*/
{
PINSTANCE_CONTEXT InstCtx = 0;
NTSTATUS Status;
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
DebugTrace( CSQ_TRACE_INSTANCE_CALLBACK,
("[Csq]: CancelSafe!InstanceTeardownStart\n") );
//
// Get a pointer to the instance context.
//
Status = FltGetInstanceContext( FltObjects->Instance,
&InstCtx );
if (!NT_SUCCESS(Status))
{
ASSERT( !"Instance Context is missing" );
return;
}
//
// Disable the insert to the cancel safe queue.
//
FltCbdqDisable( &InstCtx->Cbdq );
//
// Remove all callback data from the queue and complete them.
//
PreReadEmptyQueueAndComplete( InstCtx );
//
// Signal the worker thread if it is pended.
//
KeSetEvent( &InstCtx->TeardownEvent, 0, FALSE );
//
// Cleanup
//
FltReleaseContext( InstCtx );
}
VOID
InstanceTeardownComplete (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
/*++
Routine Description:
This routine is called at the end of instance teardown.
Arguments:
FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
opaque handles to this filter, instance and its associated volume.
Flags - Reason why this instance is been deleted.
Return Value:
None.
--*/
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
DebugTrace( CSQ_TRACE_INSTANCE_CALLBACK,
("[Csq]: CancelSafe!InstanceTeardownComplete\n") );
PAGED_CODE();
}
//
// Cbdq callback routines.
//
VOID
CsqAcquire(
__in PFLT_CALLBACK_DATA_QUEUE DataQueue,
__out PKIRQL Irql
)
/*++
Routine Description:
FltMgr calls this routine to acquire the lock protecting the queue.
Arguments:
DataQueue - Supplies a pointer to the queue itself.
Irql - Returns the previous IRQL if a spinlock is acquired. We do not use
any spinlocks, so we ignore this.
Return Value:
None.
--*/
{
PINSTANCE_CONTEXT InstCtx;
UNREFERENCED_PARAMETER( Irql );
DebugTrace( CSQ_TRACE_CBDQ_CALLBACK,
("[Csq]: CancelSafe!CsqAcquire\n") );
//
// Get a pointer to the instance context.
//
InstCtx = CONTAINING_RECORD( DataQueue, INSTANCE_CONTEXT, Cbdq );
//
// Acquire the lock.
//
ExAcquireFastMutex( &InstCtx->Lock );
}
VOID
CsqRelease(
__in PFLT_CALLBACK_DATA_QUEUE DataQueue,
__in KIRQL Irql
)
/*++
Routine Description:
FltMgr calls this routine to release the lock protecting the queue.
Arguments:
DataQueue - Supplies a pointer to the queue itself.
Irql - Supplies the previous IRQL if a spinlock is acquired. We do not use
any spinlocks, so we ignore this.
Return Value:
None.
--*/
{
PINSTANCE_CONTEXT InstCtx;
UNREFERENCED_PARAMETER( Irql );
DebugTrace( CSQ_TRACE_CBDQ_CALLBACK,
("[Csq]: CancelSafe!CsqRelease\n") );
//
// Get a pointer to the instance context.
//
InstCtx = CONTAINING_RECORD( DataQueue, INSTANCE_CONTEXT, Cbdq );
//
// Release the lock.
//
ExReleaseFastMutex( &InstCtx->Lock );
}
NTSTATUS
CsqInsertIo(
__in PFLT_CALLBACK_DATA_QUEUE DataQueue,
__in PFLT_CALLBACK_DATA Data,
__in_opt PVOID Context
)
/*++
Routine Description:
FltMgr calls this routine to insert an entry into our pending I/O queue.
The queue is already locked before this routine is called.
Arguments:
DataQueue - Supplies a pointer to the queue itself.
Data - Supplies the callback data for the operation that is being
inserted into the queue.
Context - Supplies user-defined context information.
Return Value:
STATUS_SUCCESS if the function completes successfully. Otherwise a valid
NTSTATUS code is returned.
--*/
{
PINSTANCE_CONTEXT InstCtx;
PFLT_GENERIC_WORKITEM WorkItem = NULL;
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN WasQueueEmpty;
UNREFERENCED_PARAMETER( Context );
DebugTrace( CSQ_TRACE_CBDQ_CALLBACK,
("[Csq]: CancelSafe!CsqInsertIo\n") );
//
// Get a pointer to the instance context.
//
InstCtx = CONTAINING_RECORD( DataQueue, INSTANCE_CONTEXT, Cbdq );
//
// Save the queue state before inserting to it.
//
WasQueueEmpty = IsListEmpty( &InstCtx->QueueHead );
//
// Insert the callback data entry into the queue.
//
InsertTailList( &InstCtx->QueueHead,
&Data->QueueLinks );
//
// Queue a work item if no worker thread present.
//
if (WasQueueEmpty &&
InterlockedIncrement( &InstCtx->WorkerThreadFlag ) == 1) {
WorkItem = FltAllocateGenericWorkItem();
if (WorkItem) {
Status = FltQueueGenericWorkItem( WorkItem,
InstCtx->Instance,
PreReadWorkItemRoutine,
DelayedWorkQueue,
InstCtx->Instance );
if (!NT_SUCCESS(Status)) {
DebugTrace( CSQ_TRACE_CBDQ_CALLBACK | CSQ_TRACE_ERROR,
("[Csq]: Failed to queue the work item (Status = 0x%x)\n",
Status) );
FltFreeGenericWorkItem( WorkItem );
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if ( !NT_SUCCESS( Status )) {
//
// Remove the callback data that was inserted into the queue.
//
RemoveTailList( &InstCtx->QueueHead );
}
}
return Status;
}
VOID
CsqRemoveIo(
__in PFLT_CALLBACK_DATA_QUEUE DataQueue,
__in PFLT_CALLBACK_DATA Data
)
/*++
Routine Description:
FltMgr calls this routine to remove an entry from our pending I/O queue.
The queue is already locked before this routine is called.
Arguments:
DataQueue - Supplies a pointer to the queue itself.
Data - Supplies the callback data that is to be removed.
Return Value:
None.
--*/
{
UNREFERENCED_PARAMETER( DataQueue );
DebugTrace( CSQ_TRACE_CBDQ_CALLBACK,
("[Csq]: CancelSafe!CsqRemoveIo\n") );
//
// Remove the callback data entry from the queue.
//
RemoveEntryList( &Data->QueueLinks );
}
PFLT_CALLBACK_DATA
CsqPeekNextIo(
__in PFLT_CALLBACK_DATA_QUEUE DataQueue,
__in_opt PFLT_CALLBACK_DATA Data,
__in_opt PVOID PeekContext
)
/*++
Routine Description:
FltMgr calls this routine to look for an entry on our pending I/O queue.
The queue is already locked before this routine is called.
Arguments:
DataQueue - Supplies a pointer to the queue itself.
Data - Supplies the callback data we should start our search from.
If this is NULL, we start at the beginning of the list.
PeekContext - Supplies user-defined context information.
Return Value:
A pointer to the next callback data structure, or NULL.
--*/
{
PINSTANCE_CONTEXT InstCtx;
PLIST_ENTRY NextEntry;
PFLT_CALLBACK_DATA NextData;
UNREFERENCED_PARAMETER( PeekContext );
DebugTrace( CSQ_TRACE_CBDQ_CALLBACK,
("[Csq]: CancelSafe!CsqPeekNextIo\n") );
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -