static
_fileContext*
    _getOrSetContext
    (
        PFLT_CALLBACK_DATA Data
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    _fileContext* context = NULL;
    _fileContext* oldContext = NULL;

    status = FltGetFileContext( Data->Iopb->TargetInstance,
                                Data->Iopb->TargetFileObject,
                                &context );

    if( STATUS_NOT_FOUND == status )
    {
        status = FltAllocateContext( g_filter,
                                     FLT_FILE_CONTEXT,
                                     sizeof( _fileContext ),
                                     NonPagedPool,
                                     (PFLT_CONTEXT*)&context );
        
        if( STATUS_SUCCESS == status )
        {
            context->isNew = FALSE;
            context->isDelete = FALSE;
            context->isChanged = FALSE;
            context->isRead = FALSE;
            context->lastWritePid = 0;
            context->lastReadPid = 0;

            status = FltSetFileContext( Data->Iopb->TargetInstance,
                                        Data->Iopb->TargetFileObject,
                                        FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                        context,
                                        &oldContext );

            if( STATUS_FLT_CONTEXT_ALREADY_DEFINED == status )
            {
                FltReleaseContext( (PFLT_CONTEXT)context );
                context = oldContext;
            }
            else if( STATUS_SUCCESS != status )
            {
                FltReleaseContext( (PFLT_CONTEXT)context );
                context = NULL;
            }
        }
    }

    if( NULL_CONTEXT == context )
    {
        context = NULL;
    }

    return context;
}
Пример #2
0
VOID FLTAPI
UcaTransactionContextCleanupCallback(_In_ PUCA_TRANSACTION_CONTEXT TransactionContext,
                                     _In_ FLT_CONTEXT_TYPE ContextType)
{
    PUCA_DELETE_NOTIFY DeleteNotify = NULL;

    UNREFERENCED_PARAMETER(ContextType);

    PAGED_CODE();
    __debugbreak();
    ASSERT(ContextType == FLT_TRANSACTION_CONTEXT);

    if (TransactionContext->Resource != NULL)
    {
        FltAcquireResourceExclusive( TransactionContext->Resource );

        while (!IsListEmpty( &TransactionContext->DeleteNotifyList))
        {
            //  Remove every UCA_DELETE_NOTIFY, releasing their corresponding
            //  FLT_FILE_NAME_INFORMATION objects and freeing pool used by them
            DeleteNotify = CONTAINING_RECORD(RemoveHeadList(&TransactionContext->DeleteNotifyList),
                                             UCA_DELETE_NOTIFY,
                                             Links);

            FltReleaseContext(DeleteNotify->StreamContext);
            ExFreePoolWithTag(DeleteNotify, UCA_ERESOURCE_POOL_TAG);
        }

        FltReleaseResource(TransactionContext->Resource);

        //  Delete and free the DeleteNotifyList synchronization resource.
        ExDeleteResourceLite(TransactionContext->Resource);
        ExFreePoolWithTag(TransactionContext->Resource, UCA_ERESOURCE_POOL_TAG);
    }
}
Пример #3
0
NTSTATUS
CtxCreateStreamHandleContext (
    __deref_out PSTREAMHANDLE_CONTEXT *StreamHandleContext
    )
/*++

Routine Description:

    This routine creates a new stream context

Arguments:

    StreamContext         - Returns the stream context

Return Value:

    Status

--*/
{
    NTSTATUS status;
    PSTREAMHANDLE_CONTEXT streamHandleContext;

    PAGED_CODE();

    //
    //  Allocate a stream context
    //

    status = FltAllocateContext( g_FileFltContext.FileFltHandle,
                                 FLT_STREAMHANDLE_CONTEXT,
                                 STREAMHANDLE_CONTEXT_SIZE,
                                 NonPagedPool,
                                 &streamHandleContext );

    if (!NT_SUCCESS( status )) {


        return status;
    }

    //
    //  Initialize the newly created context
    //

    RtlZeroMemory( streamHandleContext, STREAMHANDLE_CONTEXT_SIZE );

    streamHandleContext->Resource = FsAllocateResource();
    if(streamHandleContext->Resource == NULL) {

        FltReleaseContext( streamHandleContext );
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    ExInitializeResourceLite( streamHandleContext->Resource );

    *StreamHandleContext = streamHandleContext;

    return STATUS_SUCCESS;
}
Пример #4
0
NTSTATUS
iCtx_CreateStreamContext (
    __in PFLT_RELATED_OBJECTS FltObjects,
    __deref_out PSTREAM_CONTEXT *StreamContext
    )
/*++

Routine Description:

    This routine creates a new stream context

Arguments:

    StreamContext         - Returns the stream context

Return Value:

    Status

--*/
{
    NTSTATUS status;
    PSTREAM_CONTEXT streamContext;

    PAGED_CODE();

    status = FltAllocateContext( FltObjects->Filter,
                                 FLT_STREAM_CONTEXT,
                                 STREAM_CONTEXT_SIZE,
                                 NonPagedPool,
                                 &streamContext );
    if (!NT_SUCCESS( status )) 
	{
        return status;
    }

    //  Initialize the newly created context
    RtlZeroMemory( streamContext, STREAM_CONTEXT_SIZE );

    streamContext->Resource = ExAllocatePoolWithTag( NonPagedPool, sizeof( ERESOURCE ),RESOURCE_TAG );
    if(streamContext->Resource == NULL)
	{
        FltReleaseContext( streamContext );
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    ExInitializeResourceLite( streamContext->Resource );

    KeInitializeSpinLock(&streamContext->Resource1) ; 

    *StreamContext = streamContext;

    return STATUS_SUCCESS;
}
Пример #5
0
/*++

Routine Description:

    This routine creates a new stream context

Arguments:

    StreamContext         - Returns the stream context

Return Value:

    Status

--*/
NTSTATUS
CtxCreateStreamHandleContext (
    __deref_out PCTX_STREAMHANDLE_CONTEXT *StreamHandleContext
    )

{
    NTSTATUS status;
    PCTX_STREAMHANDLE_CONTEXT streamHandleContext;

    PAGED_CODE();

    //
    //  Allocate a stream context
    //

    DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                ("[Ctx]: Allocating stream handle context \n") );

    status = FltAllocateContext( Globals.Filter,
                                 FLT_STREAMHANDLE_CONTEXT,
                                 CTX_STREAMHANDLE_CONTEXT_SIZE,
                                 PagedPool,
                                 &streamHandleContext );

    if (!NT_SUCCESS( status ))
	{
        DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Failed to allocate stream handle context with status 0x%x \n",
                     status) );

        return status;
    }

    //
    //  Initialize the newly created context
    //

    RtlZeroMemory( streamHandleContext, CTX_STREAMHANDLE_CONTEXT_SIZE );

    streamHandleContext->Resource = CtxAllocateResource();
    if(streamHandleContext->Resource == NULL)
	{
        FltReleaseContext( streamHandleContext );
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    ExInitializeResourceLite( streamHandleContext->Resource );

    *StreamHandleContext = streamHandleContext;

    return STATUS_SUCCESS;
}
Пример #6
0
NTSTATUS
UcaGetOrAllocContext(_In_ PFLT_INSTANCE Instance,
                     _In_ PVOID Target,
                     _In_ FLT_CONTEXT_TYPE ContextType,
                     _In_ BOOLEAN CreateIfNotFound,
                     _Outptr_ PFLT_CONTEXT *Context)
{
    PFLT_CONTEXT OldContext;
    NTSTATUS Status;

    *Context = NULL;

    /* Try to get the existing context */
    Status = UcaGetContext(Instance, Target, ContextType, Context);
    if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND)
        return Status;

    /* Check if we need to allocate a new context */
    if (Status == STATUS_NOT_FOUND && CreateIfNotFound)
    {
        /* Allocate a new context */
        Status = UcaAllocateContext(ContextType, Context);
        if (!NT_SUCCESS(Status)) return Status;

        /* Set the new context */
        Status = UcaSetContext(Instance, Target, ContextType, *Context, &OldContext);
        if (!NT_SUCCESS(Status))
        {
            /* Something went wrong, free the context */
            FltReleaseContext(*Context);

            /* Check if a context was already set */
            if (Status == STATUS_FLT_CONTEXT_ALREADY_DEFINED)
            {
                /* We're racing with some other call which managed to set the
                   context before us. We will return that context instead */
                *Context = OldContext;
                Status = STATUS_SUCCESS;
            }
            else
            {
                *Context = NULL;
            }
        }
    }

    return Status;
}
Пример #7
0
VOID
NPInstanceTeardownStart (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_TEARDOWN_FLAGS Flags
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PVOLUME_CONTEXT context = NULL;
    UNREFERENCED_PARAMETER( Flags );
    PAGED_CODE();
    PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
                  ("minifilter1!NPInstanceTeardownStart: Entered\n") );
    status = FltGetVolumeContext(FltObjects->Filter, FltObjects->Volume, &context);
    if( NT_SUCCESS(status) && context->Name.Buffer != NULL)
        DbgPrint("[%wZ]\n", &context->Name);
    FltReleaseContext( context );
}
Пример #8
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;
}
Пример #9
0
FLT_PREOP_CALLBACK_STATUS
CtxPreClose (
    _Inout_ PFLT_CALLBACK_DATA Cbd,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID *CompletionContext
    )
{

    PCTX_STREAM_CONTEXT streamContext = NULL;    
    NTSTATUS status;
    BOOLEAN streamContextCreated;

    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );

    PAGED_CODE();

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

    //
    // 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]: CtxPreClose -> Failed to find stream context (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );
    
        goto CtxPreCloseCleanup;
    }        

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

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


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

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

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


CtxPreCloseCleanup:

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

    if (streamContext != NULL) {

        FltReleaseContext( streamContext );            
    }


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

    //
    //  It doesn't make sense to fail the cleanup - so ignore any errors we may 
    //  encounter and return success
    //

    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
