Author: pschweitzer
Date: Mon Apr 28 19:40:26 2014
New Revision: 63034

URL: http://svn.reactos.org/svn/reactos?rev=63034&view=rev
Log:
[FASTFAT]
Implement part 2/3 (first part was in ntoskrnl, remember ;-)) of renaming 
support in ReactOS.

Here, we implement support for SL_OPEN_TARGET_DIRECTORY for IRP_MJ_CREATE in 
fastfat. The code is not the best ever, but we can't do miracles with fastfat.
This fixes a few tests in KmTests:IoCreateFile and also shows failures I still 
don't get and that will require deeper attention.

Last part will be to effectively bring support of FileRenameInformation in 
IRP_MJ_SET_INFORMATION. But this is yet another story.

Modified:
    trunk/reactos/drivers/filesystems/fastfat/create.c

Modified: trunk/reactos/drivers/filesystems/fastfat/create.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat/create.c?rev=63034&r1=63033&r2=63034&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat/create.c  [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat/create.c  [iso-8859-1] Mon Apr 28 
19:40:26 2014
@@ -352,6 +352,7 @@
     PUNICODE_STRING PathNameU,
     PFILE_OBJECT FileObject,
     ULONG RequestedDisposition,
+    BOOLEAN OpenTargetDir,
     PVFATFCB *ParentFcb)
 {
     PVFATFCB Fcb;
@@ -402,6 +403,14 @@
         DPRINT ("Could not make a new FCB, status: %x\n", Status);
         return  Status;
     }
+
+    /* In case we're to open target, just check whether file exist, but don't 
open it */
+    if (OpenTargetDir)
+    {
+        vfatReleaseFCB(DeviceExt, Fcb);
+        return STATUS_OBJECT_NAME_COLLISION;
+    }
+
     if (Fcb->Flags & FCB_DELETE_PENDING)
     {
         vfatReleaseFCB(DeviceExt, Fcb);
@@ -443,6 +452,7 @@
     PWCHAR c, last;
     BOOLEAN PagingFileCreate = FALSE;
     BOOLEAN Dots;
+    BOOLEAN OpenTargetDir = FALSE;
     UNICODE_STRING FileNameU;
     UNICODE_STRING PathNameU;
     ULONG Attributes;
@@ -452,6 +462,7 @@
     RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
     RequestedOptions = Stack->Parameters.Create.Options & 
FILE_VALID_OPTION_FLAGS;
     PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
+    OpenTargetDir = (Stack->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE;
     FileObject = Stack->FileObject;
     DeviceExt = DeviceObject->DeviceExtension;
 
@@ -484,6 +495,11 @@
             return STATUS_NOT_A_DIRECTORY;
         }
 #endif
+
+        if (OpenTargetDir)
+        {
+            return STATUS_INVALID_PARAMETER;
+        }
 
         pFcb = DeviceExt->VolumeFcb;
         vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
@@ -520,6 +536,13 @@
         }
     }
 
+    /* Check if we try to open target directory of root dir */
+    if (OpenTargetDir && FileObject->RelatedFileObject == NULL && 
PathNameU.Length == sizeof(WCHAR) &&
+        PathNameU.Buffer[0] == L'\\')
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
     if (FileObject->RelatedFileObject && PathNameU.Length >= sizeof(WCHAR) && 
PathNameU.Buffer[0] == L'\\')
     {
         return STATUS_OBJECT_NAME_INVALID;
@@ -531,7 +554,86 @@
     }
 
     /* Try opening the file. */
-    Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, 
RequestedDisposition, &ParentFcb);
+    Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, 
RequestedDisposition, OpenTargetDir, &ParentFcb);
+
+    if (OpenTargetDir)
+    {
+        LONG idx, FileNameLen;
+
+        if (Status == STATUS_OBJECT_NAME_COLLISION)
+        {
+            Irp->IoStatus.Information = FILE_EXISTS;
+        }
+        else
+        {
+            Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
+        }
+
+        idx = FileObject->FileName.Length / sizeof(WCHAR) - 1;
+
+        /* Skip tailing \ - if any */
+        if (PathNameU.Buffer[idx] == L'\\')
+        {
+            --idx;
+            PathNameU.Length -= sizeof(WCHAR);
+        }
+
+        /* Get file name */
+        while (idx >= 0 && PathNameU.Buffer[idx] != L'\\')
+        {
+            --idx;
+        }
+
+        if (idx > 0)
+        {
+            /* We don't want to include / in the name */
+            FileNameLen = PathNameU.Length - ((idx + 1) * sizeof(WCHAR));
+
+            /* Try to open parent */
+            PathNameU.Length -= (PathNameU.Length - idx * sizeof(WCHAR));
+            Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, 
RequestedDisposition, FALSE, &ParentFcb);
+
+            /* Update FO just to keep file name */
+            /* Skip first slash */
+            ++idx;
+            PathNameU.Length = FileNameLen;
+            RtlMoveMemory(&PathNameU.Buffer[0], &PathNameU.Buffer[idx], 
PathNameU.Length);
+        }
+        else
+        {
+            /* This is a relative open and we have only the filename, so open 
the parent directory
+             * It is in RelatedFileObject
+             */
+            BOOLEAN Chomp = FALSE;
+            PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
+
+            DPRINT("%wZ\n", &PathNameU);
+
+            ASSERT(RelatedFileObject != NULL);
+
+            DPRINT("Relative opening\n");
+            DPRINT("FileObject->RelatedFileObject->FileName: %wZ\n", 
&RelatedFileObject->FileName);
+
+            /* VfatOpenFile() doesn't like our name ends with \, so chomp it 
if there's one */
+            if 
(RelatedFileObject->FileName.Buffer[RelatedFileObject->FileName.Length / 
sizeof(WCHAR) - 1] == L'\\')
+            {
+                Chomp = FALSE;
+                RelatedFileObject->FileName.Length -= sizeof(WCHAR);
+            }
+
+            /* Tricky part - fake our FO. It's NOT relative, we want to open 
the complete file path */
+            FileObject->RelatedFileObject = NULL;
+            Status = VfatOpenFile(DeviceExt, &RelatedFileObject->FileName, 
FileObject, RequestedDisposition, FALSE, &ParentFcb);
+
+            /* We're done opening, restore what we broke */
+            FileObject->RelatedFileObject = RelatedFileObject;
+            if (Chomp) RelatedFileObject->FileName.Length += sizeof(WCHAR);
+
+            /* No need to modify the FO, it already has the name */
+        }
+
+        return Status;
+    }
 
     /*
      * If the directory containing the file to open doesn't exist then


Reply via email to