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; }
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; }
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; }
/*++ 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; }
/*++ Routine Description: 创建一个新的上下文 This routine creates a new file context Arguments: FileName - Supplies the file name FileContext - Returns the file context Return Value: Status --*/ NTSTATUS CtxCreateFileContext ( __in PUNICODE_STRING FileName, __deref_out PCTX_FILE_CONTEXT *FileContext ) { NTSTATUS status; PCTX_FILE_CONTEXT fileContext; PAGED_CODE(); // 分配一个文件上下文 // Allocate a file context // DebugTrace(DEBUG_TRACE_FILE_CONTEXT_OPERATIONS, ("[Ctx]: Allocating file context \n")); status = FltAllocateContext( Globals.Filter, FLT_FILE_CONTEXT, CTX_FILE_CONTEXT_SIZE, PagedPool, &fileContext ); if (!NT_SUCCESS( status )) { DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR, ("[Ctx]: Failed to allocate file context with status 0x%x \n", status) ); return status; } // 初始化新创建的上下文 // Initialize the newly created context // 分配内存,并拷贝文件名 // Allocate and copy off the file name fileContext->FileName.MaximumLength = FileName->Length; status = CtxAllocateUnicodeString( &fileContext->FileName ); if (NT_SUCCESS( status )) { RtlCopyUnicodeString( &fileContext->FileName, FileName ); } *FileContext = fileContext; return STATUS_SUCCESS; }
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; }
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; }
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; }
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; }
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; }
NTSTATUS CtxCreateFileContext ( __in PUNICODE_STRING FileName, __deref_out PCTX_FILE_CONTEXT *FileContext ) /*++ Routine Description: This routine creates a new file context Arguments: FileName - Supplies the file name FileContext - Returns the file context Return Value: Status --*/ { NTSTATUS status; PCTX_FILE_CONTEXT fileContext; PAGED_CODE(); // // Allocate a file context // DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS, ("[Ctx]: Allocating file context \n") ); status = FltAllocateContext( Globals.Filter, FLT_FILE_CONTEXT, CTX_FILE_CONTEXT_SIZE, PagedPool, &fileContext ); if (!NT_SUCCESS( status )) { DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR, ("[Ctx]: Failed to allocate file context with status 0x%x \n", status) ); return status; } // // Initialize the newly created context // // // Allocate and copy off the file name // fileContext->FileName.MaximumLength = FileName->Length; status = CtxAllocateUnicodeString( &fileContext->FileName ); if (NT_SUCCESS( status )) { RtlCopyUnicodeString( &fileContext->FileName, FileName ); } *FileContext = fileContext; return STATUS_SUCCESS; }
__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, ¶ms2user ); 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; }