예제 #1
0
static NTSTATUS
UcaGetContext(_In_ PFLT_INSTANCE Instance,
              _In_ PVOID Target,
              _In_ FLT_CONTEXT_TYPE ContextType,
              _Outptr_ PFLT_CONTEXT *Context)
{
    NTSTATUS Status;

    PAGED_CODE();

    switch (ContextType)
    {
        case FLT_STREAM_CONTEXT:
            Status = FltGetStreamContext(Instance,
                                         (PFILE_OBJECT)Target,
                                         Context);
            break;

        case FLT_FILE_CONTEXT:
            Status = FltGetFileContext(Instance,
                                       (PFILE_OBJECT)Target,
                                       Context);
            break;

        case FLT_TRANSACTION_CONTEXT:
            Status = FltGetTransactionContext(Instance,
                                              (PKTRANSACTION)Target,
                                              Context);
            break;

        case FLT_INSTANCE_CONTEXT:
            Status = FltGetInstanceContext(Instance,
                                           Context);
            break;

        default:
            Status = STATUS_INVALID_PARAMETER;
            break;
    }

    return Status;
}
예제 #2
0
NTSTATUS
NcGenerateFileName (
    _In_ PFLT_INSTANCE Instance,
    _In_ PFILE_OBJECT FileObject,
    _In_opt_ PFLT_CALLBACK_DATA Data,
    _In_ FLT_FILE_NAME_OPTIONS NameOptions,
    _Out_ PBOOLEAN CacheFileNameInformation,
    _Inout_ PFLT_NAME_CONTROL OutputNameControl
    )
{
    //
    //  Status vars
    //

    NTSTATUS Status;

    //
    //  State lookup vars
    //

    BOOLEAN Opened = (BOOLEAN)(FileObject->FsContext != NULL);                                       // True if file object is opened.
    BOOLEAN ReturnShortName = (BOOLEAN)(FltGetFileNameFormat(NameOptions) == FLT_FILE_NAME_SHORT);   // True if the user is requesting short name
    BOOLEAN ReturnOpenedName = (BOOLEAN)(FltGetFileNameFormat(NameOptions) == FLT_FILE_NAME_OPENED); // True if user is requesting opened name.
    BOOLEAN ReturnNormalizedName = (BOOLEAN)(FltGetFileNameFormat(NameOptions) == FLT_FILE_NAME_NORMALIZED); // True if user is requesting normalized name.
    BOOLEAN IgnoreCase;
    FLT_FILE_NAME_OPTIONS NameQueryMethod = FltGetFileNameQueryMethod( NameOptions );
    FLT_FILE_NAME_OPTIONS NameFlags = FLT_VALID_FILE_NAME_FLAGS & NameOptions;

    //
    //  File name information
    //

    PFLT_FILE_NAME_INFORMATION LowerNameInfo = NULL; // File name as reported by lower name provider. Will always be down real mapping.
    PFLT_FILE_NAME_INFORMATION ShortInfo = NULL;  // We will use ShortInfo to store the short name if needed.

    //
    //  Contexts
    //
    
    PNC_INSTANCE_CONTEXT InstanceContext = NULL;

    //
    //  Overlap
    //
    
    NC_PATH_OVERLAP RealOverlap;
    UNICODE_STRING RealRemainder = EMPTY_UNICODE_STRING;

    //
    //  Temp storage
    //
    
    UNICODE_STRING MungedName = EMPTY_UNICODE_STRING;
    
    //
    //  Temp pointer
    //
    
    PUNICODE_STRING Name = NULL; // Pointer to the name we are going to use.

    PAGED_CODE();

    FLT_ASSERT( IoGetTopLevelIrp() == NULL );

    //
    //  This should never happen, but let's be safe.
    //

    if (!ReturnShortName &&
        !ReturnOpenedName &&
        !ReturnNormalizedName) {

        FLT_ASSERT( FALSE );
        Status = STATUS_NOT_SUPPORTED;
        goto NcGenerateFileNameCleanup;
    }

    RealOverlap.EntireFlags = 0;

    //
    //  To prevent infinite recursion, calls to FltGetFileNameInformation 
    //  from generate file name callbacks should not target current provider.
    //

    ClearFlag( NameFlags, FLT_FILE_NAME_REQUEST_FROM_CURRENT_PROVIDER );

    //
    //  Fetch the instance context.
    //

    Status = FltGetInstanceContext( Instance, &InstanceContext );   

    if (!NT_SUCCESS( Status )) {

        goto NcGenerateFileNameCleanup;
    }

    //
    //  We need to know what the name provider under us thinks the file is called.
    //  If the caller wants the normalized name we query that, otherwise we query
    //  the opened name because we have to compare the full path of the file vs.
    //  the real mapping to determine if the file is mapped.
    //

    Status = NcGetFileNameInformation( Data,
                                       FileObject,
                                       Instance,
                                       (ReturnNormalizedName ? FLT_FILE_NAME_NORMALIZED
                                                             : FLT_FILE_NAME_OPENED) |
                                           NameQueryMethod |
                                           NameFlags,
                                       &LowerNameInfo );

    if (!NT_SUCCESS( Status )) {

        goto NcGenerateFileNameCleanup;
    }

    Status = FltParseFileNameInformation( LowerNameInfo );

    if (!NT_SUCCESS( Status )) {

        goto NcGenerateFileNameCleanup;
    }

    //
    //  Issues With Pre-open path:
    //
    //  1) Poison name cache below name provider:
    //    If a filter above a name provider calls FltGetFileNameInformation on a 
    //    file object in his precreate callback, fltmgr will call the name 
    //    provider's generate name callback before the name provider's pre create
    //    callback is invoked. Name providers by their nature change names in their
    //    pre-create. Because the name provider has not had the opportunity to 
    //    modify the name yet, we need to make sure that fltmgr does not cache the name we 
    //    return below us, so we set the FLT_FILE_NAME_DO_NOT_CACHE flag.
    //    //TODO: TRY TO GET ACROSS THAT THIS IS A NAME CHANGER PROBLEM, NOT ALL NAME PROVIDERS NEED TO.
    //

    if (!Opened) {

        SetFlag( NameFlags, FLT_FILE_NAME_DO_NOT_CACHE );

        if (Data) {

            //
            //  NT supports case sensitive and non-case sensitive naming in file systems.
            //  This is handled on a per-open basis. Weather an open is case senstive is 
            //  determined by the FO_OPENED_CASE_SENSITIVE flag on the file object.
            //  In pre-create the SL_CASE_SENSITIVE flag on the create IRP specifies the mode.
            //
            //  If this is on an unopened FileObject, it had better be pre-create so we know
            //  how to process the operation.  If we are queried on an unopened FileObject
            //  at any other time we have no way to handle the request.
            //

            FLT_ASSERT( Data->Iopb->MajorFunction == IRP_MJ_CREATE ||
                        Data->Iopb->MajorFunction == IRP_MJ_NETWORK_QUERY_OPEN );

            IgnoreCase = !BooleanFlagOn( Data->Iopb->OperationFlags, SL_CASE_SENSITIVE );

        } else {

            //
            //  If people do unsafe queries on preopened IOs, we cannot
            //  determine if the open is case sensitive or not.
            //  So we cannot determine if this open is down the mapping.
            //  fail.
            //

            FLT_ASSERT( FALSE );
            Status = STATUS_INVALID_PARAMETER;
            goto NcGenerateFileNameCleanup;

        }

    } else {

        //
        //  After a file has been opened, the case sensitivity is stored in the file object.
        //

        IgnoreCase = !BooleanFlagOn( FileObject->Flags, FO_OPENED_CASE_SENSITIVE );
    }

    //
    //  Calculate the overlap with the real mapping.
    //

    NcComparePath( &LowerNameInfo->Name,
                   &InstanceContext->Mapping.RealMapping,
                   &RealRemainder,
                   IgnoreCase,
                   TRUE,
                   &RealOverlap );

    //
    //  Whether we munge depends on what name is requested.
    //

    if (ReturnOpenedName ||
        ReturnNormalizedName) {

        if (Opened &&
            RealOverlap.InMapping) {

            //
            //  We munge the opened name if it overlaps with the real mapping.
            //  The returned path will be down the user mapping.
            //

            Status = NcConstructPath( &InstanceContext->Mapping.UserMapping,
                                      &RealRemainder,
                                      TRUE,
                                      &MungedName);

            if (!NT_SUCCESS( Status )) {

                goto NcGenerateFileNameCleanup;
            }

            Name = &MungedName;

        } else {

            //
            //  We return the queried result if the path is not in the
            //  mapping.
            //

            Name = &LowerNameInfo->Name;

        }

    } else if (ReturnShortName) {

        //
        //  Note that unlike opened names, a query for a shortname only returns
        //  the final component, not the full path.
        //

        // TODO: Assert not preopen

        if (RealOverlap.Match) {

            //
            //  The opened path is the mapping path.
            //  This means that if we queried the filesystem
            //  he would return the wrong path.
            //
            //  Luckily, we can just use the mapping.
            //

            Name = &InstanceContext->Mapping.UserMapping.ShortNamePath.FinalComponentName;

        } else {

            //
            //  We have to query below us to get the short name.
            //

            Status = NcGetFileNameInformation( Data,
                                               FileObject,
                                               Instance,
                                               FLT_FILE_NAME_SHORT | 
                                                   NameQueryMethod |
                                                   NameFlags,
                                               &ShortInfo );

            if (!NT_SUCCESS( Status )) {

                goto NcGenerateFileNameCleanup;
            }

            Status = FltParseFileNameInformation( ShortInfo );

            if (!NT_SUCCESS(Status)) {

                goto NcGenerateFileNameCleanup;
            }

            //
            //  Set name to returned name.
            //

            Name = &ShortInfo->Name;
        }
    }

    FLT_ASSERT( Name != NULL );

    //
    //  Try to grow the namechanger's record to accommodate the result.
    //

    Status = FltCheckAndGrowNameControl( OutputNameControl, Name->Length );

    if (NT_SUCCESS( Status )) {

        //
        //  Copy the new name into the buffer.
        //

        RtlCopyUnicodeString( &OutputNameControl->Name, Name );
        *CacheFileNameInformation = TRUE;
    }

NcGenerateFileNameCleanup:

    if (LowerNameInfo != NULL) {

        FltReleaseFileNameInformation( LowerNameInfo );
    }

    if (ShortInfo != NULL) {

        FltReleaseFileNameInformation( ShortInfo );
    }

    if (InstanceContext != NULL) {

        FltReleaseContext( InstanceContext );
    }

    if (MungedName.Buffer != NULL) {

        ExFreePoolWithTag( MungedName.Buffer, NC_GENERATE_NAME_TAG );
    }

    return Status;
}
예제 #3
0
    IO_STATUS_BLOCK ParentStatusBlock;
    OBJECT_ATTRIBUTES ParentAttributes;
    HANDLE ParentHandle = 0;
    PFILE_OBJECT ParentFileObject = NULL;
    BOOLEAN IgnoreCase = !BooleanFlagOn( Flags, FLTFL_NORMALIZE_NAME_CASE_SENSITIVE );

    PAGED_CODE();

    FLT_ASSERT( IoGetTopLevelIrp() == NULL );

    UNREFERENCED_PARAMETER( NormalizationContext );
    UNREFERENCED_PARAMETER( DeviceNameLength );
    UNREFERENCED_PARAMETER( FileObject );

    Status = FltGetInstanceContext( Instance,
                                    &InstanceContext );

    if (!NT_SUCCESS( Status )) {

        goto NcNormalizeNameComponentExCleanup;
    }

    //
    //  Default to enumerating the component specified by the
    //  caller.
    //

    MungedComponent = Component;

    NcComparePath( ParentDirectory,
                   &InstanceContext->Mapping.UserMapping,
예제 #4
0
FLT_POSTOP_CALLBACK_STATUS
CtxPostSetInfo (
    _Inout_ PFLT_CALLBACK_DATA Cbd,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Inout_opt_ PVOID CbdContext,
    _In_ FLT_POST_OPERATION_FLAGS Flags
    )
{
    PCTX_INSTANCE_CONTEXT instanceContext = NULL;
    PCTX_FILE_CONTEXT fileContext = NULL;
    PCTX_STREAM_CONTEXT streamContext = NULL;
    PCTX_STREAMHANDLE_CONTEXT streamHandleContext = NULL;
    PFLT_FILE_NAME_INFORMATION nameInfo = NULL;

    NTSTATUS status;
    BOOLEAN streamContextCreated, fileContextCreated, streamHandleContextReplaced;
    
    UNREFERENCED_PARAMETER( Flags );
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CbdContext );

    //
    //  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,
                ("[Ctx]: CtxPostSetInfo -> Enter (Cbd = %p, FileObject = %p)\n",
                 Cbd,
                 FltObjects->FileObject) );


    //
    // Initialize defaults
    //
    
    status = STATUS_SUCCESS;

    //
    //  If the SetInfo has failed, do nothing
    //

    if (!NT_SUCCESS( Cbd->IoStatus.Status )) {
        
        goto CtxPostSetInfoCleanup;        
    }


    //
    //  Get the instance context for the target instance
    //

    DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> Trying to get instance context (TargetInstance = %p, Cbd = %p, FileObject = %p)\n",
                 Cbd->Iopb->TargetInstance,
                 Cbd,
                 FltObjects->FileObject) );
    
    status = FltGetInstanceContext( Cbd->Iopb->TargetInstance,
                                    &instanceContext );
    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: CtxPostSetInfo -> Failed to get instance context (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );
    
        goto CtxPostSetInfoCleanup;
    }

    DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> Instance context info for volume %wZ (Cbd = %p, FileObject = %p, InstanceContext = %p) \n\tVolumeName = %wZ \n\tInstance = %p \n\tVolume = %p\n",
                 &instanceContext->VolumeName,
                 Cbd,
                 FltObjects->FileObject,
                 instanceContext,
                 &instanceContext->VolumeName,
                 &instanceContext->Instance,
                 &instanceContext->Volume) );


    //
    // Get the directory name
    //
    
    status = FltGetFileNameInformation( Cbd,
                                        FLT_FILE_NAME_NORMALIZED |
                                        FLT_FILE_NAME_QUERY_DEFAULT,
                                        &nameInfo );
    
    if (!NT_SUCCESS( status )) {
    
        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS | DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                    ("[Ctx]: CtxPostSetInfo -> Failed to get file name information (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );
    
        goto CtxPostSetInfoCleanup;
    }

    
    //
    // Get the stream context
    //

    status = CtxFindOrCreateStreamContext(Cbd, 
                                          FALSE,     // do not create if one does not exist
                                          &streamContext,
                                          &streamContextCreated);
    if (!NT_SUCCESS( status )) {

        //
        //  This failure will most likely be because stream contexts are not supported
        //  on the object we are trying to assign a context to or the object is being 
        //  deleted
        //  
                
        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                    ("[Ctx]: CtxPostSetInfo -> Failed to find stream context (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );
    
        goto CtxPostSetInfoCleanup;
    }        

    DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> Getting stream context for file %wZ (Cbd = %p, FileObject = %p, StreamContext = %p. StreamContextCreated = %x)\n",
                 &nameInfo->Name,
                 Cbd,
                 FltObjects->FileObject,
                 streamContext,
                 streamContextCreated) );

    //
    //  Acquire write acccess to the context
    //
    
    CtxAcquireResourceExclusive(streamContext->Resource);


    DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> Old info in stream context for file %wZ (Cbd = %p, FileObject = %p, StreamContext = %p) \n\tName = %wZ \n\tCreateCount = %x \n\tCleanupCount = %x, \n\tCloseCount = %x\n",
                 &nameInfo->Name,
                 Cbd,
                 FltObjects->FileObject,
                 streamContext,
                 &streamContext->FileName,
                 streamContext->CreateCount,
                 streamContext->CleanupCount,
                 streamContext->CloseCount) );


    
    //
    //  Update the file name in the context
    //
    
    status = CtxUpdateNameInStreamContext( &nameInfo->Name, 
                                                  streamContext);


    DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> New info in stream context for file %wZ (Cbd = %p, FileObject = %p, StreamContext = %p) \n\tName = %wZ \n\tCreateCount = %x \n\tCleanupCount = %x, \n\tCloseCount = %x\n",
                 &nameInfo->Name,
                 Cbd,
                 FltObjects->FileObject,
                 streamContext,
                 &streamContext->FileName,
                 streamContext->CreateCount,
                 streamContext->CleanupCount,
                 streamContext->CloseCount) );

    //
    //  Relinquish write acccess to the context
    //
    
    CtxReleaseResource(streamContext->Resource);

    //
    //  Quit on failure after we have given up
    //  the resource
    //

    if (!NT_SUCCESS( status )) {
    
        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                    ("[Ctx]: CtxPostSetInfo -> Failed to update name in stream context for file %wZ (Cbd = %p, FileObject = %p)\n",
                     &nameInfo->Name,
                     Cbd,
                     FltObjects->FileObject) );

        goto CtxPostSetInfoCleanup;
    }
            


    //
    // Create or replace a stream handle context
    //

    status = CtxCreateOrReplaceStreamHandleContext(Cbd, 
                                                   TRUE,
                                                   &streamHandleContext,
                                                   &streamHandleContextReplaced);
    if (!NT_SUCCESS( status )) {

        //
        //  This failure will most likely be because stream contexts are not supported
        //  on the object we are trying to assign a context to or the object is being 
        //  deleted
        //  
                
        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                    ("[Ctx]: CtxPostSetInfo -> Failed to find or create stream handle context (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );

        goto CtxPostSetInfoCleanup;
    }        

    DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> Creating/Replacing stream handle context for file %wZ (Cbd = %p, FileObject = %p StreamHandleContext = %p, StreamHandleContextReplaced = %x)\n",
                 &nameInfo->Name,
                 Cbd,
                 FltObjects->FileObject,
                 streamHandleContext,
                 streamHandleContextReplaced) );

    //
    //  Acquire write acccess to the context
    //

    CtxAcquireResourceExclusive(streamHandleContext->Resource);

    //
    //  Update the file name in the context
    //

    status = CtxUpdateNameInStreamHandleContext( &nameInfo->Name, 
                                                 streamHandleContext);

    DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> Stream handle context info for file %wZ (Cbd = %p, FileObject = %p, StreamHandleContext = %p) \n\tName = %wZ\n",
                 &nameInfo->Name,
                 Cbd,
                 FltObjects->FileObject,
                 streamHandleContext,
                 &streamHandleContext->FileName) );

    //
    //  Relinquish write acccess to the context
    //

    CtxReleaseResource( streamHandleContext->Resource );

    //
    //  Quit on failure after we have given up
    //  the resource
    //

    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                    ("[Ctx]: CtxPostSetInfo -> Failed to update name in stream handle context for file %wZ (Cbd = %p, FileObject = %p)\n",
                     &nameInfo->Name,
                     Cbd,
                     FltObjects->FileObject) );

        goto CtxPostSetInfoCleanup;
    }

    
    //
    // Get the file context
    //

    status = CtxFindOrCreateFileContext( Cbd, 
                                         FALSE,     // do not create if one does not exist
                                         NULL,
                                         &fileContext,
                                         &fileContextCreated);
    if (!NT_SUCCESS( status )) {

        //
        //  This failure will most likely be because file contexts are not supported
        //  on the object we are trying to assign a context to or the object is being 
        //  deleted
        //  
                
        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                    ("[Ctx]: CtxPostSetInfo -> Failed to find file context (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );
    
        goto CtxPostSetInfoCleanup;
    }        

    DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> Getting file context for file %wZ (Cbd = %p, FileObject = %p, FileContext = %p. FileContextCreated = %x)\n",
                 &nameInfo->Name,
                 Cbd,
                 FltObjects->FileObject,
                 fileContext,
                 fileContextCreated) );

    DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostSetInfo -> File context info for file %wZ (Cbd = %p, FileObject = %p, FileContext = %p) \n\tName = %wZ\n",
                 &nameInfo->Name,
                 Cbd,
                 FltObjects->FileObject,
                 fileContext,
                 &fileContext->FileName) );
    

