Esempio n. 1
0
NTSTATUS
FmmReleaseMetadataFileReferences (
    __inout PFLT_CALLBACK_DATA Cbd
    )
/*++

Routine Description:

    This routine releases all references to the metadata file on the specified instance.

Arguments:

    Cbd                 - Supplies a pointer to the callbackData which
                          declares the requested operation.

Return Value:

    Status

Note:

    This routine takes care of the synchronization needed to access the metadata
    file object and handle

    This routine will also set the MetadataOpenTriggerFileObject in the instance context
    to the file object of the volume that triggered the release of the metadata file
    references.

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    PFMM_INSTANCE_CONTEXT instanceContext = NULL;

    PAGED_CODE();

    //
    //  Get the instance context
    //

    status = FltGetInstanceContext( Cbd->Iopb->TargetInstance,
                                    &instanceContext );
    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
                    ("[Fmm]: FmmReleaseMetadataFileReferences -> Failed to get instance context.\n") );

        goto FmmReleaseMetadataFileReferencesCleanup;
    }

    //
    //  Acquire exclusive access to the instance context
    //

    FmmAcquireResourceExclusive( &instanceContext->MetadataResouce);

    if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION)) {

        //
        //  If this instance context is in a transition state, it implies that
        //  the instance context lock has been released while sending an operation
        //  down to the file system. The reason for doing so is to prevent a potential
        //  deadlock if an underlying filter sends an IO to the top of the filter
        //  stack while we are holding the resource
        //
        //  We have managed to acquire this resource in this state of transition.
        //  It would be incorrect to use or modify the instance context in any way
        //  in this situation. So we simply let go.
        //

        status = STATUS_FILE_LOCK_CONFLICT;

        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
                    ("[Fmm]: FmmReleaseMetadataFileReferences -> Failed to get exclusive access to instance context since it is in a state of transition.\n") );
    } else {

        //
        //  Close the metadata file if it is open
        //

        if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) {

            DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                        ("[Fmm]: FmmReleaseMetadataFileReferences -> Releasing references to metadata handle and file object (InstanceContext = %p VolumeFileObject = %p)\n",
                         instanceContext,
                         Cbd->Iopb->TargetFileObject) );

            //
            //  Close the metadata file object
            //

            FmmCloseMetadata( instanceContext );

            //
            //  Save the volume file object for which we are releasing our references
            //

            instanceContext->MetadataOpenTriggerFileObject = Cbd->Iopb->TargetFileObject;
        } else {

            DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                        ("[Fmm]: FmmReleaseMetadataFileReferences -> Exit without attempting to release references to metadata handle and file object (InstanceContext = %p, VolumeFileObject = %p, MetadataOpenTriggerFileObject = %p, MetadataAlreadyOpen = 0x%x)\n",
                         instanceContext,
                         Cbd->Iopb->TargetFileObject,
                         instanceContext->MetadataOpenTriggerFileObject,
                         FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) );
        }
    }

    //
    //  Relinquish exclusive access to the instance context
    //

    FmmReleaseResource( &instanceContext->MetadataResouce);


FmmReleaseMetadataFileReferencesCleanup:

    //
    // Release the references we have acquired
    //

    if (instanceContext != NULL) {

        FltReleaseContext( instanceContext );
    }


    return status;
}
VOID
FmmInstanceTeardownComplete (
    _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.

--*/
{
    PFMM_INSTANCE_CONTEXT instanceContext;
    NTSTATUS status;

    UNREFERENCED_PARAMETER( Flags );

    PAGED_CODE();

    DebugTrace( DEBUG_TRACE_INSTANCES,
                ("[Fmm]: Instance teardown complete started (Instance = %p)\n",
                 FltObjects->Instance) );

    status = FltGetInstanceContext( FltObjects->Instance,
                                    &instanceContext );

    if (NT_SUCCESS( status )) {

        //
        //  Acquire exclusive access to the instance context
        //

        FmmAcquireResourceExclusive( &instanceContext->MetadataResource );

        //
        //  Sanity - the instance context cannot be in a transition state during instance teardown complete
        //

        FLT_ASSERT( !FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION) );


        if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) {

            //
            //  Close the metadata file
            //

            FmmCloseMetadata( instanceContext );
        }


        //
        //  Relinquish exclusive access to the instance context
        //

        FmmReleaseResource( &instanceContext->MetadataResource );

        FltReleaseContext( instanceContext );
    }

    DebugTrace( DEBUG_TRACE_INSTANCES,
                ("[Fmm]: Instance teardown complete ended (Instance = %p)\n",
                 FltObjects->Instance) );
}