[CDFS]
authorThomas Faber <thomas.faber@reactos.org>
Sat, 9 Apr 2016 19:33:42 +0000 (19:33 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sat, 9 Apr 2016 19:33:42 +0000 (19:33 +0000)
- Implement file locking
CORE-10790 #resolve

svn path=/trunk/; revision=71130

reactos/drivers/filesystems/cdfs/cdfs.c
reactos/drivers/filesystems/cdfs/cdfs.h
reactos/drivers/filesystems/cdfs/cleanup.c
reactos/drivers/filesystems/cdfs/dispatch.c
reactos/drivers/filesystems/cdfs/fcb.c
reactos/drivers/filesystems/cdfs/rw.c

index 9f364fe..a5a6302 100644 (file)
@@ -96,6 +96,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
     DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = CdfsFsdDispatch;
     DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = CdfsFsdDispatch;
     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CdfsFsdDispatch;
+    DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = CdfsFsdDispatch;
 
     CdfsGlobalData->FastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
     CdfsGlobalData->FastIoDispatch.FastIoCheckIfPossible = CdfsFastIoCheckIfPossible;
index 77b5c7c..1785661 100644 (file)
@@ -220,6 +220,7 @@ typedef struct _FCB
 
   ERESOURCE  NameListResource;
   LIST_ENTRY ShortNameList;
+  FILE_LOCK FileLock;
 } FCB, *PFCB;
 
 
index 26cb0fb..fa0acd8 100644 (file)
 /* FUNCTIONS ****************************************************************/
 
 static NTSTATUS
