[NTFS] - In the NtfsAddFilenameToDirectory() function, rename DirectoryContext parame...
[reactos.git] / drivers / filesystems / ntfs / create.c
index 6513827..f52cd7d 100644 (file)
@@ -246,6 +246,7 @@ NTSTATUS
 NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
              PFILE_OBJECT FileObject,
              PWSTR FileName,
+             BOOLEAN CaseSensitive,
              PNTFS_FCB * FoundFCB)
 {
     PNTFS_FCB ParentFcb;
@@ -253,7 +254,12 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
     NTSTATUS Status;
     PWSTR AbsFileName = NULL;
 
-    DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName, FoundFCB);
+    DPRINT1("NtfsOpenFile(%p, %p, %S, %s, %p)\n",
+            DeviceExt,
+            FileObject,
+            FileName,
+            CaseSensitive ? "TRUE" : "FALSE",
+            FoundFCB);
 
     *FoundFCB = NULL;
 
@@ -285,7 +291,8 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
         Status = NtfsGetFCBForFile(DeviceExt,
                                    &ParentFcb,
                                    &Fcb,
-                                   FileName);
+                                   FileName,
+                                   CaseSensitive);
         if (ParentFcb != NULL)
         {
             NtfsReleaseFCB(DeviceExt,
@@ -323,7 +330,7 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
 static
 NTSTATUS
 NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
-               PIRP Irp)
+               PNTFS_IRP_CONTEXT IrpContext)
 {
     PDEVICE_EXTENSION DeviceExt;
     PIO_STACK_LOCATION Stack;
@@ -334,8 +341,9 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
 //    PWSTR FileName;
     NTSTATUS Status;
     UNICODE_STRING FullPath;
+    PIRP Irp = IrpContext->Irp;
 
-    DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp);
+    DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, IrpContext);
 
     DeviceExt = DeviceObject->DeviceExtension;
     ASSERT(DeviceExt);
@@ -411,6 +419,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
         Status = NtfsOpenFile(DeviceExt,
                               FileObject,
                               ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
+                              (Stack->Flags & SL_CASE_SENSITIVE),
                               &Fcb);
 
         if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
@@ -523,7 +532,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
            
         DoneOverwriting:
             if (fileRecord)
-                ExFreePool(fileRecord);
+                ExFreePoolWithTag(fileRecord, TAG_NTFS);
             if (dataContext)
                 ReleaseAttributeContext(dataContext);
 
@@ -561,14 +570,18 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
             }
 
             // Create the file record on disk
-            Status = NtfsCreateFileRecord(DeviceExt, FileObject);
-
-            // Update the parent directory index
-            // Still TODO
-
-            // Call NtfsOpenFile()
+            Status = NtfsCreateFileRecord(DeviceExt,
+                                          FileObject,
+                                          (Stack->Flags & SL_CASE_SENSITIVE),
+                                          BooleanFlagOn(IrpContext->Flags,IRPCONTEXT_CANWAIT));
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("ERROR: Couldn't create file record!\n");
+                return Status;
+            }
 
-            return STATUS_CANNOT_MAKE;
+            // Now we should be able to open the file
+            return NtfsCreateFile(DeviceObject, IrpContext);
         }
     }
 
@@ -614,7 +627,7 @@ NtfsCreate(PNTFS_IRP_CONTEXT IrpContext)
     ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
                                    TRUE);
     Status = NtfsCreateFile(DeviceObject,
-                            IrpContext->Irp);
+                            IrpContext);
     ExReleaseResourceLite(&DeviceExt->DirResource);
 
     return Status;
@@ -624,7 +637,8 @@ NtfsCreate(PNTFS_IRP_CONTEXT IrpContext)
 * @name NtfsCreateFileRecord()
 * @implemented
 *
-* Creates a file record and saves it to the MFT.
+* Creates a file record and saves it to the MFT. Adds the filename attribute of the
+* created file to the parent directory's index.
 *
 * @param DeviceExt
 * Points to the target disk's DEVICE_EXTENSION
@@ -632,17 +646,34 @@ NtfsCreate(PNTFS_IRP_CONTEXT IrpContext)
 * @param FileObject
 * Pointer to a FILE_OBJECT describing the file to be created
 *
+* @param CanWait
+* Boolean indicating if the function is allowed to wait for exclusive access to the master file table.
+* This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
+* 
 * @return
 * STATUS_SUCCESS on success. 
 * STATUS_INSUFFICIENT_RESOURCES if unable to allocate memory for the file record.
+* STATUS_CANT_WAIT if CanWait was FALSE and the function needed to resize the MFT but 
+* couldn't get immediate, exclusive access to it.
 */
 NTSTATUS
 NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
-                     PFILE_OBJECT FileObject)
+                     PFILE_OBJECT FileObject,
+                     BOOLEAN CaseSensitive,
+                     BOOLEAN CanWait)
 {
     NTSTATUS Status = STATUS_SUCCESS;
     PFILE_RECORD_HEADER FileRecord;
     PNTFS_ATTR_RECORD NextAttribute;
+    PFILENAME_ATTRIBUTE FilenameAttribute;
+    ULONGLONG ParentMftIndex;
+    ULONGLONG FileMftIndex;
+
+    DPRINT1("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
+            DeviceExt,
+            FileObject,
+            CaseSensitive ? "TRUE" : "FALSE",
+            CanWait ? "TRUE" : "FALSE");
 
     // allocate memory for file record
     FileRecord = ExAllocatePoolWithTag(NonPagedPool,
@@ -686,7 +717,10 @@ NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
     NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
 
     // Add the $FILE_NAME attribute
-    AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject);
+    AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject, CaseSensitive, &ParentMftIndex);
+
+    // save a pointer to the filename attribute
+    FilenameAttribute = (PFILENAME_ATTRIBUTE)((ULONG_PTR)NextAttribute + NextAttribute->Resident.ValueOffset);
 
     // advance NextAttribute pointer to the next attribute
     NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
@@ -698,7 +732,23 @@ NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
     NtfsDumpFileRecord(DeviceExt, FileRecord);
 
     // Now that we've built the file record in memory, we need to store it in the MFT.
-    Status = AddNewMftEntry(FileRecord, DeviceExt);
+    Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
+    if (NT_SUCCESS(Status))
+    {
+        // The highest 2 bytes should be the sequence number, unless the parent happens to be root
+        if (FileMftIndex == NTFS_FILE_ROOT)
+            FileMftIndex = FileMftIndex + ((ULONGLONG)NTFS_FILE_ROOT << 48);
+        else
+            FileMftIndex = FileMftIndex + ((ULONGLONG)FileRecord->SequenceNumber << 48);
+
+        DPRINT1("New File Reference: 0x%016I64x\n", FileMftIndex);
+
+        // Add the filename attribute to the filename-index of the parent directory
+        Status = NtfsAddFilenameToDirectory(DeviceExt,
+                                            ParentMftIndex,
+                                            FileMftIndex,
+                                            FilenameAttribute);
+    }
 
     ExFreePoolWithTag(FileRecord, TAG_NTFS);