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

📄 cancelsafe.c

📁 这是一款驱动过滤程序 能轻松过滤文本文档 幻灯片等程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    __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 + -