CtxPostSetInfoCleanup:

    
    //
    // Release the references we have acquired
    //    
        
    if (instanceContext != NULL) {

        FltReleaseContext( instanceContext );            
    }

    if (fileContext != NULL) {

        FltReleaseContext( fileContext );            
    }

    if (streamContext != NULL) {

        FltReleaseContext( streamContext );            
    }

    if (streamHandleContext != NULL) {

        FltReleaseContext( streamHandleContext );            
    }

    if (nameInfo != NULL) {

        FltReleaseFileNameInformation( nameInfo );
    }

    if (!NT_SUCCESS( status )) {
    
        DebugTrace( DEBUG_TRACE_ERROR,
                    ("[Ctx]: CtxPostSetInfo -> Failed with status 0x%x \n",
                    status) );

        //
        //  It doesn't make sense to udate Cbd->IoStatus.Status on failure since the
        //  file system has suceesfully completed the operation
        //
    }

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

    return FLT_POSTOP_FINISHED_PROCESSING;
}
예제 #5
0
NTSTATUS
FmmIsImplicitVolumeLock( 
    _In_ PFLT_CALLBACK_DATA Cbd,
    _Out_ PBOOLEAN IsLock
    )
/*++

Routine Description:

    This routine determines if an open is a implcit volume lock.

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

    IsLock                - Supplies a pointer to a user allocated boolean
                            which is used to tell the user wheather the
                            operation is an implied volume lock.
Return Value:
 
    Returns STATUS_SUCCESS if the the function determined wheather or not
    the operation was a volume lock. On STATUS_SUCCESS it is safe to check 
    IsLock to get the answer. Otherwise, the check failed and we dont know
    if it is a lock or not. STATUS_INVALID_PARAMETER indicates that the
    volume's file system type is unrecognized by the check function. This is
    an error code.

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    PFMM_INSTANCE_CONTEXT instanceContext = NULL;
    USHORT shareAccess;
    ACCESS_MASK prevAccess;

    PAGED_CODE();

    //
    //  Get the instance context so we know 
    //  which file system we are attached to.
    //

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

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

    FLT_ASSERT( instanceContext != NULL );

    //
    //  Now check to see if the open is an implied volume lock
    //  on this filesystem.
    //

    shareAccess = Cbd->Iopb->Parameters.Create.ShareAccess;
    prevAccess = Cbd->Iopb->Parameters.Create.SecurityContext->DesiredAccess;

    switch (instanceContext->FilesystemType) {

        case FLT_FSTYPE_REFS:
            *IsLock = ((!BooleanFlagOn( shareAccess, FILE_SHARE_WRITE | FILE_SHARE_DELETE)) &&
                       (BooleanFlagOn( prevAccess,(FILE_WRITE_DATA | FILE_APPEND_DATA) )));
            status = STATUS_SUCCESS;
            break;

        case FLT_FSTYPE_NTFS:
            *IsLock = ((!BooleanFlagOn( shareAccess, FILE_SHARE_WRITE | FILE_SHARE_DELETE)) &&
                          (BooleanFlagOn( prevAccess,(FILE_WRITE_DATA | FILE_APPEND_DATA) )));
            status = STATUS_SUCCESS;
            break;

        case FLT_FSTYPE_FAT:
            *IsLock = (!BooleanFlagOn( shareAccess, FILE_SHARE_WRITE | FILE_SHARE_DELETE));
            status = STATUS_SUCCESS;
            break;

        default:
            status = STATUS_INVALID_PARAMETER;
            break;
    }

FmmIsImplicitVolumeLockCleanup:

    if (instanceContext != NULL ) {

        FltReleaseContext( instanceContext );
    }

    return status;
}
예제 #6
0
VOID
CtxInstanceTeardownComplete (
    __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.

--*/
{
    PCTX_INSTANCE_CONTEXT instanceContext;
    NTSTATUS status;

    UNREFERENCED_PARAMETER( Flags );

    PAGED_CODE();

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

    DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS,
                ("[Ctx]: Getting instance context (Volume = %p, Instance = %p)\n",
                 FltObjects->Volume,
                 FltObjects->Instance) );

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

    if (NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Instance teardown for volume %wZ (Volume = %p, Instance = %p, InstanceContext = %p)\n",
                     &instanceContext->VolumeName,
                     FltObjects->Volume,
                     FltObjects->Instance,
                     instanceContext) );


        //
        //  Here the filter may perform any teardown of its own structures associated
        //  with this instance.
        //
        //  The filter should not free memory or synchronization objects allocated to
        //  objects within the instance context. That should be performed in the
        //  cleanup callback for the instance context
        //

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Releasing instance context %p for volume %wZ (Volume = %p, Instance = %p)\n",
                     instanceContext,
                     &instanceContext->VolumeName,
                     FltObjects->Volume,
                     FltObjects->Instance) );

        FltReleaseContext( instanceContext );
    } else {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Failed to get instance context (Volume = %p, Instance = %p Status = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );
    }

    DebugTrace( DEBUG_TRACE_INSTANCES,
                ("[Ctx]: Instance teardown complete ended (Instance = %p)\n",
                 FltObjects->Instance) );
}
예제 #7
0
VOID
CtxInstanceTeardownStart (
    __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.

--*/
{
#if __NDAS_FS_MINI__
	NTSTATUS				status;
	PCTX_INSTANCE_CONTEXT	instanceContext = NULL;
#endif

    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( Flags );

    PAGED_CODE();

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


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

#if __NDAS_FS_MINI__

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

	NDASFS_ASSERT( status == STATUS_SUCCESS );

	if (status == STATUS_SUCCESS) {

		LfsCleanupMountedDevice( &instanceContext->LfsDeviceExt );

		if (instanceContext->DiskDeviceObject) {

			ObDereferenceObject( instanceContext->DiskDeviceObject );
			instanceContext->DiskDeviceObject = NULL;
		}

		if (instanceContext->DeviceObject) {

			ObDereferenceObject( instanceContext->DeviceObject );
			instanceContext->DeviceObject = NULL;
		}

		if (instanceContext->VolumeProperties) {

			ExFreePoolWithTag( instanceContext->VolumeProperties, CTX_VOLUME_PROPERTY_TAG );
			instanceContext->VolumeProperties = NULL;
		}

		FltReleaseContext( instanceContext );
	}

#endif
}
예제 #8
0
FLT_PREOP_CALLBACK_STATUS
NcEnumerateDirectory (
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID *CompletionContext
    )
/*++

Routine Description:

    Routine is invoked when a directory enumeration is issued by the
    user.

Arguments:

    Data - Pointer to the filter CallbackData that is passed to us.

    FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
        opaque handles to this filter, instance, its associated volume and
        file object.

    CompletionContext - The context for the completion routine for this
        operation.

Return Value:

    The return value is the Status of the operation.

--*/
{
    //TODO WE SHOULD CONSIDER MOVING THIS TO POST BECAUSE NTFS WILL TAKE CARE
    //     OF SYNC.
    FLT_PREOP_CALLBACK_STATUS ReturnValue;
    NTSTATUS Status;

    PNC_INSTANCE_CONTEXT InstanceContext = NULL;
    PNC_STREAM_HANDLE_CONTEXT HandleContext = NULL;
    PNC_DIR_QRY_CONTEXT DirCtx = NULL;

    PFLT_FILE_NAME_INFORMATION FileNameInformation = NULL;

    NC_PATH_OVERLAP RealOverlap;
    NC_PATH_OVERLAP UserOverlap;

    BOOLEAN Reset = BooleanFlagOn( Data->Iopb->OperationFlags, SL_RESTART_SCAN );
    BOOLEAN FirstQuery;
    BOOLEAN Single = BooleanFlagOn( Data->Iopb->OperationFlags, SL_RETURN_SINGLE_ENTRY );
    BOOLEAN IgnoreCase = !BooleanFlagOn( FltObjects->FileObject->Flags,
                                         FO_OPENED_CASE_SENSITIVE );
    
    FILE_INFORMATION_CLASS InformationClass = 
        Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass;

    PVOID UserBuffer;
    ULONG BufferSize; //size for user and system buffers.

    BOOLEAN Unlock = FALSE;

    //Vars for moving data into user buffer.
    ULONG NumEntriesCopied;
    ULONG UserBufferOffset;
    ULONG LastEntryStart;
    BOOLEAN MoreRoom;
    PNC_CACHE_ENTRY NextEntry;

    DIRECTORY_CONTROL_OFFSETS Offsets;

    BOOLEAN FoundStructureOffsets;

    UNREFERENCED_PARAMETER( CompletionContext );

    PAGED_CODE();

    FLT_ASSERT( IoGetTopLevelIrp() == NULL );

    FoundStructureOffsets = NcDetermineStructureOffsets( &Offsets,
                                                         InformationClass );

    if (!FoundStructureOffsets) {

        Status = STATUS_INVALID_PARAMETER;
        ReturnValue = FLT_PREOP_COMPLETE;
        goto NcEnumerateDirectoryCleanup;
    }

    //
    //  Get our instance context.
    //

    Status = FltGetInstanceContext( FltObjects->Instance,
                                    &InstanceContext );

    if (!NT_SUCCESS( Status )) {

        ReturnValue = FLT_PREOP_COMPLETE;
        goto NcEnumerateDirectoryCleanup;
    }

    //
    //  Get the directory's name.
    //

    Status = NcGetFileNameInformation( Data,
                                       NULL,
                                       NULL,
                                       FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_DEFAULT,
                                       &FileNameInformation ); 

    if (!NT_SUCCESS( Status )) {

        ReturnValue = FLT_PREOP_COMPLETE;
        goto NcEnumerateDirectoryCleanup;
    }

    Status = FltParseFileNameInformation( FileNameInformation );

    if (!NT_SUCCESS( Status )) {

        ReturnValue = FLT_PREOP_COMPLETE;
        goto NcEnumerateDirectoryCleanup;
    }

    //
    //  See if the directory is parent of either mapping.
    //

    NcComparePath( &FileNameInformation->Name,
                   &InstanceContext->Mapping.UserMapping,
                   NULL,
                   IgnoreCase,
                   TRUE,
                   &UserOverlap );

    NcComparePath( &FileNameInformation->Name,
                   &InstanceContext->Mapping.RealMapping,
                   NULL,
                   IgnoreCase,
                   TRUE,
                   &RealOverlap );

    if (!(UserOverlap.Parent || RealOverlap.Parent )) {

        //
        //  We are not interested in this directory
        //  because it is not the parent of either
        //  mapping. This means we can just passthrough.
        //

        Status = STATUS_SUCCESS;
        ReturnValue = FLT_PREOP_SUCCESS_NO_CALLBACK;
        goto NcEnumerateDirectoryCleanup;
    }

    Status = NcStreamHandleContextAllocAndAttach( FltObjects->Filter,
                                                  FltObjects->Instance,
                                                  FltObjects->FileObject,
                                                  &HandleContext );

    if (!NT_SUCCESS( Status )) {

        ReturnValue = FLT_PREOP_COMPLETE;
        goto NcEnumerateDirectoryCleanup;
    }

    FLT_ASSERT( HandleContext != NULL );

    DirCtx = &HandleContext->DirectoryQueryContext;
    _Analysis_assume_( DirCtx != NULL );

    //
    //  Before looking at the context, we have to acquire the lock.
    //
    
    NcLockStreamHandleContext( HandleContext );
    Unlock = TRUE;

    //
    //  We don't allow multiple outstanding enumeration requests on
    //  a single handle.
    //
    //  TODO: This needs to change.
    //

    if (DirCtx->EnumerationOutstanding) {

        Status = STATUS_UNSUCCESSFUL;
        ReturnValue = FLT_PREOP_COMPLETE;
        goto NcEnumerateDirectoryCleanup;

    }

    DirCtx->EnumerationOutstanding = TRUE;

    //
    //  Now drop the lock.  We're protected by the EnumerationOutstanding
    //  flag; nobody else can muck with the enumeration context structure.
    //

    NcUnlockStreamHandleContext( HandleContext );
    Unlock = FALSE;

    //
    //  Now we need to initialize or clear the cache and query options.
    //
    
    Status = NcStreamHandleContextEnumSetup( DirCtx,
                                             InstanceContext,
                                             &Offsets,
                                             Data,
                                             FltObjects,
                                             UserOverlap,
                                             &FirstQuery );

    if (!NT_SUCCESS( Status )) {

        ReturnValue = FLT_PREOP_COMPLETE;
        goto NcEnumerateDirectoryCleanup;
    }

    //
    //  Prepare to populate the user buffer.
    //

    UserBuffer = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;

    BufferSize = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length;

    //
    //  Lets copy data into the user buffer.
    //

    NumEntriesCopied = 0;
    UserBufferOffset = 0;

    do {

        //
        //  If there is no cache entry, populate it.
        //

        if (DirCtx->Cache.Buffer == NULL) {

            Status = NcPopulateCacheEntry( FltObjects->Instance,
                                           FltObjects->FileObject,
                                           Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length,
                                           Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass,
                                           Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName,
                                           Reset,
                                           &DirCtx->Cache);

            //
            //  We only want to reset the cache once.
            //

            Reset = FALSE;

            //
            //  There was a problem populating cache, pass up to user.
            //

            if (!NT_SUCCESS( Status )) {

                ReturnValue = FLT_PREOP_COMPLETE;
                goto NcEnumerateDirectoryCleanup;
            }

        }

        NextEntry = NcDirEnumSelectNextEntry( DirCtx, &Offsets, IgnoreCase );

        if (NextEntry == NULL) {

            //
            //  There are no more entries.
            //

            break;
        }

        if (NcSkipName( &Offsets, 
                        DirCtx, 
                        RealOverlap, 
                        &InstanceContext->Mapping,
                        IgnoreCase )) {

            //
            //  This entry is the real mapping path. That means we have to mask it...
            //  We will say there is more room and continue.
            //

            MoreRoom = TRUE;

        } else {

            //
            //  We are keeping this entry!
            //

            try {

                LastEntryStart = UserBufferOffset;
                UserBufferOffset = NcCopyDirEnumEntry( UserBuffer,
                                                       UserBufferOffset,
                                                       BufferSize,
                                                       NextEntry,
                                                       &Offsets,
                                                       &MoreRoom );

            } except (NcExceptionFilter( GetExceptionInformation(), TRUE )) {

                Status = STATUS_INVALID_USER_BUFFER;
                ReturnValue = FLT_PREOP_COMPLETE;
                goto NcEnumerateDirectoryCleanup;
            }

            if (MoreRoom) {

                NumEntriesCopied++;
            }

        }// end of "we are copying entry"

    } while (MoreRoom && 
             (Single ? (NumEntriesCopied < 1) : TRUE));

    if (NumEntriesCopied > 0) {

        //
        //  Now we know what the last entry in the user buffer is going to be.
        //  Set its NextEntryOffset to 0, so that the user knows its the last element.
        //

        try {

            NcSetNextEntryOffset( Add2Ptr(UserBuffer, LastEntryStart),
                                  &Offsets, 
                                  TRUE );

        } except (NcExceptionFilter( GetExceptionInformation(), TRUE )) {

            Status = STATUS_INVALID_USER_BUFFER;
            ReturnValue = FLT_PREOP_COMPLETE;
            goto NcEnumerateDirectoryCleanup;
        }
    }

    //
    //  We finished copying data.
    //

    ReturnValue = FLT_PREOP_COMPLETE;

    if (NumEntriesCopied == 0) {

        if (FirstQuery) {

            Status = STATUS_NO_SUCH_FILE;

        } else {

            Status = STATUS_NO_MORE_FILES;
        }

    } else {

        Status = STATUS_SUCCESS;
    }

    ReturnValue = FLT_PREOP_COMPLETE;
    goto NcEnumerateDirectoryCleanup;

NcEnumerateDirectoryCleanup:

    if (ReturnValue == FLT_PREOP_COMPLETE) {
 
        //
        //  We need to write back results of query.
        //
 
        Data->IoStatus.Status = Status;
 
        if (NT_SUCCESS( Status )) {
 
            //success
            Data->IoStatus.Information = UserBufferOffset;

        } else {
 
            //failure
            Data->IoStatus.Information = 0;
        }
    }
 
    if (InstanceContext != NULL) {

        FltReleaseContext( InstanceContext );
    }
 
    if (DirCtx != NULL) {
        
        if (!Unlock) {
            NcLockStreamHandleContext( HandleContext );
            Unlock = TRUE;
        }

        FLT_ASSERT( DirCtx->EnumerationOutstanding );
        DirCtx->EnumerationOutstanding = FALSE;

        NcUnlockStreamHandleContext( HandleContext );
        Unlock = FALSE;

        FltReleaseContext( HandleContext );
    }

    FLT_ASSERT( !Unlock );
 
    if (FileNameInformation != NULL) {

        FltReleaseFileNameInformation( FileNameInformation );
    }
 
    return ReturnValue;
}
예제 #9
0
파일: DataStore.c 프로젝트: kcrazy/winekit
NTSTATUS
FmmIsMetadataOpen (
    __inout PFLT_CALLBACK_DATA Cbd,
    __out BOOLEAN* MetadataOpen
    )
/*++

Routine Description:

    This routine returns if the metadata file is open on the specified instance.

Arguments:

    Cbd                 - Supplies a pointer to the callbackData which
                          declares the requested operation.
    MetadataOpen        - Returns if the metadata file is open

Return Value:

    Status

Note:

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


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


    //
    //  Get the instance context
    //

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

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

        goto FmmIsMetadataOpenCleanup;
    }

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

    FmmAcquireResourceShared( &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]: FmmIsMetadataOpen -> Failed to get exclusive access to instance context since it is in a state of transition.\n") );
    } else {

        //
        //  Return if the metadata is opened
        //

        *MetadataOpen = BooleanFlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED );

        //
        //  Sanity - verify that this flag is reflecting the correct state of the metadata file
        //

        ASSERT ( (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED ) &&
                  (instanceContext->MetadataFileObject != NULL) &&
                  (instanceContext->MetadataHandle != NULL)) ||
                 (!FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED ) &&
                  (instanceContext->MetadataFileObject == NULL) &&
                  (instanceContext->MetadataHandle == NULL)) );

    }

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

    FmmReleaseResource( &instanceContext->MetadataResouce);


FmmIsMetadataOpenCleanup:

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

    if (instanceContext != NULL) {

        FltReleaseContext( instanceContext );
    }


    return status;
}
예제 #10
0
파일: DataStore.c 프로젝트: kcrazy/winekit
NTSTATUS
FmmSetMetadataOpenTriggerFileObject (
    __inout PFLT_CALLBACK_DATA Cbd
    )
/*++

Routine Description:

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

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


--*/
{
    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]: FmmSetMetadataOpenTriggerFileObject -> Failed to get instance context.\n") );

        goto FmmSetMetadataOpenTriggerFileObjectCleanup;
    }

    //
    //  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]: FmmSetMetadataOpenTriggerFileObject -> Failed to get exclusive access to instance context since it is in a state of transition.\n") );
    } else {

        DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                    ("[Fmm]: FmmSetMetadataOpenTriggerFileObject -> Setting MetadataOpenTriggerFileObject to %p (OldValue = %p).\n",
                     Cbd->Iopb->TargetFileObject,
                     instanceContext->MetadataOpenTriggerFileObject) );


        //
        //  Save the volume file object as the trigger file object
        //

        ASSERT((instanceContext->MetadataOpenTriggerFileObject == NULL) ||
               (instanceContext->MetadataOpenTriggerFileObject == Cbd->Iopb->TargetFileObject));

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

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

    FmmReleaseResource( &instanceContext->MetadataResouce);