Пример #10
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) );
}
Пример #11
0
NTSTATUS
CtxInstanceSetup (
    __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.

Return Value:

    STATUS_SUCCESS - attach
    STATUS_FLT_DO_NOT_ATTACH - do not attach

--*/
{
    PCTX_INSTANCE_CONTEXT instanceContext = NULL;
    NTSTATUS status = STATUS_SUCCESS;
    ULONG volumeNameLength;

#if __NDAS_FS_MINI__

	ULONG					propertyLengthReturned; 

	UNICODE_STRING			ntfs;
	UNICODE_STRING			ndasNtfs;
	UNICODE_STRING			fat;
	UNICODE_STRING			ndasFat;

	PNETDISK_PARTITION		netdiskPartition;
	NETDISK_ENABLE_MODE		netdiskEnableMode;

#endif

#if __LFS__
	ULONG					propertyLengthReturned; 
	BOOLEAN					result;

	UNICODE_STRING			ntfs;
	UNICODE_STRING			ndasNtfs;
	UNICODE_STRING			fat;
	UNICODE_STRING			ndasFat;

	PENABLED_NETDISK		enabledNetdisk;
	NETDISK_ENABLE_MODE		netdiskEnableMode;
#endif

    UNREFERENCED_PARAMETER( Flags );
    UNREFERENCED_PARAMETER( VolumeDeviceType );
    UNREFERENCED_PARAMETER( VolumeFilesystemType );

    PAGED_CODE();

#if __NDAS_FS_MINI__

    DebugTrace( DEBUG_TRACE_INSTANCES,
                ("[Ctx]: Instance setup started FltObjects = %p\n", FltObjects) );

#endif

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

    //
    //  Allocate and initialize the context for this volume
    //


    //
    //  Allocate the instance context
    //

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

    status = FltAllocateContext( FltObjects->Filter,
                                 FLT_INSTANCE_CONTEXT,
                                 CTX_INSTANCE_CONTEXT_SIZE,
                                 NonPagedPool,
                                 &instanceContext );

    if (!NT_SUCCESS( status )) {

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

        goto CtxInstanceSetupCleanup;
    }

#if __NDAS_FS_MINI__

	RtlZeroMemory( instanceContext, sizeof(CTX_INSTANCE_CONTEXT) );

	status = FltGetVolumeProperties( FltObjects->Volume,
									 NULL,
									 0,
									 &propertyLengthReturned ); 


	DebugTrace( DEBUG_TRACE_INSTANCES,
				("[MiniSpy]: IRP_MJ_VOLUME_MOUNT FltGetVolumeProperties, status = %x, propertyLengthReturned = %d\n",
				 status,
				 propertyLengthReturned) );

	instanceContext->VolumeProperties = ExAllocatePoolWithTag( PagedPool, propertyLengthReturned, CTX_VOLUME_PROPERTY_TAG );

	status = FltGetVolumeProperties( FltObjects->Volume,
									 instanceContext->VolumeProperties,
									 propertyLengthReturned,
									 &propertyLengthReturned ); 

	DebugTrace( DEBUG_TRACE_INSTANCES,
				("[MiniSpy]: FltGetVolumeProperties, status = %x, propertyLengthReturned = %d\n",
				 status,
				 propertyLengthReturned) );

	if( !NT_SUCCESS( status )) {

		status = STATUS_FLT_DO_NOT_ATTACH;
		goto CtxInstanceSetupCleanup;
	}

	DebugTrace( DEBUG_TRACE_INSTANCES,
				("[MiniSpy]: FltGetVolumeProperties, DeviceType = %d "
				 "FileSystemDriverName = %wZ\n"
				 "FileSystemDeviceName = %wZ "
				 "RealDeviceName = %wZ\n",
				 instanceContext->VolumeProperties->DeviceType,
				 &instanceContext->VolumeProperties->FileSystemDriverName,
				 &instanceContext->VolumeProperties->FileSystemDeviceName,
				 &instanceContext->VolumeProperties->RealDeviceName) );

	RtlInitUnicodeString( &ntfs, L"\\Ntfs" );
	RtlInitUnicodeString( &ndasNtfs, NDAS_NTFS_DEVICE_NAME );
	RtlInitUnicodeString( &fat, L"\\Fat" );
	RtlInitUnicodeString( &ndasFat, NDAS_FAT_DEVICE_NAME );

	if (!(RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ntfs, TRUE)		||
		  RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasNtfs, TRUE)	||
		  RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &fat, TRUE)		||
		  RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasFat, TRUE))) {

		status = STATUS_FLT_DO_NOT_ATTACH;
		goto CtxInstanceSetupCleanup;
	}

	status = FltGetDeviceObject( FltObjects->Volume, &instanceContext->DeviceObject );

	if (!NT_SUCCESS(status)) {

		status = STATUS_FLT_DO_NOT_ATTACH;
		goto CtxInstanceSetupCleanup;
	}
	
	status = FltGetDiskDeviceObject( FltObjects->Volume, &instanceContext->DiskDeviceObject );

	if (!NT_SUCCESS(status)) {

		status = STATUS_FLT_DO_NOT_ATTACH;
		goto CtxInstanceSetupCleanup;
	}

	DebugTrace( DEBUG_TRACE_INSTANCES,
				("DeviceObject = %p, DiskDeviceObject = %p\n", instanceContext->DeviceObject, instanceContext->DiskDeviceObject) );


	if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasFat, TRUE) && 
		!GlobalLfs.NdasFatRwSupport && !GlobalLfs.NdasFatRoSupport ||
		RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasNtfs, TRUE) && 
		!GlobalLfs.NdasNtfsRwSupport && !GlobalLfs.NdasNtfsRoSupport) {

		NDASFS_ASSERT( FALSE );
		status = STATUS_FLT_DO_NOT_ATTACH;
		goto CtxInstanceSetupCleanup;
	}

	if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasFat, TRUE)) {

		status = NetdiskManager_PreMountVolume( GlobalLfs.NetdiskManager,
												GlobalLfs.NdasFatRwIndirect ? TRUE : FALSE,
												instanceContext->DiskDeviceObject, //pIrpSp->Parameters.MountVolume.DeviceObject,
												instanceContext->DiskDeviceObject, //pIrpSp->Parameters.MountVolume.Vpb->RealDevice,
												&netdiskPartition,
												&netdiskEnableMode );
	
	} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasNtfs, TRUE)) {

		status = NetdiskManager_PreMountVolume( GlobalLfs.NetdiskManager,
												GlobalLfs.NdasNtfsRwIndirect ? TRUE : FALSE,
												instanceContext->DiskDeviceObject, //pIrpSp->Parameters.MountVolume.DeviceObject,
												instanceContext->DiskDeviceObject, //pIrpSp->Parameters.MountVolume.Vpb->RealDevice,
												&netdiskPartition,
												&netdiskEnableMode );
	
	} else {

		status = NetdiskManager_PreMountVolume( GlobalLfs.NetdiskManager,
												FALSE,
												instanceContext->DiskDeviceObject, //pIrpSp->Parameters.MountVolume.DeviceObject,
												instanceContext->DiskDeviceObject, //pIrpSp->Parameters.MountVolume.Vpb->RealDevice,
												&netdiskPartition,
												&netdiskEnableMode );
	}


	SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ("NetdiskManager_IsNetdiskPartition status = %x\n", status) );

	if (!NT_SUCCESS(status)) {

		if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasFat, TRUE) ||
			RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasNtfs, TRUE)) {

			NDASFS_ASSERT( FALSE );
			status = STATUS_FLT_DO_NOT_ATTACH;
			goto CtxInstanceSetupCleanup;
		}

		status = STATUS_FLT_DO_NOT_ATTACH;
		goto CtxInstanceSetupCleanup;
	} 
	
	switch (netdiskEnableMode) {

	case NETDISK_READ_ONLY:

		if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &fat, TRUE)) {

			if (GlobalLfs.NdasFatRoSupport) {

				NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
												netdiskPartition,
												netdiskEnableMode,
												FALSE,
												0,
												NULL,
												NULL );
	
				NDASFS_ASSERT( FALSE );
				status = STATUS_FLT_DO_NOT_ATTACH;
				goto CtxInstanceSetupCleanup;
			}			
			
		} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasFat, TRUE)) {

			if (!GlobalLfs.NdasFatRoSupport) {

				NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
												netdiskPartition,
												netdiskEnableMode,
												FALSE,
												0,
												NULL,
												NULL );
	
				NDASFS_ASSERT( FALSE );
				status = STATUS_FLT_DO_NOT_ATTACH;
				goto CtxInstanceSetupCleanup;
			}			

		} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ntfs, TRUE)) {

			if (GlobalLfs.NdasNtfsRoSupport) {

				NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
												netdiskPartition,
												netdiskEnableMode,
												FALSE,
												0,
												NULL,
												NULL );

				NDASFS_ASSERT( FALSE );
				status = STATUS_FLT_DO_NOT_ATTACH;
				goto CtxInstanceSetupCleanup;
			}
			
		} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasNtfs, TRUE)) {

			if (!GlobalLfs.NdasNtfsRoSupport) {

				NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
												netdiskPartition,
												netdiskEnableMode,
												FALSE,
												0,
												NULL,
												NULL );

				NDASFS_ASSERT( FALSE );
				status = STATUS_FLT_DO_NOT_ATTACH;
				goto CtxInstanceSetupCleanup;
			}
			
		} else {

			NDASFS_ASSERT( FALSE );
		}

		break;

	case NETDISK_SECONDARY:
	case NETDISK_PRIMARY:
	case NETDISK_SECONDARY2PRIMARY:

		if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &fat, TRUE)) {

			if (GlobalLfs.NdasFatRwSupport &&
				FlagOn(netdiskPartition->EnabledNetdisk->NetdiskInformation.EnabledFeatures, NDASFEATURE_SIMULTANEOUS_WRITE)) {

				NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
												netdiskPartition,
												netdiskEnableMode,
												FALSE,
												0,
												NULL,
												NULL );
	
				NDASFS_ASSERT( FALSE );
				status = STATUS_FLT_DO_NOT_ATTACH;
				goto CtxInstanceSetupCleanup;
			}			
			
		} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasFat, TRUE)) {

			if (!(GlobalLfs.NdasFatRwSupport &&
				  FlagOn(netdiskPartition->EnabledNetdisk->NetdiskInformation.EnabledFeatures, NDASFEATURE_SIMULTANEOUS_WRITE))) {

				NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
												netdiskPartition,
												netdiskEnableMode,
												FALSE,
												0,
												NULL,
												NULL );
	
				NDASFS_ASSERT( FALSE );
				status = STATUS_FLT_DO_NOT_ATTACH;
				goto CtxInstanceSetupCleanup;
			}			

		} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ntfs, TRUE)) {

			if (GlobalLfs.NdasNtfsRwSupport &&
				FlagOn(netdiskPartition->EnabledNetdisk->NetdiskInformation.EnabledFeatures, NDASFEATURE_SIMULTANEOUS_WRITE)) {

				NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
												netdiskPartition,
												netdiskEnableMode,
												FALSE,
												0,
												NULL,
												NULL );

				NDASFS_ASSERT( FALSE );
				status = STATUS_FLT_DO_NOT_ATTACH;
				goto CtxInstanceSetupCleanup;
			}
			
		} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasNtfs, TRUE)) {

			if (!(GlobalLfs.NdasNtfsRwSupport &&
				  FlagOn(netdiskPartition->EnabledNetdisk->NetdiskInformation.EnabledFeatures, NDASFEATURE_SIMULTANEOUS_WRITE))) {

				NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
												netdiskPartition,
												netdiskEnableMode,
												FALSE,
												0,
												NULL,
												NULL );

				NDASFS_ASSERT( FALSE );
				status = STATUS_FLT_DO_NOT_ATTACH;
				goto CtxInstanceSetupCleanup;
			}
			
		} else {

			NDASFS_ASSERT( FALSE );
		}
	
		break;

	default:

		NDASFS_ASSERT( FALSE );
		break;
	}

	LfsReference( &GlobalLfs );

    ExInitializeFastMutex( &instanceContext->LfsDeviceExt.FastMutex );
	instanceContext->LfsDeviceExt.ReferenceCount		= 1;

	InitializeListHead( &instanceContext->LfsDeviceExt.LfsQListEntry );

	instanceContext->LfsDeviceExt.Flags = LFS_DEVICE_FLAG_INITIALIZING;

	instanceContext->LfsDeviceExt.FileSpyDeviceObject	= NULL;
	instanceContext->LfsDeviceExt.InstanceContext		= instanceContext;

	FltReferenceContext( instanceContext->LfsDeviceExt.InstanceContext );

	instanceContext->LfsDeviceExt.NetdiskPartition		= netdiskPartition;
	instanceContext->LfsDeviceExt.NetdiskEnabledMode	= netdiskEnableMode;

	instanceContext->LfsDeviceExt.FilteringMode	= LFS_NO_FILTERING;

	instanceContext->LfsDeviceExt.DiskDeviceObject			= instanceContext->DiskDeviceObject;
	instanceContext->LfsDeviceExt.MountVolumeDeviceObject	= instanceContext->DiskDeviceObject;

    SPY_LOG_PRINT( SPYDEBUG_ERROR,
                   ("FileSpy!CtxInstanceSetup: instanceContext->LfsDeviceExt.DiskDeviceObject = %p\n",
					instanceContext->LfsDeviceExt.DiskDeviceObject) );

	ExInterlockedInsertTailList( &GlobalLfs.LfsDeviceExtQueue,
								 &instanceContext->LfsDeviceExt.LfsQListEntry,
								 &GlobalLfs.LfsDeviceExtQSpinLock );


	if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ntfs, TRUE)) {

		instanceContext->LfsDeviceExt.FileSystemType = LFS_FILE_SYSTEM_NTFS;

	} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasNtfs, TRUE)) {

		instanceContext->LfsDeviceExt.FileSystemType = LFS_FILE_SYSTEM_NDAS_NTFS;
	
	} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &fat, TRUE)) {

		instanceContext->LfsDeviceExt.FileSystemType = LFS_FILE_SYSTEM_FAT;

	} else if (RtlEqualUnicodeString(&instanceContext->VolumeProperties->FileSystemDeviceName, &ndasFat, TRUE)) {

		instanceContext->LfsDeviceExt.FileSystemType = LFS_FILE_SYSTEM_NDAS_FAT;
	
	} else {

		NDASFS_ASSERT( FALSE ); 
	}

	NetdiskManager_PostMountVolume( GlobalLfs.NetdiskManager,
									instanceContext->LfsDeviceExt.NetdiskPartition,
									instanceContext->LfsDeviceExt.NetdiskEnabledMode,
									TRUE,
									instanceContext->LfsDeviceExt.FileSystemType,		
									&instanceContext->LfsDeviceExt,
									&instanceContext->LfsDeviceExt.NetdiskPartitionInformation );

	switch (netdiskEnableMode) {

	case NETDISK_READ_ONLY:

		instanceContext->LfsDeviceExt.FilteringMode = LFS_READONLY;

		break;

	case NETDISK_SECONDARY:

		instanceContext->LfsDeviceExt.FilteringMode = LFS_SECONDARY;

		break;

	case NETDISK_PRIMARY:
	case NETDISK_SECONDARY2PRIMARY:

		instanceContext->LfsDeviceExt.FilteringMode = LFS_PRIMARY;

		break;
	
	default:

		ASSERT( LFS_BUG );

		break;
	}

	SetFlag( instanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTING );

	ASSERT( instanceContext->DiskDeviceObject->Vpb->DeviceObject );

	instanceContext->LfsDeviceExt.Vpb						= instanceContext->LfsDeviceExt.DiskDeviceObject->Vpb; // Vpb will be changed in IrpSp Why ?
	instanceContext->LfsDeviceExt.BaseVolumeDeviceObject	= instanceContext->LfsDeviceExt.Vpb->DeviceObject;

	switch (instanceContext->LfsDeviceExt.FilteringMode) {

	case LFS_READONLY: {
		
		//
		//	We don't support cache purging yet.
		//

		SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ("LfsFsControlMountVolumeComplete: READONLY newDevExt->LfsDeviceExt = %p "
											"newDevExt->LfsDeviceExt.FileSystemType = %d\n",
											 &instanceContext->LfsDeviceExt, instanceContext->LfsDeviceExt.FileSystemType) );
		
		instanceContext->LfsDeviceExt.AttachedToDeviceObject = instanceContext->DeviceObject; //NULL; //instanceContext->NLExtHeader.AttachedToDeviceObject;

		NetdiskManager_MountVolumeComplete( GlobalLfs.NetdiskManager,
											instanceContext->LfsDeviceExt.NetdiskPartition,
											instanceContext->LfsDeviceExt.NetdiskEnabledMode,
											status,
											instanceContext->LfsDeviceExt.AttachedToDeviceObject );

		status = SpyFsControlReadonlyMountVolumeComplete( &instanceContext->LfsDeviceExt );

		break;
	}

	case LFS_PRIMARY: {

		instanceContext->LfsDeviceExt.AttachedToDeviceObject = instanceContext->DeviceObject; //NULL; //instanceContext->NLExtHeader.AttachedToDeviceObject;

		ASSERT( instanceContext->LfsDeviceExt.AttachedToDeviceObject );

		NetdiskManager_MountVolumeComplete( GlobalLfs.NetdiskManager,
											instanceContext->LfsDeviceExt.NetdiskPartition,
											instanceContext->LfsDeviceExt.NetdiskEnabledMode,
											status,
											instanceContext->LfsDeviceExt.AttachedToDeviceObject );

		SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ("LfsFsControlMountVolumeComplete: LFS_PRIMARY newDevExt->LfsDeviceExt = %p "
											"newDevExt->LfsDeviceExt.FileSystemType = %d\n",
											 &instanceContext->LfsDeviceExt, instanceContext->LfsDeviceExt.FileSystemType) );

		status = STATUS_SUCCESS;
		break;
	}

	case LFS_SECONDARY: {

		instanceContext->LfsDeviceExt.AttachedToDeviceObject = instanceContext->DeviceObject; //NULL; //instanceContext->NLExtHeader.AttachedToDeviceObject;
					
		NetdiskManager_MountVolumeComplete( GlobalLfs.NetdiskManager,
											instanceContext->LfsDeviceExt.NetdiskPartition,
											instanceContext->LfsDeviceExt.NetdiskEnabledMode,
											status,
											instanceContext->LfsDeviceExt.AttachedToDeviceObject );

		SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ("CtxInstanceSetup: LFS_SECONDARY newDevExt->LfsDeviceExt = %p "
											"newDevExt->LfsDeviceExt.FileSystemType = %d\n",
											 &instanceContext->LfsDeviceExt, instanceContext->LfsDeviceExt.FileSystemType) );

		status = SpyFsControlSecondaryMountVolumeComplete( &instanceContext->LfsDeviceExt );

		if (instanceContext->LfsDeviceExt.FilteringMode == LFS_SECONDARY_TO_PRIMARY) {
		
			NetdiskManager_ChangeMode( GlobalLfs.NetdiskManager,
									   instanceContext->LfsDeviceExt.NetdiskPartition,
									   &instanceContext->LfsDeviceExt.NetdiskEnabledMode );
		}

		break;
	}

	default:

		NDASFS_ASSERT( FALSE );

		NetdiskManager_MountVolumeComplete( GlobalLfs.NetdiskManager,
											instanceContext->LfsDeviceExt.NetdiskPartition,
											instanceContext->LfsDeviceExt.NetdiskEnabledMode,
											status,
											NULL );

		status = STATUS_SUCCESS;

		break;
	}

    //
    //  We completed initialization of this device object, so now
    //  clear the initializing flag.
    //

	if (status == STATUS_SUCCESS) {

		ClearFlag( instanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_INITIALIZING );
		ClearFlag( instanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTING );

		SetFlag( instanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTED );

	} else {

		NTSTATUS status2;


		NDASFS_ASSERT( FALSE );

		//
		//	Queue an event to notify user applications
		//

		XevtQueueVolumeInvalidOrLocked( -1,
										instanceContext->LfsDeviceExt.NetdiskPartitionInformation.NetdiskInformation.SlotNo,
										instanceContext->LfsDeviceExt.NetdiskPartitionInformation.NetdiskInformation.UnitDiskNo );

		//
		//	Try to unplug
		//

		status2 = NetdiskManager_UnplugNetdisk( GlobalLfs.NetdiskManager,
												instanceContext->LfsDeviceExt.NetdiskPartition,
												instanceContext->LfsDeviceExt.NetdiskEnabledMode );

		ASSERT( NT_SUCCESS(status2) );
	}

