From ab38eafc212cccdbc9be31aded00894f3b56ae0b Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Thu, 30 Oct 2014 20:56:40 +0000 Subject: [PATCH] [FASTFAT] On the road for getting rid of IopParseDevice() hack.... - Add support for FSCTL_LOCK_VOLUME, FSCTL_UNLOCK_VOLUME, FSCTL_DISMOUNT_VOLUME in VfatFileSystemControl() - Implement VfatLockOrUnlockVolume(). This brings some kind of volume locking to FastFAT FSD. It's likely not fully accurate and welcome to race conditions. But, its main purpose is to be used in usetup. So, this is fine for now. - Stubplement VfatDismountVolume(). This will be implemented later on, but should be relatively straightforward as it requires volume to be locked (so, we're the last ones on it :-)). svn path=/trunk/; revision=65129 --- reactos/drivers/filesystems/fastfat/cleanup.c | 3 + reactos/drivers/filesystems/fastfat/create.c | 11 +++ reactos/drivers/filesystems/fastfat/fsctl.c | 80 +++++++++++++++++++ reactos/drivers/filesystems/fastfat/vfat.h | 3 + 4 files changed, 97 insertions(+) diff --git a/reactos/drivers/filesystems/fastfat/cleanup.c b/reactos/drivers/filesystems/fastfat/cleanup.c index 97c2515116e..f9bde77d206 100644 --- a/reactos/drivers/filesystems/fastfat/cleanup.c +++ b/reactos/drivers/filesystems/fastfat/cleanup.c @@ -24,6 +24,7 @@ VfatCleanupFile( PVFAT_IRP_CONTEXT IrpContext) { PVFATFCB pFcb; + PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt; PFILE_OBJECT FileObject = IrpContext->FileObject; DPRINT("VfatCleanupFile(DeviceExt %p, FileObject %p)\n", @@ -37,6 +38,7 @@ VfatCleanupFile( if (pFcb->Flags & FCB_IS_VOLUME) { pFcb->OpenHandleCount--; + DeviceExt->OpenHandleCount--; if (pFcb->OpenHandleCount != 0) { @@ -63,6 +65,7 @@ VfatCleanupFile( FileObject->FsContext2); pFcb->OpenHandleCount--; + DeviceExt->OpenHandleCount--; if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) && FsRtlAreThereCurrentFileLocks(&pFcb->FileLock)) diff --git a/reactos/drivers/filesystems/fastfat/create.c b/reactos/drivers/filesystems/fastfat/create.c index bccbdb77183..6314c52ae3c 100644 --- a/reactos/drivers/filesystems/fastfat/create.c +++ b/reactos/drivers/filesystems/fastfat/create.c @@ -473,10 +473,18 @@ VfatCreateFile( return STATUS_INVALID_PARAMETER; } + /* Deny create if the volume is locked */ + if (DeviceExt->Flags & VCB_VOLUME_LOCKED) + { + return STATUS_ACCESS_DENIED; + } + /* This a open operation for the volume itself */ if (FileObject->FileName.Length == 0 && (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL)) { + DPRINT1("Volume opening\n"); + if (RequestedDisposition != FILE_OPEN && RequestedDisposition != FILE_OPEN_IF) { @@ -497,6 +505,7 @@ VfatCreateFile( pFcb = DeviceExt->VolumeFcb; vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject); + DeviceExt->OpenHandleCount++; Irp->IoStatus.Information = FILE_OPENED; return STATUS_SUCCESS; @@ -639,6 +648,7 @@ VfatCreateFile( } pFcb->OpenHandleCount++; + DeviceExt->OpenHandleCount++; } else if (ParentFcb != NULL) { @@ -884,6 +894,7 @@ VfatCreateFile( } pFcb->OpenHandleCount++; + DeviceExt->OpenHandleCount++; /* FIXME : test write access if requested */ diff --git a/reactos/drivers/filesystems/fastfat/fsctl.c b/reactos/drivers/filesystems/fastfat/fsctl.c index e0a1608600c..19f97854ea8 100644 --- a/reactos/drivers/filesystems/fastfat/fsctl.c +++ b/reactos/drivers/filesystems/fastfat/fsctl.c @@ -612,6 +612,8 @@ VfatMount( FsRtlNotifyInitializeSync(&DeviceExt->NotifySync); InitializeListHead(&DeviceExt->NotifyList); + DPRINT1("Mount success\n"); + Status = STATUS_SUCCESS; ByeBye: @@ -855,6 +857,72 @@ VfatMarkVolumeDirty( return Status; } +static +NTSTATUS +VfatLockOrUnlockVolume( + PVFAT_IRP_CONTEXT IrpContext, + BOOLEAN Lock) +{ + PFILE_OBJECT FileObject; + PDEVICE_EXTENSION DeviceExt; + + DPRINT1("VfatLockOrUnlockVolume(%p, %d)\n", IrpContext, Lock); + + DeviceExt = IrpContext->DeviceExt; + FileObject = IrpContext->FileObject; + + /* Only allow locking with the volume open */ + if (FileObject->FsContext != DeviceExt->VolumeFcb) + { + return STATUS_ACCESS_DENIED; + } + + /* Bail out if it's already in the demanded state */ + if (((DeviceExt->Flags & VCB_VOLUME_LOCKED) && Lock) || + (!(DeviceExt->Flags & VCB_VOLUME_LOCKED) && !Lock)) + { + return STATUS_ACCESS_DENIED; + } + + /* Deny locking if we're not alone */ + if (Lock && DeviceExt->OpenHandleCount != 1) + { + return STATUS_ACCESS_DENIED; + } + + /* Finally, proceed */ + if (Lock) + { + DeviceExt->Flags |= VCB_VOLUME_LOCKED; + } + else + { + DeviceExt->Flags &= ~VCB_VOLUME_LOCKED; + } + + return STATUS_SUCCESS; +} + +static +NTSTATUS +VfatDismountVolume( + PVFAT_IRP_CONTEXT IrpContext) +{ + PDEVICE_EXTENSION DeviceExt; + + DPRINT1("VfatDismountVolume(%p)\n", IrpContext); + + DeviceExt = IrpContext->DeviceExt; + + if (!(DeviceExt->Flags & VCB_VOLUME_LOCKED)) + { + return STATUS_ACCESS_DENIED; + } + + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + /* * FUNCTION: File system control */ @@ -898,6 +966,18 @@ VfatFileSystemControl( Status = VfatMarkVolumeDirty(IrpContext); break; + case FSCTL_LOCK_VOLUME: + Status = VfatLockOrUnlockVolume(IrpContext, TRUE); + break; + + case FSCTL_UNLOCK_VOLUME: + Status = VfatLockOrUnlockVolume(IrpContext, FALSE); + break; + + case FSCTL_DISMOUNT_VOLUME: + Status = VfatDismountVolume(IrpContext); + break; + default: Status = STATUS_INVALID_DEVICE_REQUEST; } diff --git a/reactos/drivers/filesystems/fastfat/vfat.h b/reactos/drivers/filesystems/fastfat/vfat.h index 416fa74c9fa..c35b73540b6 100644 --- a/reactos/drivers/filesystems/fastfat/vfat.h +++ b/reactos/drivers/filesystems/fastfat/vfat.h @@ -296,6 +296,9 @@ typedef struct DEVICE_EXTENSION /* Notifications */ LIST_ENTRY NotifyList; PNOTIFY_SYNC NotifySync; + + /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */ + ULONG OpenHandleCount; } DEVICE_EXTENSION, VCB, *PVCB; typedef struct