-CdfsCleanupFile(PDEVICE_EXTENSION DeviceExt,
+CdfsCleanupFile(PCDFS_IRP_CONTEXT IrpContext,
                 PFILE_OBJECT FileObject)
                 /*
                 * FUNCTION: Cleans up after a file has been closed.
                 */
 {
+    PDEVICE_EXTENSION DeviceExt;
     PFCB Fcb;
 
     DPRINT("CdfsCleanupFile(DeviceExt %p, FileObject %p)\n",
         DeviceExt,
         FileObject);
 
+    DeviceExt = IrpContext->DeviceObject->DeviceExtension;
     Fcb = FileObject->FsContext;
     if (!Fcb)
     {
@@ -58,6 +60,15 @@ CdfsCleanupFile(PDEVICE_EXTENSION DeviceExt,
                        &(DeviceExt->NotifyList),
                        FileObject->FsContext2);
 
+   if (!CdfsFCBIsDirectory(Fcb) &&
+       FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
+    {
+        FsRtlFastUnlockAll(&Fcb->FileLock,
+                           FileObject,
+                           IoGetRequestorProcess(IrpContext->Irp),
+                           NULL);
+    }
+
     /* Uninitialize file cache if initialized for this file object. */
     if (FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->SharedCacheMap)
     {
@@ -99,7 +110,7 @@ CdfsCleanup(
     KeEnterCriticalRegion();
     ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource, TRUE);
 
-    Status = CdfsCleanupFile(DeviceExtension, FileObject);
+    Status = CdfsCleanupFile(IrpContext, FileObject);
 
     ExReleaseResourceLite(&DeviceExtension->DirResource);
     KeLeaveCriticalRegion();
index a850694..d8d1319 100644 (file)
@@ -53,6 +53,34 @@ CdfsQueueRequest(PCDFS_IRP_CONTEXT IrpContext)
     return STATUS_PENDING;
 }
 
+static
+NTSTATUS
+CdfsLockControl(
+    IN PCDFS_IRP_CONTEXT IrpContext)
+{
+    PFCB Fcb;
+    NTSTATUS Status;
+
+    DPRINT("CdfsLockControl(IrpContext %p)\n", IrpContext);
+
+    if (IrpContext->DeviceObject == CdfsGlobalData->DeviceObject)
+    {
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+
+    Fcb = IrpContext->FileObject->FsContext;
+    if (CdfsFCBIsDirectory(Fcb))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
+    Status = FsRtlProcessFileLock(&Fcb->FileLock,
+                                  IrpContext->Irp,
+                                  NULL);
+    return Status;
+}
+
 static
 NTSTATUS
 CdfsDispatch(PCDFS_IRP_CONTEXT IrpContext)
@@ -115,6 +143,10 @@ CdfsDispatch(PCDFS_IRP_CONTEXT IrpContext)
         case IRP_MJ_FILE_SYSTEM_CONTROL:
             Status = CdfsFileSystemControl(IrpContext);
             break;
+
+        case IRP_MJ_LOCK_CONTROL:
+            Status = CdfsLockControl(IrpContext);
+            break;
     }
 
     ASSERT((!(IrpContext->Flags & IRPCONTEXT_COMPLETE) && !(IrpContext->Flags & IRPCONTEXT_QUEUE)) ||
index 801ba8b..3dbb887 100644 (file)
@@ -97,6 +97,7 @@ CdfsCreateFCB(PCWSTR FileName)
     Fcb->RFCB.Resource = &Fcb->MainResource;
     Fcb->RFCB.IsFastIoPossible = FastIoIsNotPossible;
     InitializeListHead(&Fcb->ShortNameList);
+    FsRtlInitializeFileLock(&Fcb->FileLock, NULL, NULL);
 
     return(Fcb);
 }
@@ -107,6 +108,7 @@ CdfsDestroyFCB(PFCB Fcb)
 {
     PLIST_ENTRY Entry;
 
+    FsRtlUninitializeFileLock(&Fcb->FileLock);
     ExDeleteResourceLite(&Fcb->PagingIoResource);
     ExDeleteResourceLite(&Fcb->MainResource);
 
index af9d2b1..dc42903 100644 (file)
@@ -41,7 +41,7 @@
 /* FUNCTIONS ****************************************************************/
 
 static NTSTATUS
-CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
+CdfsReadFile(PCDFS_IRP_CONTEXT IrpContext,
              PFILE_OBJECT FileObject,
              PUCHAR Buffer,
              ULONG Length,
@@ -53,6 +53,7 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
              */
 {
     NTSTATUS Status = STATUS_SUCCESS;
+    PDEVICE_EXTENSION DeviceExt;
     PFCB Fcb;
     ULONG ToRead = Length;
 
@@ -63,6 +64,7 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
     if (Length == 0)
         return(STATUS_SUCCESS);
 
+    DeviceExt = IrpContext->DeviceObject->DeviceExtension;
     Fcb = (PFCB)FileObject->FsContext;
 
     if (ReadOffset >= Fcb->Entry.DataLengthL)
@@ -71,6 +73,15 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
     if (ReadOffset + Length > Fcb->Entry.DataLengthL)
         ToRead = Fcb->Entry.DataLengthL - ReadOffset;
 
+    if (!(IrpFlags & IRP_PAGING_IO) &&
+        FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
+    {
+        if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock, IrpContext->Irp))
+        {
+            return STATUS_FILE_LOCK_CONFLICT;
+        }
+    }
+
     DPRINT("Reading %u bytes at %u\n", Length, ReadOffset);
 
     if (!(IrpFlags & (IRP_NOCACHE|IRP_PAGING_IO)))
@@ -179,8 +190,6 @@ CdfsRead(
     PCDFS_IRP_CONTEXT IrpContext)
 {
     PIRP Irp;
-    PDEVICE_OBJECT DeviceObject;
-    PDEVICE_EXTENSION DeviceExt;
     PIO_STACK_LOCATION Stack;
     PFILE_OBJECT FileObject;
     PVOID Buffer = NULL;
@@ -194,17 +203,15 @@ CdfsRead(
     ASSERT(IrpContext);
 
     Irp = IrpContext->Irp;
-    DeviceObject = IrpContext->DeviceObject;
     Stack = IrpContext->Stack;
 
-    DeviceExt = DeviceObject->DeviceExtension;
     FileObject = Stack->FileObject;
 
     ReadLength = Stack->Parameters.Read.Length;
     ReadOffset = Stack->Parameters.Read.ByteOffset;
     if (ReadLength) Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
 
-    Status = CdfsReadFile(DeviceExt,
+    Status = CdfsReadFile(IrpContext,
         FileObject,
         Buffer,
         ReadLength,