#endif

    //
    //  Get the NT volume name length
    //

    status = FltGetVolumeName( FltObjects->Volume, NULL, &volumeNameLength );

    if( !NT_SUCCESS( status ) &&
        (status != STATUS_BUFFER_TOO_SMALL) ) {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Unexpected failure in FltGetVolumeName. (Volume = %p, Instance = %p, Status = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );

        goto CtxInstanceSetupCleanup;
    }

    //
    //  Allocate a string big enough to take the volume name
    //

    instanceContext->VolumeName.MaximumLength = (USHORT) volumeNameLength;
    status = CtxAllocateUnicodeString( &instanceContext->VolumeName );

    if( !NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Failed to allocate volume name string. (Volume = %p, Instance = %p, Status = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );

        goto CtxInstanceSetupCleanup;
    }

    //
    //  Get the NT volume name
    //

    status = FltGetVolumeName( FltObjects->Volume, &instanceContext->VolumeName, &volumeNameLength );

    if( !NT_SUCCESS( status ) ) {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Unexpected failure in FltGetVolumeName. (Volume = %p, Instance = %p, Status = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );

        goto CtxInstanceSetupCleanup;
    }


    instanceContext->Instance = FltObjects->Instance;
    instanceContext->Volume = FltObjects->Volume;

    //
    //  Set the instance context.
    //

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

    status = FltSetInstanceContext( FltObjects->Instance,
                                    FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                    instanceContext,
                                    NULL );

    if( !NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Failed to set instance context for volume %wZ (Volume = %p, Instance = %p, Status = 0x%08X)\n",
                     &instanceContext->VolumeName,
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );
        goto CtxInstanceSetupCleanup;
    }

