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

📄 operations.c

📁 文件系统过滤驱动程序的框架
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1999 - 2002  Microsoft Corporation

Module Name:

    operations.c

Abstract:

    This is the i/o operations module of the kernel mode filter driver implementing
    filter metadata management.


Environment:

    Kernel mode


--*/

#include "pch.h"

//
//  Missing error code on Win2k
//

#if (WINVER==0x0500)
#ifndef STATUS_INVALID_DEVICE_OBJECT_PARAMETER
#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS)0xC0000369L)
#endif
#endif

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

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FmmPreCreate)
#pragma alloc_text(PAGE, FmmPostCreate)
#pragma alloc_text(PAGE, FmmPreCleanup)
#pragma alloc_text(PAGE, FmmPostCleanup)
#pragma alloc_text(PAGE, FmmPreFSControl)
#pragma alloc_text(PAGE, FmmPostFSControl)
#pragma alloc_text(PAGE, FmmPreDeviceControl)
#pragma alloc_text(PAGE, FmmPostDeviceControl)
#pragma alloc_text(PAGE, FmmPreShutdown)
#pragma alloc_text(PAGE, FmmPrePnp)

#endif

FLT_PREOP_CALLBACK_STATUS
FmmPreCreate (
    IN OUT PFLT_CALLBACK_DATA Cbd,
    IN PCFLT_RELATED_OBJECTS FltObjects,
    OUT PVOID *CompletionContext
    )
{
    NTSTATUS status;
    FLT_PREOP_CALLBACK_STATUS callbackStatus;

    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );

    PAGED_CODE();

    DebugTrace( DEBUG_TRACE_ALL_IO,
                ("[Fmm]: FmmPreCreate -> Enter (Cbd = %p, FileObject = %p)\n",
                 Cbd,
                 FltObjects->FileObject) );


    //
    // Initialize defaults
    //

    status = STATUS_SUCCESS;
    callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK; // pass through - default is no post op callback

     //
     //  Sanity check to ensure that the volume detection logic works
     //
     //  If the filename length is 0 and the related file object is NULL,
     //  the the FO_VOLUME_OPEN flag must be set
     //

     ASSERT( (!(Cbd->Iopb->TargetFileObject->FileName.Length == 0 &&
                Cbd->Iopb->TargetFileObject->RelatedFileObject == NULL)) ||
              FlagOn( Cbd->Iopb->TargetFileObject->Flags, FO_VOLUME_OPEN ) );

    if (FmmTargetIsVolumeOpen( Cbd )) {

        //
        //  Check for implicit volume locks (primarily used by autochk)
        //

        if (!FlagOn( Cbd->Iopb->Parameters.Create.ShareAccess, FILE_SHARE_WRITE)) {

            //
            //  This is an implicit volume lock
            //

            //
            //  Give up the metadata file handle and the metadata file object
            //

            status = FmmReleaseMetadataFileReferences( Cbd );

            if ( NT_SUCCESS( status )) {

                //
                //  Continue with the lock/dismount - we need to check if the
                //  lock operation suceeded in the post-op
                //

                callbackStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;
            } else {

                //
                //  Fail the lock/dismount
                //

                DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
                            ("[Fmm]: Failed to release metadata file references with status 0x%x for a volume lock/dismount\n",
                             status) );

                //
                //  Since this operation has failed, FmmPreCreateCleanup will
                //  update Cbd->IoStatus.Status with the status code and
                //  complete the operation by returning FLT_PREOP_COMPLETE
                //

            }

        }

        //
        //  We do not need to process volume opens any further
        //

         goto FmmPreCreateCleanup;
    }

    //
    //  Here the filter can do any further processing it may want to do
    //  in the PreCreate Callback
    //



FmmPreCreateCleanup:


    //
    // If any operation has failed then complete and fail the call
    //

    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_ERROR,
                    ("[Fmm]: FmmPreCreate -> Failed with status 0x%x \n",
                    status) );

        Cbd->IoStatus.Status = status;
        callbackStatus = FLT_PREOP_COMPLETE;
    }

    DebugTrace( DEBUG_TRACE_ALL_IO,
                ("[Fmm]: FmmPreCreate -> Exit (Cbd = %p, FileObject = %p)\n",
                 Cbd,
                 FltObjects->FileObject) );

    return callbackStatus;

}


