From 7ef68a668847eef8da7312397870e6811c53bf6f Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sun, 20 Dec 2015 14:23:58 -0800 Subject: [PATCH] Major refactoring: WIP --- src/sys/create.c | 3 +- src/sys/driver.h | 1 + src/sys/fsctl.c | 269 ++++++++++++++++++++++------------------------- 3 files changed, 129 insertions(+), 144 deletions(-) diff --git a/src/sys/create.c b/src/sys/create.c index d118f596..61e8e94d 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -33,11 +33,12 @@ static NTSTATUS FspFsctlCreate( PAGED_CODE(); FSP_FSCTL_FILE_CONTEXT2 *FsContext2; - FsContext2 = FspAlloc(sizeof *FsContext2); + FsContext2 = FspAllocNonPaged(sizeof *FsContext2); if (0 == FsContext2) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(FsContext2, sizeof *FsContext2); + ExInitializeFastMutex(&FsContext2->FastMutex); IrpSp->FileObject->FsContext2 = FsContext2; Irp->IoStatus.Information = FILE_OPENED; diff --git a/src/sys/driver.h b/src/sys/driver.h index 5f51d4a8..88e86824 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -411,6 +411,7 @@ VOID FspDeviceDeleteAll(VOID); /* fsctl file objects */ typedef struct { + FAST_MUTEX FastMutex; PDEVICE_OBJECT FsvolDeviceObject; } FSP_FSCTL_FILE_CONTEXT2; diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c index 5d1a2e9d..0ac6ac37 100644 --- a/src/sys/fsctl.c +++ b/src/sys/fsctl.c @@ -69,7 +69,6 @@ static NTSTATUS FspFsctlCreateVolume( { PAGED_CODE(); -#if 0 /* check parameters */ ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; @@ -114,24 +113,22 @@ static NTSTATUS FspFsctlCreateVolume( Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]); ASSERT(NT_SUCCESS(Result)); - FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject); - ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE); + FSP_FSCTL_FILE_CONTEXT2 *FsContext2 = IrpSp->FileObject->FsContext2; + ExAcquireFastMutex(&FsContext2->FastMutex); try { - HANDLE MupHandle = 0; - PDEVICE_OBJECT FsvrtDeviceObject = 0; - PDEVICE_OBJECT FsvolDeviceObject; - FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension; - BOOLEAN Inserted; - - /* quick check to see if we already have a volume */ - FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject); - if (0 != FsvolDeviceObject) + /* check to see if we already have a volume */ + if (0 != FsContext2->FsvolDeviceObject) { Result = STATUS_ACCESS_DENIED; goto exit; } + HANDLE MupHandle = 0; + PDEVICE_OBJECT FsvrtDeviceObject = 0; + PDEVICE_OBJECT FsvolDeviceObject; + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension; + /* create the volume (and virtual disk) device(s) */ Result = FspDeviceCreate(FspFsvolDeviceExtensionKind, 0, DeviceObject->DeviceType, @@ -175,9 +172,7 @@ static NTSTATUS FspFsctlCreateVolume( } /* associate the new volume device with our file object */ - FspDeviceInsertContext(DeviceObject, (UINT_PTR)IrpSp->FileObject, FsvolDeviceObject, - &FsvolDeviceExtension->ElementStorage, &Inserted); - ASSERT(Inserted); + FsContext2->FsvolDeviceObject = FsvolDeviceObject; Irp->IoStatus.Information = DeviceName.Length + sizeof(WCHAR); Result = STATUS_SUCCESS; @@ -186,13 +181,10 @@ static NTSTATUS FspFsctlCreateVolume( } finally { - ExReleaseResourceLite(&DeviceExtension->Resource); + ExReleaseFastMutex(&FsContext2->FastMutex); } return Result; -#else - return STATUS_INVALID_DEVICE_REQUEST; -#endif } static NTSTATUS FspFsctlMountVolume( @@ -200,51 +192,51 @@ static NTSTATUS FspFsctlMountVolume( { PAGED_CODE(); -#if 0 NTSTATUS Result; + PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb; + PDEVICE_OBJECT FsvrtDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject; + PDEVICE_OBJECT FsvolDeviceObject = 0; + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = 0; + PDEVICE_OBJECT *DeviceObjects = 0; + ULONG DeviceObjectCount = 0; + KIRQL Irql; - FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject); - ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE); - try + /* check the passed in device object; it must be our own and not marked delete pending */ + Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount); + if (NT_SUCCESS(Result)) { - PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb; - PDEVICE_OBJECT FsvrtDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject; - PDEVICE_OBJECT FsvolDeviceObject; - FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension; - - /* quick check to see if we already have a volume */ - FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject); - if (0 != FsvolDeviceObject) - { - Result = STATUS_UNRECOGNIZED_VOLUME; - goto exit; - } - - FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); - if (FsvolDeviceExtension->DeletePending || - FsvolDeviceExtension->FsvrtDeviceObject != FsvrtDeviceObject) - { - Result = STATUS_UNRECOGNIZED_VOLUME; - goto exit; - } - - Vpb->DeviceObject = FsvolDeviceObject; - Vpb->SerialNumber = FsvolDeviceExtension->VolumeParams.SerialNumber; - - Irp->IoStatus.Information = 0; - Result = STATUS_SUCCESS; - - exit:; - } - finally - { - ExReleaseResourceLite(&DeviceExtension->Resource); + Result = STATUS_UNRECOGNIZED_VOLUME; + for (ULONG i = 0; DeviceObjectCount > i; i++) + if (FspDeviceRetain(DeviceObjects[i])) + { + if (FspFsvolDeviceExtensionKind == FspDeviceExtension(DeviceObjects[i])->Kind) + { + FsvolDeviceObject = DeviceObjects[i]; + FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + if (FsvolDeviceExtension->FsvrtDeviceObject == FsvrtDeviceObject && + !FsvolDeviceExtension->DeletePending) + { + Result = STATUS_SUCCESS; + break; + } + } + FspDeviceRelease(DeviceObjects[i]); + } + FspDeviceDeleteList(DeviceObjects, DeviceObjectCount); } + if (!NT_SUCCESS(Result)) + return Result; - return Result; -#else - return STATUS_INVALID_DEVICE_REQUEST; -#endif + /* our volume device object has been FspDeviceRetain'ed */ + ASSERT(0 != FsvolDeviceObject && 0 != FsvolDeviceExtension); + IoAcquireVpbSpinLock(&Irql); + Vpb->ReferenceCount++; + Vpb->DeviceObject = FsvolDeviceObject; + Vpb->SerialNumber = FsvolDeviceExtension->VolumeParams.SerialNumber; + IoReleaseVpbSpinLock(Irql); + + Irp->IoStatus.Information = 0; + return STATUS_SUCCESS; } VOID FspFsctlDeleteVolume( @@ -253,107 +245,99 @@ VOID FspFsctlDeleteVolume( /* performed during IRP_MJ_CLEANUP! */ PAGED_CODE(); -#if 0 + FSP_FSCTL_FILE_CONTEXT2 *FsContext2 = IrpSp->FileObject->FsContext2; PDEVICE_OBJECT FsvolDeviceObject = 0; - FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject); - ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE); - try + /* + * Check to see if we have a volume. There is no need to protect this + * access in FsContext2->FastMutex, because we are called during IRP_MJ_CLEANUP. + */ + FsvolDeviceObject = FsContext2->FsvolDeviceObject; + if (0 == FsvolDeviceObject) + return; + + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + + /* mark the volume device as pending delete */ + FsvolDeviceExtension->DeletePending = TRUE; + + /* stop the I/O queue */ + FspIoqStop(&FsvolDeviceExtension->Ioq); + + /* do we have a virtual disk device or a MUP handle? */ + if (0 != FsvolDeviceExtension->FsvrtDeviceObject) { - FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject); - if (0 != FsvolDeviceObject) - FspDeviceDeleteContext(DeviceObject, (UINT_PTR)IrpSp->FileObject, 0); - } - finally - { - ExReleaseResourceLite(&DeviceExtension->Resource); - } + PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject; + PVPB OldVpb; + KIRQL Irql; + BOOLEAN DeleteVpb = FALSE; + BOOLEAN DeleteDly = FALSE; + LARGE_INTEGER DelayTimeout; - if (0 != FsvolDeviceObject) - { - FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); - - /* mark the volume device as pending delete */ - FsvolDeviceExtension->DeletePending = TRUE; - - /* stop the I/O queue */ - FspIoqStop(&FsvolDeviceExtension->Ioq); - - /* do we have a virtual disk device or a MUP handle? */ - if (0 != FsvolDeviceExtension->FsvrtDeviceObject) - { - PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject; - PVPB OldVpb; - KIRQL Irql; - BOOLEAN DeleteVpb = FALSE; - BOOLEAN DeleteDelayed = FALSE; - LARGE_INTEGER DelayTimeout; - - /* swap the virtual disk device VPB with the preallocated one */ + /* swap the virtual disk device VPB with the preallocated one */ #pragma prefast(push) #pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb") - IoAcquireVpbSpinLock(&Irql); - OldVpb = FsvrtDeviceObject->Vpb; - if (0 != OldVpb) - { - FsvrtDeviceObject->Vpb = FsvolDeviceExtension->SwapVpb; - FsvrtDeviceObject->Vpb->Size = sizeof *FsvrtDeviceObject->Vpb; - FsvrtDeviceObject->Vpb->Type = IO_TYPE_VPB; - FsvrtDeviceObject->Vpb->Flags = FlagOn(OldVpb->Flags, VPB_REMOVE_PENDING); - FsvrtDeviceObject->Vpb->RealDevice = OldVpb->RealDevice; - FsvrtDeviceObject->Vpb->RealDevice->Vpb = FsvrtDeviceObject->Vpb; - DeleteVpb = 0 == OldVpb->ReferenceCount; - DeleteDelayed = !DeleteVpb; - if (DeleteDelayed) - { - /* keep VPB around for delayed delete */ - OldVpb->ReferenceCount++; - FsvolDeviceExtension->SwapVpb = OldVpb; - } - else - FsvolDeviceExtension->SwapVpb = 0; - } - IoReleaseVpbSpinLock(Irql); - if (DeleteDelayed) - /* keep volume device object around for delayed delete */ - FspDeviceRetain(FsvolDeviceObject); - else if (DeleteVpb) - /* no more references to the old VPB; delete now! */ - FspFreeExternal(OldVpb); + IoAcquireVpbSpinLock(&Irql); + OldVpb = FsvrtDeviceObject->Vpb; + if (0 != OldVpb) + { + FsvrtDeviceObject->Vpb = FsvolDeviceExtension->SwapVpb; + FsvrtDeviceObject->Vpb->Size = sizeof *FsvrtDeviceObject->Vpb; + FsvrtDeviceObject->Vpb->Type = IO_TYPE_VPB; + FsvrtDeviceObject->Vpb->Flags = FlagOn(OldVpb->Flags, VPB_REMOVE_PENDING); + FsvrtDeviceObject->Vpb->RealDevice = OldVpb->RealDevice; + FsvrtDeviceObject->Vpb->RealDevice->Vpb = FsvrtDeviceObject->Vpb; + DeleteVpb = 0 == OldVpb->ReferenceCount; + DeleteDly = 2 <= OldVpb->ReferenceCount; + } + IoReleaseVpbSpinLock(Irql); + if (DeleteVpb) + { + /* no more references to the old VPB; delete now! */ + FspFreeExternal(OldVpb); + FsvolDeviceExtension->SwapVpb = 0; + } + else if (!DeleteDly) + { + /* there is only the reference from IRP_MN_MOUNT_VOLUME */ + FspFreeExternal(OldVpb); + FsvolDeviceExtension->SwapVpb = 0; + FspDeviceRelease(FsvolDeviceObject); + } + else + /* keep VPB around for delayed delete */ + FsvolDeviceExtension->SwapVpb = OldVpb; #pragma prefast(pop) - /* release the virtual disk and volume device objects */ - FspDeviceRelease(FsvrtDeviceObject); - FspDeviceRelease(FsvolDeviceObject); + /* release the virtual disk and volume device objects */ + FspDeviceRelease(FsvrtDeviceObject); + FspDeviceRelease(FsvolDeviceObject); - /* are we doing delayed delete of VPB and volume device object? */ - if (DeleteDelayed) - { - DelayTimeout.QuadPart = 300/*ms*/ * -10000; - FspInitializeWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, - FspFsctlDeleteVolumeDelayed, FsvolDeviceObject); - FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout); - } - } - else if (0 != FsvolDeviceExtension->MupHandle) + /* are we doing delayed delete of VPB and volume device object? */ + if (DeleteDly) { - HANDLE MupHandle = FsvolDeviceExtension->MupHandle; - - FsRtlDeregisterUncProvider(MupHandle); - - /* release the volume device object */ - FspDeviceRelease(FsvolDeviceObject); + DelayTimeout.QuadPart = 300/*ms*/ * -10000; + FspInitializeWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, + FspFsctlDeleteVolumeDelayed, FsvolDeviceObject); + FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout); } } -#endif + else if (0 != FsvolDeviceExtension->MupHandle) + { + HANDLE MupHandle = FsvolDeviceExtension->MupHandle; + + FsRtlDeregisterUncProvider(MupHandle); + FsvolDeviceExtension->MupHandle = 0; + + /* release the volume device object */ + FspDeviceRelease(FsvolDeviceObject); + } } static VOID FspFsctlDeleteVolumeDelayed(PVOID Context) { PAGED_CODE(); -#if 0 - PDEVICE_OBJECT FsvolDeviceObject = Context; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); KIRQL Irql; @@ -377,7 +361,6 @@ static VOID FspFsctlDeleteVolumeDelayed(PVOID Context) DelayTimeout.QuadPart = 300/*ms*/ * -10000; FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout); } -#endif } static NTSTATUS FspFsctlTransact(