CtxInstanceSetupCleanup:

#if __NDAS_FS_MINI__

	if (status != STATUS_SUCCESS) {

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

		if (FlagOn(instanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_INITIALIZING)) {

			LfsDeviceExt_Dereference( &instanceContext->LfsDeviceExt );
		}
	}

#endif

    //
    //  If FltAllocateContext suceeded then we MUST release the context,
    //  irrespective of whether FltSetInstanceContext suceeded or not.
    //
    //  FltAllocateContext increments the ref count by one.
    //  A successful FltSetInstanceContext increments the ref count by one
    //  and also associates the context with the file system object
    //
    //  FltReleaseContext decrements the ref count by one.
    //
    //  When FltSetInstanceContext succeeds, calling FltReleaseContext will
    //  leave the context with a ref count of 1 corresponding to the internal
    //  reference to the context from the file system structures
    //
    //  When FltSetInstanceContext fails, calling FltReleaseContext will
    //  leave the context with a ref count of 0 which is correct since
    //  there is no reference to the context from the file system structures
    //

    if ( instanceContext != NULL ) {

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

        FltReleaseContext( instanceContext );
    }


    if (NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Ctx]: Instance setup complete (Volume = %p, Instance = %p). Filter will attach to the volume.\n",
                     FltObjects->Volume,
                     FltObjects->Instance) );
    } else {

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Ctx]: Instance setup complete (Volume = %p, Instance = %p). Filter will not attach to the volume.\n",
                     FltObjects->Volume,
                     FltObjects->Instance) );
    }

    return status;
}
Пример #12
0
/*++

Routine Description:

    This routine creates a stream handle context for the target stream
    handle. Optionally, if the context already exists, this routine
    replaces it with the new context and releases the old context

Arguments:

    Cbd                   - Supplies a pointer to the callbackData which
                            declares the requested operation.
    ReplaceIfExists       - Supplies if the stream handle context must be
                            replaced if already present
    StreamContext         - Returns the stream context
    ContextReplaced       - Returns if an existing context was replaced

Return Value:

    Status

--*/
NTSTATUS
CtxCreateOrReplaceStreamHandleContext (
    __in PFLT_CALLBACK_DATA Cbd,
    __in BOOLEAN ReplaceIfExists,
    __deref_out PCTX_STREAMHANDLE_CONTEXT *StreamHandleContext,
    __out_opt PBOOLEAN ContextReplaced
    )
{
    NTSTATUS status;
    PCTX_STREAMHANDLE_CONTEXT streamHandleContext;
    PCTX_STREAMHANDLE_CONTEXT oldStreamHandleContext;

    PAGED_CODE();

    *StreamHandleContext = NULL;
    if (ContextReplaced != NULL) *ContextReplaced = FALSE;

    //
    //  Create a stream context
    //

    DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                ("[Ctx]: Creating stream handle context (FileObject = %p, Instance = %p)\n",
                 Cbd->Iopb->TargetFileObject,
                 Cbd->Iopb->TargetInstance) );

    status = CtxCreateStreamHandleContext( &streamHandleContext );

    if (!NT_SUCCESS( status ))
	{
        DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Failed to create stream context with status 0x%x. (FileObject = %p, Instance = %p)\n",
                    status,
                    Cbd->Iopb->TargetFileObject,
                    Cbd->Iopb->TargetInstance) );

        return status;
    }

    //
    //  Set the new context we just allocated on the file object
    //

    DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                ("[Ctx]: Setting stream context %p (FileObject = %p, Instance = %p, ReplaceIfExists = %x)\n",
                 streamHandleContext,
                 Cbd->Iopb->TargetFileObject,
                 Cbd->Iopb->TargetInstance,
                 ReplaceIfExists) );

    status = FltSetStreamHandleContext( Cbd->Iopb->TargetInstance,
                                        Cbd->Iopb->TargetFileObject,
                                        ReplaceIfExists ? FLT_SET_CONTEXT_REPLACE_IF_EXISTS : FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                        streamHandleContext,
                                        &oldStreamHandleContext );

    if (!NT_SUCCESS( status ))
	{
        DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Failed to set stream handle context with status 0x%x. (FileObject = %p, Instance = %p)\n",
                    status,
                    Cbd->Iopb->TargetFileObject,
                    Cbd->Iopb->TargetInstance) );

        //
        //  We release the context here because FltSetStreamContext failed
        //
        //  If FltSetStreamContext succeeded then the context will be returned
        //  to the caller. The caller will use the context and then release it
        //  when he is done with the context.
        //

        DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Releasing stream handle context %p (FileObject = %p, Instance = %p)\n",
                     streamHandleContext,
                     Cbd->Iopb->TargetFileObject,
                     Cbd->Iopb->TargetInstance) );

        FltReleaseContext( streamHandleContext );

        if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED)
		{
            //
            //  FltSetStreamContext failed for a reason other than the context already
            //  existing on the stream. So the object now does not have any context set
            //  on it. So we return failure to the caller.
            //

            DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                        ("[Ctx]: Failed to set stream context with status 0x%x != STATUS_FLT_CONTEXT_ALREADY_DEFINED. (FileObject = %p, Instance = %p)\n",
                        status,
                        Cbd->Iopb->TargetFileObject,
                        Cbd->Iopb->TargetInstance) );

            return status;
        }

        //
        //  We will reach here only if we have failed with STATUS_FLT_CONTEXT_ALREADY_DEFINED
        //  and we can fail with that code only if the context already exists and we have used
        //  the FLT_SET_CONTEXT_KEEP_IF_EXISTS flag

        ASSERT( ReplaceIfExists  == FALSE );

        //
        //  Race condition. Someone has set a context after we queried it.
        //  Use the already set context instead
        //

        DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Stream context already defined. Retaining old stream context %p (FileObject = %p, Instance = %p)\n",
                     oldStreamHandleContext,
                     Cbd->Iopb->TargetFileObject,
                     Cbd->Iopb->TargetInstance) );

        //
        //  Return the existing context. Note that the new context that we allocated has already been
        //  realeased above.
        //

        streamHandleContext = oldStreamHandleContext;
        status = STATUS_SUCCESS;

    } 
	else 
	{
        //
        //  FltSetStreamContext has suceeded. The new context will be returned
        //  to the caller. The caller will use the context and then release it
        //  when he is done with the context.
        //
        //  However, if we have replaced an existing context then we need to
        //  release the old context so as to decrement the ref count on it.
        //
        //  Note that the memory allocated to the objects within the context
        //  will be freed in the context cleanup and must not be done here.
        //

        if ( ReplaceIfExists && oldStreamHandleContext != NULL) 
		{
            DebugTrace( DEBUG_TRACE_STREAMHANDLE_CONTEXT_OPERATIONS,
                        ("[Ctx]: Releasing old stream handle context %p (FileObject = %p, Instance = %p)\n",
                         oldStreamHandleContext,
                         Cbd->Iopb->TargetFileObject,
                         Cbd->Iopb->TargetInstance) );

            FltReleaseContext( oldStreamHandleContext );
            if (ContextReplaced != NULL) *ContextReplaced = TRUE;
        }
    }

    *StreamHandleContext = streamHandleContext;

    return status;
}
Пример #13
0
NTSTATUS
CtxCreateOrReplaceStreamHandleContext (
    __in PFLT_CALLBACK_DATA Cbd,
    __in BOOLEAN ReplaceIfExists,
    __deref_out PSTREAMHANDLE_CONTEXT *StreamHandleContext,
    __out_opt PBOOLEAN ContextReplaced
    )
/*++

Routine Description:

    This routine creates a stream handle context for the target stream
    handle. Optionally, if the context already exists, this routine
    replaces it with the new context and releases the old context

Arguments:

    Cbd                   - Supplies a pointer to the callbackData which
                            declares the requested operation.
    ReplaceIfExists       - Supplies if the stream handle context must be
                            replaced if already present
    StreamContext         - Returns the stream context
    ContextReplaced       - Returns if an existing context was replaced

Return Value:

    Status

--*/
{
    NTSTATUS status;
    PSTREAMHANDLE_CONTEXT streamHandleContext;
    PSTREAMHANDLE_CONTEXT oldStreamHandleContext;

    PAGED_CODE();

    *StreamHandleContext = NULL;
    if (ContextReplaced != NULL) *ContextReplaced = FALSE;

    //
    //  Create a stream context
    //

    status = CtxCreateStreamHandleContext( &streamHandleContext );

    if (!NT_SUCCESS( status )) {

        return status;
    }

    //
    //  Set the new context we just allocated on the file object
    //

    status = FltSetStreamHandleContext( Cbd->Iopb->TargetInstance,
                                        Cbd->Iopb->TargetFileObject,
                                        ReplaceIfExists ? FLT_SET_CONTEXT_REPLACE_IF_EXISTS : FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                        streamHandleContext,
                                        &oldStreamHandleContext );

    if (!NT_SUCCESS( status )) {

        //
        //  We release the context here because FltSetStreamContext failed
        //
        //  If FltSetStreamContext succeeded then the context will be returned
        //  to the caller. The caller will use the context and then release it
        //  when he is done with the context.
        //


        FltReleaseContext( streamHandleContext );

        if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED) {

            //
            //  FltSetStreamContext failed for a reason other than the context already
            //  existing on the stream. So the object now does not have any context set
            //  on it. So we return failure to the caller.
            //


            return status;
        }

        //
        //  We will reach here only if we have failed with STATUS_FLT_CONTEXT_ALREADY_DEFINED
        //  and we can fail with that code only if the context already exists and we have used
        //  the FLT_SET_CONTEXT_KEEP_IF_EXISTS flag

        ASSERT( ReplaceIfExists  == FALSE );

        //
        //  Race condition. Someone has set a context after we queried it.
        //  Use the already set context instead
        //


        //
        //  Return the existing context. Note that the new context that we allocated has already been
        //  realeased above.
        //

        streamHandleContext = oldStreamHandleContext;
        status = STATUS_SUCCESS;

    } else {

        //
        //  FltSetStreamContext has suceeded. The new context will be returned
        //  to the caller. The caller will use the context and then release it
        //  when he is done with the context.
        //
        //  However, if we have replaced an existing context then we need to
        //  release the old context so as to decrement the ref count on it.
        //
        //  Note that the memory allocated to the objects within the context
        //  will be freed in the context cleanup and must not be done here.
        //

        if ( ReplaceIfExists &&
             oldStreamHandleContext != NULL) {

	      streamHandleContext->TaskState = oldStreamHandleContext->TaskState;

            FltReleaseContext( oldStreamHandleContext );
            if (ContextReplaced != NULL) *ContextReplaced = TRUE;
        }
    }

    *StreamHandleContext = streamHandleContext;

    return status;
}
Пример #14
0
NTSTATUS
CtxFindOrCreateFileContext (
    __in PFLT_CALLBACK_DATA Cbd,
    __in BOOLEAN CreateIfNotFound,
    __in_opt PUNICODE_STRING FileName,
    __deref_out PCTX_FILE_CONTEXT *FileContext,
    __out_opt PBOOLEAN ContextCreated
    )