FLT_POSTOP_CALLBACK_STATUS
FmmPostCreate (
    IN OUT PFLT_CALLBACK_DATA Cbd,
    IN PCFLT_RELATED_OBJECTS FltObjects,
    IN PVOID CbdContext,
    IN FLT_POST_OPERATION_FLAGS Flags
    )
{

    NTSTATUS status;

    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CbdContext );
    UNREFERENCED_PARAMETER( Flags );

    PAGED_CODE();

    DebugTrace( DEBUG_TRACE_ALL_IO,
                ("[Fmm]: FmmPostCreate -> Enter (Cbd = %p, FileObject = %p)\n",
                 Cbd,
                 FltObjects->FileObject) );

    //
    // Initialize defaults
    //

    status = STATUS_SUCCESS;

    if (!FlagOn(Flags,FLTFL_POST_OPERATION_DRAINING) &&
        FmmTargetIsVolumeOpen( Cbd )) {

        //
        //  Check for implicit volume locks (primarily used by autochk)
        //

        if (!FlagOn( Cbd->Iopb->Parameters.Create.ShareAccess, FILE_SHARE_WRITE)) {

            //
            //  This is an implicit volume lock
            //

            if (!NT_SUCCESS( Cbd->IoStatus.Status )) {

                //
                //  The lock failed - reaquire our references to the metadata file
                //  handle and the metadata file object
                //

                status = FmmReacquireMetadataFileReferences( Cbd );

                if (!NT_SUCCESS( status )) {

                    DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
                                ("[Fmm]: Failed to re-open metadata with status 0x%x after a failed lock with status 0x%x\n",
                                 status,
                                 Cbd->IoStatus.Status) );

                    //
                    //  Sanity - we are now in a bad state. The lock has failed
                    //  but we have not been able to re-acquire references to
                    //  our metadata file
                    //
                    //  It is always possible to fail with STATUS_INSUFFICIENT_RESOURCES
                    //  so we should ignore that.
                    //
                    //  It is also possible to fail if the instance context was in a transition state
                    //  so we should ignore STATUS_FILE_LOCK_CONFLICT too.
                    //

                    ASSERT( (status == STATUS_INSUFFICIENT_RESOURCES) ||
                            (status == STATUS_FILE_LOCK_CONFLICT) );
                }

            } else {

                //
                //  The lock operation suceeded - update the
                //  MetadataOpenTriggerFileObject in the instance context to
                //  the File Object that performed the lock operation.  This
                //  is so we can recognize an implicit unlock at close time.
                //
                //  You may have noticed that we set the
                //  MetadataOpenTriggerFileObject in pre-create and may be
                //  wondering why we set it again in this case.  This is to
                //  support a lower filter doing a recursive lock operation
                //  from the top of the stack.
                //

                status = FmmSetMetadataOpenTriggerFileObject( Cbd );

                if (!NT_SUCCESS( status )) {

                    DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
                                ("[Fmm]: Failed to update MetadataOpenTriggerFileObject in the instance context with status 0x%x after a successful lock.\n",
                                 status,
                                 Cbd->IoStatus.Status) );

                    //
                    //  Sanity - we are now in a bad state. We have failed to set the TriggerFileObject
                    //  We may not be able to detect an unlock operation on which we need to
                    //  re-acquire our metadata file references
                    //

                    ASSERT( status == STATUS_FILE_LOCK_CONFLICT );

                }
            }
        }

        //
        //  We do not need to process volume opens any further
        //

        goto FmmPostCreateCleanup;
    }


    //
    //  Here the filter can do any further processing it may want to do
    //  in the PostCreate Callback
    //

FmmPostCreateCleanup:


    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_ERROR,
                    ("[Fmm]: FmmPostCreate -> Failed with status 0x%x \n",
                    status) );

        //
        //  It does not make sense to fail in the the post op, since the operation has completed
        //
    }


    DebugTrace( DEBUG_TRACE_ALL_IO,
                ("[Fmm]: FmmPostCreate -> Exit (Cbd = %p, FileObject = %p, Status = 0x%08X)\n",
                 Cbd,
                 FltObjects->FileObject,
                 Cbd->IoStatus.Status) );

    return FLT_POSTOP_FINISHED_PROCESSING;
}