FmmSetMetadataOpenTriggerFileObjectCleanup:

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

    if (instanceContext != NULL) {

        FltReleaseContext( instanceContext );
    }


    return status;;
}
예제 #11
0
파일: DataStore.c 프로젝트: kcrazy/winekit
NTSTATUS
FmmReacquireMetadataFileReferences (
    __inout PFLT_CALLBACK_DATA Cbd
    )
/*++

Routine Description:

    This routine re-acquires 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 NULL the MetadataOpenTriggerFileObject in the instance context
    if it was successfully able to open 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]: FmmReacquireMetadataFileReferences -> Failed to get instance context.\n") );

        goto FmmReacquireMetadataFileReferencesCleanup;
    }

    //
    //  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]: FmmReacquireMetadataFileReferences -> Failed to get exclusive access to instance context since it is in a state of transition.\n") );
    } else {

        //
        //  Re-open the metadata only if the trigger file object match the file object that
        //  caused this function to be called
        //

        if (instanceContext->MetadataOpenTriggerFileObject == Cbd->Iopb->TargetFileObject) {

            //
            //  Open the filter metadata file (do not read the file since we already have
            //  stuff in memory and do not create if the file does not exist
            //

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

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

                status = FmmOpenMetadata( instanceContext,
                                                 FALSE );

                //
                //  Reset the trigger file object since the volume open failed.
                //

                instanceContext->MetadataOpenTriggerFileObject = NULL;

            } else {

                DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                            ("[Fmm]: FmmReacquireMetadataFileReferences -> Exit without attempting to re-acquire 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 )) );
            }
        } else {


            DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                        ("[Fmm]: FmmReacquireMetadataFileReferences -> Exit without attempting to re-acquire 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 );


FmmReacquireMetadataFileReferencesCleanup:

    //
    // 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) );
}