/*++

Routine Description:

    This routine finds the file context for the target file.
    Optionally, if the context does not exist this routing creates
    a new one and attaches the context to the file.

Arguments:

    Cbd                   - Supplies a pointer to the callbackData which
                            declares the requested operation.
    CreateIfNotFound      - Supplies if the file context must be created if missing
    FileName              - Supplies the file name
    FileContext           - Returns the file context
    ContextCreated        - Returns if a new context was created

Return Value:

    Status

--*/
{
    NTSTATUS status;
    PCTX_FILE_CONTEXT fileContext;
    PCTX_FILE_CONTEXT oldFileContext;

    PAGED_CODE();

    *FileContext = NULL;
    if (ContextCreated != NULL) *ContextCreated = FALSE;

    //
    //  First try to get the file context.
    //

    DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                ("[Ctx]: Trying to get file context (FileObject = %p, Instance = %p)\n",
                 Cbd->Iopb->TargetFileObject,
                 Cbd->Iopb->TargetInstance) );

    status = FltGetFileContext( Cbd->Iopb->TargetInstance,
                                  Cbd->Iopb->TargetFileObject,
                                  &fileContext );

    //
    //  If the call failed because the context does not exist
    //  and the user wants to creat a new one, the create a
    //  new context
    //

    if (!NT_SUCCESS( status ) &&
        (status == STATUS_NOT_FOUND) &&
        CreateIfNotFound) {


        //
        //  Create a file context
        //

        DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Creating file context (FileObject = %p, Instance = %p)\n",
                     Cbd->Iopb->TargetFileObject,
                     Cbd->Iopb->TargetInstance) );

        status = CtxCreateFileContext( FileName, &fileContext );

        if (!NT_SUCCESS( status )) {

            DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                        ("[Ctx]: Failed to create file context with status 0x%x. (FileObject = %p, Instance = %p)\n",
                        status,
                        Cbd->Iopb->TargetFileObject,
                        Cbd->Iopb->TargetInstance) );

            return status;
        }


        //
        //  Set the new context we just allocated on the file object
        //

        DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Setting file context %p (FileObject = %p, Instance = %p)\n",
                     fileContext,
                     Cbd->Iopb->TargetFileObject,
                     Cbd->Iopb->TargetInstance) );

        status = FltSetFileContext( Cbd->Iopb->TargetInstance,
                                      Cbd->Iopb->TargetFileObject,
                                      FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                      fileContext,
                                      &oldFileContext );

        if (!NT_SUCCESS( status )) {

            DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                        ("[Ctx]: Failed to set file context with status 0x%x. (FileObject = %p, Instance = %p)\n",
                        status,
                        Cbd->Iopb->TargetFileObject,
                        Cbd->Iopb->TargetInstance) );
            //
            //  We release the context here because FltSetFileContext failed
            //
            //  If FltSetFileContext succeeded then the context will be returned
            //  to the caller. The caller will use the context and then release it
            //  when he is done with the context.
            //

            DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                        ("[Ctx]: Releasing file context %p (FileObject = %p, Instance = %p)\n",
                         fileContext,
                         Cbd->Iopb->TargetFileObject,
                         Cbd->Iopb->TargetInstance) );

            FltReleaseContext( fileContext );

            if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED) {

                //
                //  FltSetFileContext failed for a reason other than the context already
                //  existing on the file. So the object now does not have any context set
                //  on it. So we return failure to the caller.
                //

                DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                            ("[Ctx]: Failed to set file context with status 0x%x != STATUS_FLT_CONTEXT_ALREADY_DEFINED. (FileObject = %p, Instance = %p)\n",
                            status,
                            Cbd->Iopb->TargetFileObject,
                            Cbd->Iopb->TargetInstance) );

                return status;
            }

            //
            //  Race condition. Someone has set a context after we queried it.
            //  Use the already set context instead
            //

            DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                        ("[Ctx]: File context already defined. Retaining old file context %p (FileObject = %p, Instance = %p)\n",
                         oldFileContext,
                         Cbd->Iopb->TargetFileObject,
                         Cbd->Iopb->TargetInstance) );

            //
            //  Return the existing context. Note that the new context that we allocated has already been
            //  realeased above.
            //

            fileContext = oldFileContext;
            status = STATUS_SUCCESS;

        } else {

            if (ContextCreated != NULL) *ContextCreated = TRUE;
        }
    }

    *FileContext = fileContext;

    return status;
}
Пример #15
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;
}
Пример #16
0
static NTSTATUS
UcaAllocateContext(_In_ FLT_CONTEXT_TYPE ContextType,
                   _Outptr_ PFLT_CONTEXT *Context)