FLT_PREOP_CALLBACK_STATUS
FmmPreCleanup (
    IN OUT PFLT_CALLBACK_DATA Cbd,
    IN PCFLT_RELATED_OBJECTS FltObjects,
    OUT PVOID *CompletionContext
    )
{

    UNREFERENCED_PARAMETER( Cbd );
    UNREFERENCED_PARAMETER( CompletionContext );
    UNREFERENCED_PARAMETER( FltObjects );

    PAGED_CODE();

    DebugTrace( DEBUG_TRACE_ALL_IO,
                ("[Fmm]: FmmPreCleanup -> Enter (Cbd = %p, FileObject = %p)\n",
                 Cbd,
                 FltObjects->FileObject) );


    DebugTrace( DEBUG_TRACE_ALL_IO,
                ("[Fmm]: FmmPreCleanup -> Exit (Cbd = %p, FileObject = %p)\n",
                 Cbd,
                 FltObjects->FileObject) );

    return FLT_PREOP_SYNCHRONIZE;
}


FLT_POSTOP_CALLBACK_STATUS
FmmPostCleanup (
    IN OUT PFLT_CALLBACK_DATA Cbd,
    IN PCFLT_RELATED_OBJECTS FltObjects,
    IN PVOID CbdContext,
    IN FLT_POST_OPERATION_FLAGS Flags
    )
{
    PFMM_INSTANCE_CONTEXT instanceContext = NULL;
    NTSTATUS status;


    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CbdContext );
    UNREFERENCED_PARAMETER( Flags );
    ASSERT(!FlagOn(Flags,FLTFL_POST_OPERATION_DRAINING));   //can't drain this operation

    //
    //  The pre-operation callback will return FLT_PREOP_SYNCHRONIZE if it needs a
    //  post operation callback. In this case, the Filter Manager will call the
    //  minifilter's post-operation callback in the context of the pre-operation
    //  thread, at IRQL <= APC_LEVEL. This allows the post-operation code to be
    //  pagable and also allows it to access paged data
    //

    PAGED_CODE();

    DebugTrace( DEBUG_TRACE_ALL_IO,
                ("[Fmm]: FmmPostCleanup -> Enter (Cbd = %p, FileObject = %p)\n",
                 Cbd,
                 FltObjects->FileObject) );

    //
    // Initialize defaults
    //

    status = STATUS_SUCCESS;


    if (FmmTargetIsVolumeOpen( Cbd )) {

        if (NT_SUCCESS( Cbd->IoStatus.Status )) {

            //
            //  A close on a volume handle could be an unlock if a lock was
            //  previously  called on this handle. Check if this was a close
            //  on a volume handle on which a lock was previously successful.
            //  If so, re-acquire the references to our metadata file
            //

            status = FmmReacquireMetadataFileReferences( Cbd );

            if (!NT_SUCCESS( status )) {

                DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
                            ("[Fmm]: Failed to re-open metadata with status 0x%x after a successful unlock.\n",
                             status) );

                //
                //  Sanity - we are now in a bad state. The volume was unlocked
                //  but we have not been able to re-acquire references to
                //  our metadata file
                //
                //  Ntfs dismounts and remounts the volume after an unlock. So we ignore
                //  failures to open the metadata with STATUS_INVALID_DEVICE_OBJECT_PARAMETER
                //  because the volume should have been remounted and the metadata file
                //  should have been opened on the newly mounted instance of that volume
                //
                //  Note however, that if this is an implicit lock (used by autoXXX.exe) then
                //  ntfs will not automatically dismount the volume. It relies on the application
                //  to restart the system if it has made any changes to the volume. If the
                //  application has not made any changes then ntfs will simply continue on
                //  after the unlock without dismounting the volume. Hence we cannot assume
                //  that ntfs always dismounts the volume. We need to try to re-acquire

⌨️ 快捷键说明

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