[NTFS]
authorPierre Schweitzer <pierre@reactos.org>
Sun, 31 May 2015 21:28:52 +0000 (21:28 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Sun, 31 May 2015 21:28:52 +0000 (21:28 +0000)
Directly implement NtfsOpenFileById() for special files from the MFT where we cannot moonwalk there path.
It concerns any file with ID < 0x10.
This function can only cope with file which ID is < 0xc. Windows Internals reports that 0xc - 0xf entries are unused.

It would be interesting to double check returrned status in case of error, and also what Windows returns when attempting weird opening of suchs entries (overwrite, create for unused, etc).

svn path=/trunk/; revision=67983

reactos/drivers/filesystems/ntfs/create.c
reactos/drivers/filesystems/ntfs/ntfs.h

index a71c507..4d2c9fc 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+static PCWSTR MftIdToName[] = {
+    L"$MFT",
+    L"$MFTMirr",
+    L"$LogFile",
+    L"$Volume",
+    L"AttrDef",
+    L".",
+    L"$Bitmap",
+    L"$Boot",
+    L"$BadClus",
+    L"$Quota",
+    L"$UpCase",
+    L"$Extended",
+};
+
 /* FUNCTIONS ****************************************************************/
 
 static
@@ -157,6 +172,72 @@ NtfsMoonWalkID(PDEVICE_EXTENSION DeviceExt,
     return Status;
 }
 
+static
+NTSTATUS
+NtfsOpenFileById(PDEVICE_EXTENSION DeviceExt,
+                 PFILE_OBJECT FileObject,
+                 ULONGLONG MftId,
+                 PNTFS_FCB * FoundFCB)
+{
+    NTSTATUS Status;
+    PNTFS_FCB FCB;
+    PFILE_RECORD_HEADER MftRecord;
+
+    DPRINT1("NtfsOpenFileById(%p, %p, %I64x, %p)\n", DeviceExt, FileObject, MftId, FoundFCB);
+
+    ASSERT(MftId < 0x10);
+    if (MftId > 0xb) /* No entries are used yet beyond this */
+    {
+        return STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+
+    MftRecord = ExAllocatePoolWithTag(NonPagedPool,
+                                      DeviceExt->NtfsInfo.BytesPerFileRecord,
+                                      TAG_NTFS);
+    if (MftRecord == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    Status = ReadFileRecord(DeviceExt, MftId, MftRecord);
+    if (!NT_SUCCESS(Status))
+    {
+        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        return Status;
+    }
+
+    if (!(MftRecord->Flags & FRH_IN_USE))
+    {
+        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        return STATUS_OBJECT_PATH_NOT_FOUND;
+    }
+
+    FCB = NtfsGrabFCBFromTable(DeviceExt, MftIdToName[MftId]);
+    if (FCB == NULL)
+    {
+        UNICODE_STRING Name;
+
+        RtlInitUnicodeString(&Name, MftIdToName[MftId]);
+        Status = NtfsMakeFCBFromDirEntry(DeviceExt, NULL, &Name, MftRecord, MftId, &FCB);
+        if (!NT_SUCCESS(Status))
+        {
+            ExFreePoolWithTag(MftRecord, TAG_NTFS);
+            return Status;
+        }
+    }
+
+    ASSERT(FCB != NULL);
+
+    ExFreePoolWithTag(MftRecord, TAG_NTFS);
+
+    Status = NtfsAttachFCBToFileObject(DeviceExt,
+                                       FCB,
+                                       FileObject);
+    *FoundFCB = FCB;
+
+    return Status;
+}
+
 /*
  * FUNCTION: Opens a file
  */
@@ -249,7 +330,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
     PFILE_OBJECT FileObject;
     ULONG RequestedDisposition;
     ULONG RequestedOptions;
-    PNTFS_FCB Fcb;
+    PNTFS_FCB Fcb = NULL;
 //    PWSTR FileName;
     NTSTATUS Status;
     UNICODE_STRING FullPath;
@@ -287,13 +368,15 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
             return STATUS_INVALID_PARAMETER;
 
         MFTId = (*(PULONGLONG)FileObject->FileName.Buffer) & NTFS_MFT_MASK;
-        if (MFTId < 0xf)
+        if (MFTId < 0x10)
         {
-            UNIMPLEMENTED;
-            return STATUS_NOT_IMPLEMENTED;
+            Status = NtfsOpenFileById(DeviceExt, FileObject, MFTId, &Fcb);
+        }
+        else
+        {
+            Status = NtfsMoonWalkID(DeviceExt, MFTId, &FullPath);
         }
 
-        Status = NtfsMoonWalkID(DeviceExt, MFTId, &FullPath);
         if (!NT_SUCCESS(Status))
         {
             return Status;
@@ -324,14 +407,17 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
         return STATUS_SUCCESS;
     }
 
-    Status = NtfsOpenFile(DeviceExt,
-                          FileObject,
-                          ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
-                          &Fcb);
-
-    if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
+    if (Fcb == NULL)
     {
-        ExFreePoolWithTag(FullPath.Buffer, TAG_NTFS);
+        Status = NtfsOpenFile(DeviceExt,
+                              FileObject,
+                              ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
+                              &Fcb);
+
+        if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
+        {
+            ExFreePoolWithTag(FullPath.Buffer, TAG_NTFS);
+        }
     }
 
     if (NT_SUCCESS(Status))
index a18fbdc..1da9e07 100644 (file)
@@ -643,6 +643,14 @@ NtfsReadFCBAttribute(PNTFS_VCB Vcb,
                      ULONG NameLength,
                      PVOID * Data);
 
+NTSTATUS
+NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,
+                        PNTFS_FCB DirectoryFCB,
+                        PUNICODE_STRING Name,
+                        PFILE_RECORD_HEADER Record,
+                        ULONGLONG MFTIndex,
+                        PNTFS_FCB * fileFCB);
+
 
 /* finfo.c */