{
    PUCA_TRANSACTION_CONTEXT TransactionContext;
    NTSTATUS Status;

    PAGED_CODE();

    switch (ContextType)
    {
        case FLT_STREAM_CONTEXT:
            /* Allocate stream context */
            Status = FltAllocateContext(DriverData.FilterHandle,
                                        FLT_STREAM_CONTEXT,
                                        sizeof(UCA_STREAM_CONTEXT),
                                        UCA_CONTEXT_POOL_TYPE,
                                        Context);

            if (NT_SUCCESS(Status))
            {
                RtlZeroMemory(*Context, sizeof(UCA_STREAM_CONTEXT));
                FltInitializePushLock(&((PUCA_STREAM_CONTEXT)*Context)->Lock);
            }
            break;

        case FLT_FILE_CONTEXT:
            /* Allocate file context */
            Status = FltAllocateContext(DriverData.FilterHandle,
                                        FLT_FILE_CONTEXT,
                                        sizeof(UCA_STREAM_CONTEXT),
                                        UCA_CONTEXT_POOL_TYPE,
                                        Context);
            if (NT_SUCCESS(Status))
            {
                RtlZeroMemory(*Context, sizeof(UCA_STREAM_CONTEXT));
                FltInitializePushLock(&((PUCA_STREAM_CONTEXT)*Context)->Lock);
            }
            break;

        case FLT_TRANSACTION_CONTEXT:
            /* Allocate transaction context */
            Status = FltAllocateContext(DriverData.FilterHandle,
                                        FLT_TRANSACTION_CONTEXT,
                                        sizeof(UCA_TRANSACTION_CONTEXT),
                                        UCA_CONTEXT_POOL_TYPE,
                                        Context);

            if (NT_SUCCESS(Status))
            {
                TransactionContext = (PUCA_TRANSACTION_CONTEXT)*Context;

                /* Zero the memory */
                RtlZeroMemory(TransactionContext, sizeof(UCA_TRANSACTION_CONTEXT));

                /* Initialize the notify list */
                InitializeListHead(&TransactionContext->DeleteNotifyList);

                /* The resource needs to be in NPP */
                TransactionContext->Resource = (PERESOURCE)ExAllocatePoolWithTag(NonPagedPool,
                                                                                 sizeof(ERESOURCE),
                                                                                 UCA_ERESOURCE_POOL_TAG);
                if (TransactionContext->Resource == NULL)
                {
                    FltReleaseContext(TransactionContext);
                    return STATUS_INSUFFICIENT_RESOURCES;
                }

                /* Initialize the lock */
                ExInitializeResourceLite(TransactionContext->Resource);
            }
            break;

        case FLT_INSTANCE_CONTEXT:
            /* Allocate instance context */
            Status = FltAllocateContext(DriverData.FilterHandle,
                                        FLT_INSTANCE_CONTEXT,
                                        sizeof(UCA_INSTANCE_CONTEXT),
                                        UCA_CONTEXT_POOL_TYPE,
                                        Context);

            if (NT_SUCCESS(Status))
            {
                RtlZeroMemory(*Context, sizeof(UCA_INSTANCE_CONTEXT));
            }
            break;

        default:
            Status = STATUS_INVALID_PARAMETER;
            break;
    }

    return Status;
}
Пример #17
0
NTSTATUS
CtxInstanceSetup (
    __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.

Return Value:

    STATUS_SUCCESS - attach
    STATUS_FLT_DO_NOT_ATTACH - do not attach

--*/
{
    PCTX_INSTANCE_CONTEXT instanceContext = NULL;
    NTSTATUS status = STATUS_SUCCESS;
    ULONG volumeNameLength;

    UNREFERENCED_PARAMETER( Flags );
    UNREFERENCED_PARAMETER( VolumeDeviceType );
    UNREFERENCED_PARAMETER( VolumeFilesystemType );

    PAGED_CODE();

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


    //
    //  Allocate and initialize the context for this volume
    //


    //
    //  Allocate the instance context
    //

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

    status = FltAllocateContext( FltObjects->Filter,
                                 FLT_INSTANCE_CONTEXT,
                                 CTX_INSTANCE_CONTEXT_SIZE,
                                 NonPagedPool,
                                 &instanceContext );

    if (!NT_SUCCESS( status )) {

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

        goto CtxInstanceSetupCleanup;
    }

    //
    //  Get the NT volume name length
    //

    status = FltGetVolumeName( FltObjects->Volume, NULL, &volumeNameLength );

    if( !NT_SUCCESS( status ) &&
        (status != STATUS_BUFFER_TOO_SMALL) ) {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Unexpected failure in FltGetVolumeName. (Volume = %p, Instance = %p, Status = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );

        goto CtxInstanceSetupCleanup;
    }

    //
    //  Allocate a string big enough to take the volume name
    //

    instanceContext->VolumeName.MaximumLength = (USHORT) volumeNameLength;
    status = CtxAllocateUnicodeString( &instanceContext->VolumeName );

    if( !NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Failed to allocate volume name string. (Volume = %p, Instance = %p, Status = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );

        goto CtxInstanceSetupCleanup;
    }

    //
    //  Get the NT volume name
    //

    status = FltGetVolumeName( FltObjects->Volume, &instanceContext->VolumeName, &volumeNameLength );

    if( !NT_SUCCESS( status ) ) {

        DebugTrace( DEBUG_TRACE_INSTANCE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Unexpected failure in FltGetVolumeName. (Volume = %p, Instance = %p, Status = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );

        goto CtxInstanceSetupCleanup;
    }


    instanceContext->Instance = FltObjects->Instance;
    instanceContext->Volume = FltObjects->Volume;

    //
    //  Set the instance context.
    //

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

    status = FltSetInstanceContext( FltObjects->Instance,
                                    FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                    instanceContext,
                                    NULL );

    if( !NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Failed to set instance context for volume %wZ (Volume = %p, Instance = %p, Status = 0x%08X)\n",
                     &instanceContext->VolumeName,
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );
        goto CtxInstanceSetupCleanup;
    }


CtxInstanceSetupCleanup:

    //
    //  If FltAllocateContext suceeded then we MUST release the context,
    //  irrespective of whether FltSetInstanceContext suceeded or not.
    //
    //  FltAllocateContext increments the ref count by one.
    //  A successful FltSetInstanceContext increments the ref count by one
    //  and also associates the context with the file system object
    //
    //  FltReleaseContext decrements the ref count by one.
    //
    //  When FltSetInstanceContext succeeds, calling FltReleaseContext will
    //  leave the context with a ref count of 1 corresponding to the internal
    //  reference to the context from the file system structures
    //
    //  When FltSetInstanceContext fails, calling FltReleaseContext will
    //  leave the context with a ref count of 0 which is correct since
    //  there is no reference to the context from the file system structures
    //

    if ( instanceContext != NULL ) {

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

        FltReleaseContext( instanceContext );
    }


    if (NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Ctx]: Instance setup complete (Volume = %p, Instance = %p). Filter will attach to the volume.\n",
                     FltObjects->Volume,
                     FltObjects->Instance) );
    } else {

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Ctx]: Instance setup complete (Volume = %p, Instance = %p). Filter will not attach to the volume.\n",
                     FltObjects->Volume,
                     FltObjects->Instance) );
    }

    return status;
}
Пример #18
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;
}
Пример #19
0
NTSTATUS
UcaGetVolumeGuidName(_In_ PCFLT_RELATED_OBJECTS FltObjects,
                     _Inout_ PUNICODE_STRING VolumeGuidName)
{
    PUCA_INSTANCE_CONTEXT InstanceContext = NULL;
    NTSTATUS Status;

    //PAGED_CODE();

    /* Get the instance context, or create one if none exists */
    Status = UcaGetOrAllocContext(FltObjects->Instance,
                                  NULL,
                                  FLT_INSTANCE_CONTEXT,
                                  TRUE,
                                  (PFLT_CONTEXT *)&InstanceContext);
    if (!NT_SUCCESS(Status)) return Status;

    /* Check if we've already cached the volume guid in a previous call */
    if (InstanceContext->VolumeGuidName.Buffer == NULL)
    {
        UNICODE_STRING TempString;
        ULONG RequiredBytes;

        /* Get the required buffer for the string, plug an extra one for a trailing backslash */
        RequiredBytes = UCA_VOLUME_GUID_NAME_SIZE * sizeof(WCHAR) +  sizeof(WCHAR);

        /* Set the string data */
        TempString.Length = 0;
        TempString.MaximumLength = (USHORT)RequiredBytes;

        /* Allocate some memory to hold the target */
        TempString.Buffer = (PWCH)ExAllocatePoolWithTag(PagedPool,
                                                        RequiredBytes,
                                                        UCA_POOL_TAG);
        if (TempString.Buffer == NULL)
        {
            FltReleaseContext(InstanceContext);
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        /* Now get the volume guid name */
        Status = FltGetVolumeGuidName(FltObjects->Volume,
                                      &TempString,
                                      NULL);
        if (!NT_SUCCESS(Status))
        {
            TRACE_ERROR(TraceHandle, "FltGetVolumeGuidName returned %X", Status);
            ExFreePoolWithTag(TempString.Buffer, UCA_POOL_TAG);
            FltReleaseContext(InstanceContext);
            return Status;
        }

        /* Add the trailing backslash */
        RtlAppendUnicodeToString(&TempString, L"\\");

        /* Set the SourceGuidName to the TempString.
         * It's okay to set Length and MaximumLength with no synchronization
         * because those will always be the same value */
        InstanceContext->VolumeGuidName.Length = TempString.Length;
        InstanceContext->VolumeGuidName.MaximumLength = TempString.MaximumLength;

        /*  Setting the buffer, however, requires some synchronization,
         *  because another thread might be attempting to do the same,
         *  and even though they're exactly the same string, they're
         *  different allocations (buffers) so if the other thread we're
         *  racing with manages to set the buffer before us, we need to
         *  free our temporary string buffer */
        InterlockedCompareExchangePointer(&InstanceContext->VolumeGuidName.Buffer,
                                          TempString.Buffer,
                                          NULL);

        if (InstanceContext->VolumeGuidName.Buffer != TempString.Buffer)
        {
            /* We didn't manage to set the buffer, so free the TempString buffer */
            ExFreePoolWithTag(TempString.Buffer, UCA_POOL_TAG);
        }
    }

    /* Copy the guid name to the caller */
    RtlCopyUnicodeString(VolumeGuidName, &InstanceContext->VolumeGuidName);

    /* We're done with the instance context */
    FltReleaseContext(InstanceContext);

    return Status;
}
Пример #20
0
NTSTATUS
NPInstanceSetup (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_SETUP_FLAGS Flags,
    __in DEVICE_TYPE VolumeDeviceType,
    __in FLT_FILESYSTEM_TYPE VolumeFilesystemType
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PVOLUME_CONTEXT context = NULL;
    ULONG retLen;
    UCHAR volPropBuffer[sizeof(FLT_VOLUME_PROPERTIES)+512];
    PFLT_VOLUME_PROPERTIES volProp = (PFLT_VOLUME_PROPERTIES)volPropBuffer;
    PDEVICE_OBJECT devObj = NULL;

    UNREFERENCED_PARAMETER( Flags );
    UNREFERENCED_PARAMETER( VolumeDeviceType );
    UNREFERENCED_PARAMETER( VolumeFilesystemType );
    PAGED_CODE();

    PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
                  ("minifilter1!NPInstanceSetup: Entered\n") );
    try
    {
        // Allocate a volume context structure.
        status = FltAllocateContext( FltObjects->Filter,
                                     FLT_VOLUME_CONTEXT,
                                     sizeof(VOLUME_CONTEXT),
                                     NonPagedPool,
                                     &context );
        if( !NT_SUCCESS(status) )
            leave;
        // Get the volume properties, so I can get a sector size
        status = FltGetVolumeProperties( FltObjects->Volume,
                                         volProp,
                                         sizeof(volPropBuffer),
                                         &retLen );
        if( !NT_SUCCESS(status) )
            leave;
        // Get sector size
        ASSERT((volProp->SectorSize == 0) || (volProp->SectorSize >= MIN_SECTOR_SIZE));
        context->SectorSize = max(volProp->SectorSize, MIN_SECTOR_SIZE);

        // Get device object, so I can get disk name
        context->Name.Buffer = NULL;
        status = FltGetDiskDeviceObject( FltObjects->Volume, &devObj );
        if( !NT_SUCCESS(status) )
            leave;

        status = IoVolumeDeviceToDosName( devObj, &context->Name);
        if( !NT_SUCCESS(status) )
            leave;

        // Set the context
        status = FltSetVolumeContext( FltObjects->Volume,
                                      FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                      context,
                                      NULL );

        DbgPrint("minifilter1!NPInstanceSetup: [%wZ 0x%04x/0x%04x]\n",
                  &context->Name, context->SectorSize, volProp->SectorSize);
        DbgPrint("[%wZ - %wZ - %wZ]\n",
                &volProp->FileSystemDriverName,
                &volProp->FileSystemDeviceName,
                &volProp->RealDeviceName);
        if (status == STATUS_FLT_CONTEXT_ALREADY_DEFINED )
        {
            status = STATUS_SUCCESS;
        }
    }
    finally
    {
        //  Always release the context.  If the set failed, it will free the
        //  context.  If not, it will remove the reference added by the set.
        //  Note that the name buffer in the context will get freed by the
        //  NPCleanupVolumeContext() routine.
        if(context)
            FltReleaseContext( context );
        if(devObj)
            ObDereferenceObject( devObj );
    }

    return status;
}
Пример #21
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;
}
Пример #22
0
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;;
}
Пример #23
0
FLT_POSTOP_CALLBACK_STATUS
CtxPostCreate (
    _Inout_ PFLT_CALLBACK_DATA Cbd,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Inout_opt_ PVOID CbdContext,
    _In_ FLT_POST_OPERATION_FLAGS Flags
    )
{

    PCTX_FILE_CONTEXT fileContext = NULL;    
    PCTX_STREAM_CONTEXT streamContext = NULL;    
    PCTX_STREAMHANDLE_CONTEXT streamHandleContext = NULL;    
    PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
    UNICODE_STRING fileName;

    NTSTATUS status;
    BOOLEAN fileContextCreated, streamContextCreated, streamHandleContextReplaced;


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

    PAGED_CODE();

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

    //
    // Initialize defaults
    //

    status = STATUS_SUCCESS;

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

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


    //
    // Get the file 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]: CtxPostCreate -> Failed to get name information (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );

        goto CtxPostCreateCleanup;
    }

    
    //
    // Find or create a stream context
    //

    status = CtxFindOrCreateStreamContext(Cbd, 
                                          TRUE,
                                          &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]: CtxPostCreate -> Failed to find or create stream context (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );
    
        goto CtxPostCreateCleanup;
    }        

    DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostCreate -> Getting/Creating 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);

    //
    //  Increment the create count
    //

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


    DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostCreate -> Stream context info 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]: CtxPostCreate -> Failed to update name in stream context for file %wZ (Cbd = %p, FileObject = %p)\n",
                     &nameInfo->Name,
                     Cbd,
                     FltObjects->FileObject) );

        goto CtxPostCreateCleanup;
    }
            


    //
    // 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]: CtxPostCreate -> Failed to find or create stream handle context (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );

        goto CtxPostCreateCleanup;
    }        

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

        goto CtxPostCreateCleanup;
    }
    
    //
    //  After FltParseFileNameInformation, nameInfo->Name also
    //  contains the stream name. We need only the filename and do
    //  not want to include the stream name in the file context
    //

    fileName.Buffer = nameInfo->Name.Buffer;
    fileName.Length = nameInfo->Name.Length - nameInfo->Stream.Length;
    fileName.MaximumLength = fileName.Length;

    //
    // Find or create a file context
    //

    status = CtxFindOrCreateFileContext( Cbd, 
                                         TRUE,
                                         &fileName,
                                         &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]: CtxPostCreate -> Failed to find or create file context (Cbd = %p, FileObject = %p)\n",
                     Cbd,
                     FltObjects->FileObject) );

        goto CtxPostCreateCleanup;
    }        

    DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                ("[Ctx]: CtxPostCreate -> Getting/Creating 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]: CtxPostCreate -> File context info for file %wZ (Cbd = %p, FileObject = %p, FileContext = %p) \n\tName = %wZ\n",
                 &nameInfo->Name,
                 Cbd,
                 FltObjects->FileObject,
                 fileContext,
                 &fileContext->FileName) );


