예제 #1
0
static NTSTATUS
UcaSetContext(_In_ PFLT_INSTANCE Instance,
              _In_ PVOID Target,
              _In_ FLT_CONTEXT_TYPE ContextType,
              _In_ PFLT_CONTEXT NewContext,
              _Outptr_opt_result_maybenull_ PFLT_CONTEXT *OldContext)
{
    NTSTATUS Status;

    PAGED_CODE();

    switch (ContextType)
    {
        case FLT_STREAM_CONTEXT:

            Status = FltSetStreamContext(Instance,
                                         (PFILE_OBJECT)Target,
                                         FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                         NewContext,
                                         OldContext);
            break;

        case FLT_FILE_CONTEXT:

            Status = FltSetFileContext(Instance,
                                       (PFILE_OBJECT)Target,
                                       FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                       NewContext,
                                       OldContext);
            break;

        case FLT_TRANSACTION_CONTEXT:

            Status = FltSetTransactionContext(Instance,
                                              (PKTRANSACTION)Target,
                                              FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                              NewContext,
                                              OldContext);
            break;

        case FLT_INSTANCE_CONTEXT:

            Status = FltSetInstanceContext(Instance,
                                           FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                           NewContext,
                                           OldContext);
            break;

        default:

            Status = STATUS_INVALID_PARAMETER;
            break;
    }

    return Status;
}
예제 #2
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;
}
예제 #3
0
파일: ctxinit.c 프로젝트: 340211173/hf-2011
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;
}
예제 #4
0
__checkReturn
NTSTATUS
FLTAPI
InstanceSetup (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_SETUP_FLAGS Flags,
    __in DEVICE_TYPE VolumeDeviceType,
    __in FLT_FILESYSTEM_TYPE VolumeFilesystemType
    )
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    PInstanceContext pInstanceCtx = NULL;
    PVolumeContext pVolumeContext = NULL;

    UNREFERENCED_PARAMETER( Flags );

    ASSERT( FltObjects->Filter == gFileMgr.m_FileFilter );

    if ( FLT_FSTYPE_RAW == VolumeFilesystemType)
    {
        return STATUS_FLT_DO_NOT_ATTACH;
    }

    if ( FILE_DEVICE_NETWORK_FILE_SYSTEM == VolumeDeviceType )
    {
        return STATUS_FLT_DO_NOT_ATTACH;
    }

    __try
    {
        status = FltAllocateContext(
            gFileMgr.m_FileFilter,
            FLT_INSTANCE_CONTEXT,
            sizeof( InstanceContext ),
            NonPagedPool,
            (PFLT_CONTEXT*) &pInstanceCtx
            );

        if ( !NT_SUCCESS( status ) )
        {
            pInstanceCtx = NULL;
            __leave;
        }

        RtlZeroMemory( pInstanceCtx, sizeof( InstanceContext ) );

        status = FltAllocateContext(
            gFileMgr.m_FileFilter,
            FLT_VOLUME_CONTEXT,
            sizeof( VolumeContext ),
            NonPagedPool,
            (PFLT_CONTEXT*) &pVolumeContext
            );

        if ( !NT_SUCCESS( status ) )
        {
            pVolumeContext = NULL;
            __leave;
        }
        
        RtlZeroMemory( pVolumeContext, sizeof( VolumeContext ) );

        // just for fun
        pInstanceCtx->m_VolumeDeviceType = VolumeDeviceType;
        pInstanceCtx->m_VolumeFilesystemType = VolumeFilesystemType;

        status = FillVolumeProperties( FltObjects, pVolumeContext );
        if ( !NT_SUCCESS( status ) )
        {
            __leave;
        }

        ASSERT( VolumeDeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM );

        VERDICT Verdict = VERDICT_NOT_FILTERED;
        if ( gFileMgr.m_FltSystem->IsFiltersExist() )
        {
            VolumeInterceptorContext event(
                FltObjects,
                pInstanceCtx,
                pVolumeContext,
                VOLUME_MINIFILTER,
                OP_VOLUME_ATTACH,
                0,
                PostProcessing
                );

            PARAMS_MASK params2user;
            status = gFileMgr.m_FltSystem->FilterEvent(
                &event,
                &Verdict,
                &params2user
                );

            if ( NT_SUCCESS( status ) && FlagOn( Verdict, VERDICT_ASK ) )
            {
                status = ChannelAskUser( &event, params2user, &Verdict );
                if ( NT_SUCCESS( status ) )
                {
                }
            }
        }

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

        pVolumeContext->m_Instance = FltObjects->Instance;
        status = FltSetVolumeContext(
            FltObjects->Volume,
            FLT_SET_CONTEXT_KEEP_IF_EXISTS,
            pVolumeContext,
            NULL
            );
    }
    __finally
    {
        ReleaseContext( (PFLT_CONTEXT*) &pInstanceCtx );
        ReleaseContext( (PFLT_CONTEXT*) &pVolumeContext );
    }

    return STATUS_SUCCESS;
}
NTSTATUS
FmmInstanceSetup (
    _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

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

    UNREFERENCED_PARAMETER( VolumeDeviceType );

    PAGED_CODE();

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

    //
    //  Check if the file system mounted is ntfs or fat
    //
    //  The sample picks NTFS, FAT and ReFS as examples. The metadata
    //  handling demostrated in the sample can be applied
    //  to any file system
    //

    if (VolumeFilesystemType != FLT_FSTYPE_NTFS && VolumeFilesystemType != FLT_FSTYPE_FAT && VolumeFilesystemType != FLT_FSTYPE_REFS) {

        //
        //  An unknown file system is mounted which we do not care
        //

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Fmm]: Unsupported file system mounted (Volume = %p, Instance = %p)\n",
                     FltObjects->Volume,
                     FltObjects->Instance) );

        status = STATUS_NOT_SUPPORTED;
        goto FmmInstanceSetupCleanup;
    }

    //
    //  Get the disk device object and make sure it is a disk device type and does not
    //  have any of the device characteristics we do not support.
    //
    //  The sample picks the device characteristics to demonstrate how to access and
    //  check the device characteristics in order to make a decision to attach. The
    //  metadata handling demostrated in the sample is not limited to the
    //  characteristics we have used in the sample.
    //

    status = FltGetDiskDeviceObject( FltObjects->Volume, &diskDeviceObject );

    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES | DEBUG_TRACE_ERROR,
                    ("[Fmm]: Failed to get device object (Volume = %p, Status = 0x%08X)\n",
                     FltObjects->Volume,
                     status) );
        goto FmmInstanceSetupCleanup;
    }

    if (diskDeviceObject->DeviceType != FILE_DEVICE_DISK ||
        FlagOn( diskDeviceObject->Characteristics, FMM_UNSUPPORTED_DEVICE_CHARACS )) {

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Fmm]: Unsupported device type or device characteristics (Volume = %p, Instance = %p DiskDeviceObjectDeviceTYpe = 0x%x, DiskDeviceObjectCharacteristics = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     diskDeviceObject->DeviceType,
                     diskDeviceObject->Characteristics) );

        ObDereferenceObject( diskDeviceObject );
        status = STATUS_NOT_SUPPORTED;
        goto FmmInstanceSetupCleanup;
    }

    ObDereferenceObject( diskDeviceObject );

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

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

    if( !NT_SUCCESS( status )) {

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

        goto FmmInstanceSetupCleanup;
    }

    FLT_ASSERT( instanceContext != NULL );

    RtlZeroMemory( instanceContext, FMM_INSTANCE_CONTEXT_SIZE );

    instanceContext->Flags = 0;
    instanceContext->Instance = FltObjects->Instance;
    instanceContext->FilesystemType = VolumeFilesystemType;
    instanceContext->Volume = FltObjects->Volume;
    ExInitializeResourceLite( &instanceContext->MetadataResource );


    //
    //  Set the instance context.
    //

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

    if( !NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES | DEBUG_TRACE_ERROR,
                    ("[Fmm]: Failed to set instance context (Volume = %p, Instance = %p, Status = 0x%08X)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );
        goto FmmInstanceSetupCleanup;
    }

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

    FmmAcquireResourceExclusive( &instanceContext->MetadataResource );

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

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

    //
    //  Open the filter metadata on disk
    //
    //  The sample will attach to volume if it finds its metadata file on the volume.
    //  If this is a manual attachment then the sample filter will create its metadata
    //  file and attach to the volume.
    //

    status = FmmOpenMetadata( instanceContext,
                              BooleanFlagOn( Flags, FLTFL_INSTANCE_SETUP_MANUAL_ATTACHMENT ) );

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

    FmmReleaseResource( &instanceContext->MetadataResource );

    if (!NT_SUCCESS( status )) {

        goto FmmInstanceSetupCleanup;
    }


FmmInstanceSetupCleanup:

    //
    //  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 ) {

        FltReleaseContext( instanceContext );
    }


    if (NT_SUCCESS( status )) {

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

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

    //
    //  If this is an automatic attachment (mount, load, etc) and we are not 
    //  attaching to this volume because we do not support attaching to this 
    //  volume, then simply return STATUS_FLT_DO_NOT_ATTACH. If we return 
    //  anything else fltmgr logs an event log indicating failure to attach. 
    //  Since this failure to attach is not really an error, we do not want 
    //  this failure to be logged as an error in the event log. For all other
    //  error codes besides the ones we consider "normal", if is ok for fltmgr
    //  to actually log the failure to attach.
    //
    //  If this is a manual attach attempt that we have failed then we want to 
    //  give the user a clear indication of why the attachment failed. Hence in 
    //  this case, we will not override the error status with STATUS_FLT_DO_NOT_ATTACH
    //  irrespective of the cause of the failure to attach
    //

    if (status == STATUS_NOT_SUPPORTED && 
       !FlagOn( Flags, FLTFL_INSTANCE_SETUP_MANUAL_ATTACHMENT )) {

        status = STATUS_FLT_DO_NOT_ATTACH;
    }

    return status;
}