CtxPostCreateCleanup:
    
    
    //
    // Release the references we have acquired
    //    
        
    if (nameInfo != NULL) {

        FltReleaseFileNameInformation( nameInfo );
    }
    
    if (fileContext != NULL) {

        FltReleaseContext( fileContext );            
    }

    if (streamContext != NULL) {

        FltReleaseContext( streamContext );            
    }

    if (streamHandleContext != NULL) {

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

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


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

    return FLT_POSTOP_FINISHED_PROCESSING;
}
Пример #24
0
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;
}
Пример #25
0
/*++
Routine Description:

	这个函数查找目标流的流上下文。
    This routine finds the stream context for the target stream.
    Optionally, if the context does not exist this routing creates
    a new one and attaches the context to the stream.

Arguments:

    Cbd                   - Supplies a pointer to the callbackData which
                            declares the requested operation.
    CreateIfNotFound      - Supplies if the stream must be created if missing
    StreamContext         - Returns the stream context
    ContextCreated        - Returns if a new context was created

Return Value:

    Status

--*/
NTSTATUS
CtxFindOrCreateStreamContext (
    __in PFLT_CALLBACK_DATA Cbd,
    __in BOOLEAN CreateIfNotFound,
    __deref_out PCTX_STREAM_CONTEXT *StreamContext,
    __out_opt PBOOLEAN ContextCreated
    )
{
    NTSTATUS status;
    PCTX_STREAM_CONTEXT streamContext;
    PCTX_STREAM_CONTEXT oldStreamContext;

    PAGED_CODE();

    *StreamContext = NULL;
    if (ContextCreated != NULL) *ContextCreated = FALSE;

    //
    //  First try to get the stream context.
    //

    DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                ("[Ctx]: Trying to get stream context (FileObject = %p, Instance = %p)\n",
                 Cbd->Iopb->TargetFileObject,
                 Cbd->Iopb->TargetInstance) );

    status = FltGetStreamContext( Cbd->Iopb->TargetInstance,
                                  Cbd->Iopb->TargetFileObject,
                                  &streamContext );

    //
    //  If the call failed because the context does not exist
    //  and the user wants to creat a new one, the create a
    //  new context
    //

    if (!NT_SUCCESS( status ) && (status == STATUS_NOT_FOUND) && CreateIfNotFound)
	{
        //
        //  Create a stream context
        //

        DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                    ("[Ctx]: Creating stream context (FileObject = %p, Instance = %p)\n",
                     Cbd->Iopb->TargetFileObject,
                     Cbd->Iopb->TargetInstance) );

        status = CtxCreateStreamContext( &streamContext );

        if (!NT_SUCCESS( status )) 
		{
            DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                        ("[Ctx]: Failed to create stream context with status 0x%x. (FileObject = %p, Instance = %p)\n",
                        status,
                        Cbd->Iopb->TargetFileObject,
                        Cbd->Iopb->TargetInstance) );

            return status;
        }


        //
        //  Set the new context we just allocated on the file object
        //

        DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                    ("[Ctx]: Setting stream context %p (FileObject = %p, Instance = %p)\n",
                     streamContext,
                     Cbd->Iopb->TargetFileObject,
                     Cbd->Iopb->TargetInstance) );

        status = FltSetStreamContext( Cbd->Iopb->TargetInstance,
                                      Cbd->Iopb->TargetFileObject,
                                      FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                      streamContext,
                                      &oldStreamContext );

        if (!NT_SUCCESS( status ))
		{
            DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                        ("[Ctx]: Failed to set stream context with status 0x%x. (FileObject = %p, Instance = %p)\n",
                        status,
                        Cbd->Iopb->TargetFileObject,
                        Cbd->Iopb->TargetInstance) );
            //
            //  We release the context here because FltSetStreamContext failed
            //
            //  If FltSetStreamContext succeeded then the context will be returned
            //  to the caller. The caller will use the context and then release it
            //  when he is done with the context.
            //

            DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                        ("[Ctx]: Releasing stream context %p (FileObject = %p, Instance = %p)\n",
                         streamContext,
                         Cbd->Iopb->TargetFileObject,
                         Cbd->Iopb->TargetInstance) );

            FltReleaseContext( streamContext );

            if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED) 
			{
                //
                //  FltSetStreamContext failed for a reason other than the context already
                //  existing on the stream. So the object now does not have any context set
                //  on it. So we return failure to the caller.
                //

                DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                            ("[Ctx]: Failed to set stream context with status 0x%x != STATUS_FLT_CONTEXT_ALREADY_DEFINED. (FileObject = %p, Instance = %p)\n",
                            status,
                            Cbd->Iopb->TargetFileObject,
                            Cbd->Iopb->TargetInstance) );

                return status;
            }

            //
            //  Race condition. Someone has set a context after we queried it.
            //  Use the already set context instead
            //

            DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS,
                        ("[Ctx]: Stream context already defined. Retaining old stream context %p (FileObject = %p, Instance = %p)\n",
                         oldStreamContext,
                         Cbd->Iopb->TargetFileObject,
                         Cbd->Iopb->TargetInstance) );

            //
            //  Return the existing context. Note that the new context that we allocated has already been
            //  realeased above.
            //

            streamContext = oldStreamContext;
            status = STATUS_SUCCESS;

        }
		else 
		{
            if (ContextCreated != NULL)
				*ContextCreated = TRUE;
        }
    }

    *StreamContext = streamContext;

    return status;
}
Пример #26
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
}
Пример #27
0
/*++

Routine Description:

	这个函数找到目标文件的文件上下文。
	如果上下文不存在,这个函数创建一个新的文件上下文附加在该文件上。
    This routine finds the file context for the target file.
    Optionally, if the context does not exist this routing creates
    a new one and attaches the context to the file.

Arguments:

    Cbd                   - Supplies a pointer to the callbackData which
                            declares the requested operation.
    CreateIfNotFound      - Supplies if the file context must be created if missing
    FileName              - Supplies the file name
    FileContext           - Returns the file context
    ContextCreated        - Returns if a new context was created

Return Value:

    Status

--*/
NTSTATUS
CtxFindOrCreateFileContext (
    __in PFLT_CALLBACK_DATA Cbd,
    __in BOOLEAN CreateIfNotFound,
    __in_opt PUNICODE_STRING FileName,
    __deref_out PCTX_FILE_CONTEXT *FileContext,
    __out_opt PBOOLEAN ContextCreated
    )
{
    NTSTATUS status;
    PCTX_FILE_CONTEXT fileContext;
    PCTX_FILE_CONTEXT oldFileContext;

    PAGED_CODE();

    *FileContext = NULL;
    if (ContextCreated != NULL) *ContextCreated = FALSE;

    //  首先,尝试获取文件上下文。
    //  First try to get the file context.
    DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                ("[Ctx]: Trying to get file context (FileObject = %p, Instance = %p)\n",
                 Cbd->Iopb->TargetFileObject,
                 Cbd->Iopb->TargetInstance) );

    status = FltGetFileContext( Cbd->Iopb->TargetInstance, Cbd->Iopb->TargetFileObject, &fileContext );

    //  如果调用失败是因为上下文不存在,并且用户想创建一个新的话,那么就创建一个
    //  If the call failed because the context does not exist
    //  and the user wants to creat a new one, the create a
    //  new context
    if (!NT_SUCCESS( status ) && (status == STATUS_NOT_FOUND) && CreateIfNotFound) 
	{
        //  创建一个文件上下文
        //  Create a file context
        DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Creating file context (FileObject = %p, Instance = %p)\n",
                     Cbd->Iopb->TargetFileObject,
                     Cbd->Iopb->TargetInstance) );

        status = CtxCreateFileContext( FileName, &fileContext );

        if (!NT_SUCCESS( status )) 
		{
            DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                        ("[Ctx]: Failed to create file context with status 0x%x. (FileObject = %p, Instance = %p)\n",
                        status,
                        Cbd->Iopb->TargetFileObject,
                        Cbd->Iopb->TargetInstance) );

            return status;
        }

        //  将新建的上下文设置到文件对象上
        //  Set the new context we just allocated on the file object
        DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                    ("[Ctx]: Setting file context %p (FileObject = %p, Instance = %p)\n",
                     fileContext,
                     Cbd->Iopb->TargetFileObject,
                     Cbd->Iopb->TargetInstance) );

        status = FltSetFileContext( Cbd->Iopb->TargetInstance,
                                      Cbd->Iopb->TargetFileObject,
                                      FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                      fileContext,
                                      &oldFileContext );

        if (!NT_SUCCESS( status ))
		{
            DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                        ("[Ctx]: Failed to set file context with status 0x%x. (FileObject = %p, Instance = %p)\n",
                        status,
                        Cbd->Iopb->TargetFileObject,
                        Cbd->Iopb->TargetInstance) );

            //  由于FltSetFileContext()调用失败,释放上下文
            //  We release the context here because FltSetFileContext failed
            //
			//  如果FltSetFileContext()成功,这个上下文会返回给调用者。
			//  调用者使用这个上下文,当使用完毕之后释放它。
            //  If FltSetFileContext succeeded then the context will be returned
            //  to the caller. The caller will use the context and then release it
            //  when he is done with the context.
            DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                        ("[Ctx]: Releasing file context %p (FileObject = %p, Instance = %p)\n",
                         fileContext,
                         Cbd->Iopb->TargetFileObject,
                         Cbd->Iopb->TargetInstance) );

            FltReleaseContext( fileContext );

            if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED)
			{
                //  
                //  FltSetFileContext failed for a reason other than the context already
                //  existing on the file. So the object now does not have any context set
                //  on it. So we return failure to the caller.
                DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                            ("[Ctx]: Failed to set file context with status 0x%x != STATUS_FLT_CONTEXT_ALREADY_DEFINED. (FileObject = %p, Instance = %p)\n",
                            status,
                            Cbd->Iopb->TargetFileObject,
                            Cbd->Iopb->TargetInstance) );

                return status;
            }

            //  竞争条件。
            //  Race condition. Someone has set a context after we queried it.
            //  Use the already set context instead
            DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS,
                        ("[Ctx]: File context already defined. Retaining old file context %p (FileObject = %p, Instance = %p)\n",
                         oldFileContext,
                         Cbd->Iopb->TargetFileObject,
                         Cbd->Iopb->TargetInstance) );

            //
            //  Return the existing context. Note that the new context that we allocated has already been
            //  realeased above.
            fileContext = oldFileContext;
            status = STATUS_SUCCESS;
        } 
		else
		{
            if (ContextCreated != NULL) 
				*ContextCreated = TRUE;
        }
    }

    *FileContext = fileContext;

    return status;
}
Пример #28
0
NTSTATUS
CtxFindOrCreateStreamHandleContext (
    __in PFLT_CALLBACK_DATA Cbd,
    __in BOOLEAN CreateIfNotFound,
    __deref_out PSTREAMHANDLE_CONTEXT *StreamHandleContext,
    __out_opt PBOOLEAN ContextCreated
    )
/*++

Routine Description:

    This routine finds the stream context for the target stream.
    Optionally, if the context does not exist this routing creates
    a new one and attaches the context to the stream.

Arguments:

    Cbd                   - Supplies a pointer to the callbackData which
                            declares the requested operation.
    CreateIfNotFound      - Supplies if the stream must be created if missing
    StreamContext         - Returns the stream context
    ContextCreated        - Returns if a new context was created

Return Value:

    Status

--*/
{
    NTSTATUS status;
    PSTREAMHANDLE_CONTEXT streamHandleContext;
    PSTREAMHANDLE_CONTEXT oldStreamHandleContext;

    PAGED_CODE();

    *StreamHandleContext = NULL;
    if (ContextCreated != NULL) *ContextCreated = FALSE;

    //
    //  First try to get the stream context.
    //

    status = FltGetStreamHandleContext( Cbd->Iopb->TargetInstance,
                                  Cbd->Iopb->TargetFileObject,
                                  &streamHandleContext );

    //
    //  If the call failed because the context does not exist
    //  and the user wants to creat a new one, the create a
    //  new context
    //

    if (!NT_SUCCESS( status ) &&
        (status == STATUS_NOT_FOUND) &&
        CreateIfNotFound) {


        //
        //  Create a stream context
        //

        status = CtxCreateStreamHandleContext( &streamHandleContext );

        if (!NT_SUCCESS( status )) {

            return status;
        }


        //
        //  Set the new context we just allocated on the file object
        //

        status = FltSetStreamContext( Cbd->Iopb->TargetInstance,
                                      Cbd->Iopb->TargetFileObject,
                                      FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                      streamHandleContext,
                                      &oldStreamHandleContext );

        if (!NT_SUCCESS( status )) {

            //
            //  We release the context here because FltSetStreamContext failed
            //
            //  If FltSetStreamContext succeeded then the context will be returned
            //  to the caller. The caller will use the context and then release it
            //  when he is done with the context.
            //

            FltReleaseContext( streamHandleContext );

            if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED) {

                //
                //  FltSetStreamContext failed for a reason other than the context already
                //  existing on the stream. So the object now does not have any context set
                //  on it. So we return failure to the caller.
                //

                return status;
            }

            //
            //  Race condition. Someone has set a context after we queried it.
            //  Use the already set context instead
            //

            //
            //  Return the existing context. Note that the new context that we allocated has already been
            //  realeased above.
            //

            streamHandleContext = oldStreamHandleContext;
            status = STATUS_SUCCESS;

        } else {

            if (ContextCreated != NULL) *ContextCreated = TRUE;
        }
    }

    *StreamHandleContext = streamHandleContext;

    return status;
}
Пример #29
0
NTSTATUS
PtInstanceSetup (
				 __in PCFLT_RELATED_OBJECTS FltObjects,
				 __in FLT_INSTANCE_SETUP_FLAGS Flags,
				 __in DEVICE_TYPE VolumeDeviceType,
				 __in FLT_FILESYSTEM_TYPE VolumeFilesystemType
				 )
{
	PDEVICE_OBJECT devObj = NULL;
	PVOLUME_CONTEXT ctx = NULL;
	PFILE_FS_SIZE_INFORMATION VolumeBuffer = NULL;
	NTSTATUS status = STATUS_SUCCESS;
	ULONG retLen;
	PUNICODE_STRING workingName;
	USHORT size;
	IO_STATUS_BLOCK IoStatus;

	UCHAR volPropBuffer[sizeof(FLT_VOLUME_PROPERTIES)+512];
	PFLT_VOLUME_PROPERTIES volProp = (PFLT_VOLUME_PROPERTIES)volPropBuffer;

	PAGED_CODE();

	UNREFERENCED_PARAMETER( Flags );
	UNREFERENCED_PARAMETER( VolumeDeviceType );
	UNREFERENCED_PARAMETER( VolumeFilesystemType );

	try {

		//我们在卷上下文中保存扇区大小跟一个资源,用卷上下文完成vcb的工作
		status = FltAllocateContext( FltObjects->Filter,
			FLT_VOLUME_CONTEXT,
			sizeof(VOLUME_CONTEXT),
			NonPagedPool,
			&ctx );

		if (!NT_SUCCESS(status)) 
		{
			leave;
		}

		status = FltGetVolumeProperties( FltObjects->Volume,
			volProp,
			sizeof(volPropBuffer),
			&retLen );

		if (!NT_SUCCESS(status)) 
		{

			leave;
		}

		ASSERT((volProp->SectorSize  == 0) || (volProp->SectorSize  >= MIN_SECTOR_SIZE));

		if(volProp->SectorSize  > MAX_SECTOR_SIZE)
		{
			DbgPrint("不支持这么大的扇区的磁盘 %d \n",volProp->SectorSize );
			status = STATUS_UNSUCCESSFUL;
			leave;
		}

		ctx->SectorSize = max(volProp->SectorSize ,MIN_SECTOR_SIZE);

		ctx->VolResource = X70FsdAllocateResource();

		ctx->DeviceType = volProp->DeviceType;

		VolumeBuffer = FltAllocatePoolAlignedWithTag(FltObjects->Instance,NonPagedPool,sizeof(FILE_FS_SIZE_INFORMATION),'clu');

		if(VolumeBuffer == NULL)
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			leave;
		}

		status = FltQueryVolumeInformation(
			FltObjects->Instance,
			&IoStatus,
			VolumeBuffer,
			sizeof(FILE_FS_SIZE_INFORMATION),
			FileFsSizeInformation
			); 

		if (NT_SUCCESS(status)) 
		{

			ctx->SectorsPerAllocationUnit = VolumeBuffer->SectorsPerAllocationUnit;
		}
		else
		{
			ctx->SectorsPerAllocationUnit = 1; //网络设备会返回失败。
		}

		FltIsVolumeWritable(FltObjects->Volume,&ctx->IsWritable );

		status = FltSetVolumeContext( FltObjects->Volume,
			FLT_SET_CONTEXT_KEEP_IF_EXISTS,
			ctx,
			NULL );

		if (status == STATUS_FLT_CONTEXT_ALREADY_DEFINED) 
		{
			status = STATUS_SUCCESS;
		}

	} 
	finally 
	{

		if (ctx != NULL)
		{

			FltReleaseContext( ctx );
		}
		if(VolumeBuffer != NULL)
		{
			FltFreePoolAlignedWithTag(FltObjects->Instance,VolumeBuffer,'clu');
		}
	}

	return status;
}
static
FLT_POSTOP_CALLBACK_STATUS
    FileCreateFilterPostCallback
    (
        PFLT_CALLBACK_DATA Data,
        PCFLT_RELATED_OBJECTS FltObjects,
        PVOID CompletionContext,
        FLT_POST_OPERATION_FLAGS Flags
    )
{
    FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING;
    KLOCK_QUEUE_HANDLE hMutex = { 0 };
    PFLT_FILE_NAME_INFORMATION fileInfo = NULL;
    RU32 pid = 0;
    RU64 ts = 0;
    RU32 createOptions = 0;
    RU32 createDispositions = 0;
    _fileContext* context = NULL;
    
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );
    UNREFERENCED_PARAMETER( Flags );

    // We only care about user mode for now.
    if( UserMode != Data->RequestorMode ||
        STATUS_SUCCESS != Data->IoStatus.Status )
    {
        return status;
    }

    if( FILE_CREATED == Data->IoStatus.Information )
    {
        pid = (RU32)FltGetRequestorProcessId( Data );
        ts = rpal_time_getLocal();
        
        if( !NT_SUCCESS( FltGetFileNameInformation( Data,
                                                    FLT_FILE_NAME_NORMALIZED |
                                                    FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
                                                    &fileInfo ) ) )
        {
            rpal_debug_kernel( "Failed to get file name info" );
            fileInfo = NULL;
        }
        else
        {
            //rpal_debug_kernel( "NEW: %wZ", fileInfo->Name );
        }

        if( NULL != ( context = _getOrSetContext( Data ) ) )
        {
            context->isNew = TRUE;
            FltReleaseContext( (PFLT_CONTEXT)context );
        }

        KeAcquireInStackQueuedSpinLock( &g_collector_2_mutex, &hMutex );

        g_files[ g_nextFile ].pid = pid;
        g_files[ g_nextFile ].ts = ts;
        g_files[ g_nextFile ].uid = KERNEL_ACQ_NO_USER_ID;
        g_files[ g_nextFile ].action = KERNEL_ACQ_FILE_ACTION_ADDED;

        if( NULL != fileInfo )
        {
            copyUnicodeStringToBuffer( &fileInfo->Name,
                                       g_files[ g_nextFile ].path );

            FltReleaseFileNameInformation( fileInfo );
        }

        g_nextFile++;
        if( g_nextFile == _NUM_BUFFERED_FILES )
        {
            g_nextFile = 0;
        }

        KeReleaseInStackQueuedSpinLock( &hMutex );
    }

    createOptions = Data->Iopb->Parameters.Create.Options & 0x00FFFFFF;
    createDispositions = ( Data->Iopb->Parameters.Create.Options & 0xFF000000 ) >> 24;

    if( IS_FLAG_ENABLED( createOptions, FILE_DELETE_ON_CLOSE ) )
    {
        if( NULL != ( context = _getOrSetContext( Data ) ) )
        {
            context->isDelete = TRUE;
            FltReleaseContext( (PFLT_CONTEXT)context );
        }
    }

    return status;
}