[NTFS]
authorPierre Schweitzer <pierre@reactos.org>
Sat, 14 Feb 2015 15:35:35 +0000 (15:35 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 14 Feb 2015 15:35:35 +0000 (15:35 +0000)
Simplify the implementation of the "Open by ID" feature of our driver.
Instead of creating singleton FCB not linked to the rest of FS tree, just walk the whole path down, to recreate it.

This doesn't make nfi work properly though. Will investigate more.

CORE-8725

svn path=/trunk/; revision=66264

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

index ac9920e..70b3ba2 100644 (file)
@@ -46,6 +46,18 @@ NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject,
     Fcb = pFileObject->FsContext;
     ASSERT(Fcb);
 
+    if (Fcb->Flags & FCB_IS_VOLUME)
+    {
+        /* This is likely to be an opening by ID, return ourselves */
+        if (pRelativeFileName[0] == L'\\')
+        {
+            *pAbsoluteFilename = NULL;
+            return STATUS_SUCCESS;
+        }
+
+        return STATUS_INVALID_PARAMETER;
+    }
+
     /* verify related object is a directory and target name
        don't start with \. */
     if (NtfsFCBIsDirectory(Fcb) == FALSE ||
@@ -72,6 +84,66 @@ NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject,
 }
 
 
+static
+NTSTATUS
+NtfsMoonWalkID(PDEVICE_EXTENSION DeviceExt,
+               ULONGLONG Id,
+               PUNICODE_STRING OutPath)
+{
+    NTSTATUS Status;
+    PFILE_RECORD_HEADER MftRecord;
+    PFILENAME_ATTRIBUTE FileName;
+    WCHAR FullPath[MAX_PATH];
+    ULONG WritePosition = MAX_PATH - 1;
+
+    DPRINT1("NtfsMoonWalkID(%p, %I64x, %p)\n", DeviceExt, Id, OutPath);
+
+    Id = Id & NTFS_MFT_MASK;
+
+    RtlZeroMemory(FullPath, sizeof(FullPath));
+    MftRecord = ExAllocatePoolWithTag(NonPagedPool,
+                                      DeviceExt->NtfsInfo.BytesPerFileRecord,
+                                      TAG_NTFS);
+    if (MftRecord == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    while (TRUE)
+    {
+        Status = ReadFileRecord(DeviceExt, Id, MftRecord);
+        if (!NT_SUCCESS(Status))
+            break;
+
+        ASSERT(MftRecord->Ntfs.Type == NRH_FILE_TYPE);
+
+        FileName = GetBestFileNameFromRecord(MftRecord);
+        WritePosition -= FileName->NameLength;
+        ASSERT(WritePosition < MAX_PATH);
+        RtlCopyMemory(FullPath + WritePosition, FileName->Name, FileName->NameLength * sizeof(WCHAR));
+        WritePosition -= 1;
+        ASSERT(WritePosition < MAX_PATH);
+        FullPath[WritePosition] = L'\\';
+
+        Id = FileName->DirectoryFileReferenceNumber & NTFS_MFT_MASK;
+        if (Id == NTFS_FILE_ROOT)
+            break;
+    }
+
+    ExFreePoolWithTag(MftRecord, TAG_NTFS);
+
+    OutPath->Length = (MAX_PATH - WritePosition - 1) * sizeof(WCHAR);
+    OutPath->MaximumLength = (MAX_PATH - WritePosition) * sizeof(WCHAR);
+    OutPath->Buffer = ExAllocatePoolWithTag(NonPagedPool, OutPath->MaximumLength, TAG_NTFS);
+    if (OutPath->Buffer == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    RtlCopyMemory(OutPath->Buffer, FullPath + WritePosition, OutPath->MaximumLength);
+
+    return Status;
+}
+
 /*
  * FUNCTION: Opens a file
  */
@@ -80,7 +152,6 @@ NTSTATUS
 NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
              PFILE_OBJECT FileObject,
              PWSTR FileName,
-             BOOLEAN OpenById,
              PNTFS_FCB * FoundFCB)
 {
     PNTFS_FCB ParentFcb;
@@ -88,81 +159,53 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
     NTSTATUS Status;
     PWSTR AbsFileName = NULL;
 
-    DPRINT1("NtfsOpenFile(%p, %p, %S, %u, %p)\n", DeviceExt, FileObject, (!OpenById ? FileName : NULL), OpenById, FoundFCB);
+    DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName, FoundFCB);
 
     *FoundFCB = NULL;
 
-    if (OpenById)
+    if (FileObject->RelatedFileObject)
     {
-        ULONGLONG Id = (*(PULONGLONG)FileName) & NTFS_MFT_MASK;
+        DPRINT("Converting relative filename to absolute filename\n");
 
-        DPRINT1("Will attempt to open by id: %I64x\n", Id);
-
-        Fcb = NtfsGrabFCBFromTableById(DeviceExt,
-                                       Id);
-        if (Fcb == NULL)
+        Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
+                                          FileName,
+                                          &AbsFileName);
+        if (AbsFileName) FileName = AbsFileName;
+        if (!NT_SUCCESS(Status))
         {
-            Status = NtfsGetFCBForFileById(DeviceExt,
-                                           &Fcb,
-                                           Id);
-            if (!NT_SUCCESS (Status))
-            {
-                DPRINT("Could not make a new FCB, status: %x\n", Status);
-
-                return Status;
-            }
-
-            Fcb->Flags |= FCB_IS_OPEN_BY_ID;
+            return Status;
         }
     }
-    else
-    {
-        if (FileObject->RelatedFileObject)
-        {
-            DPRINT("Converting relative filename to absolute filename\n");
-
-            Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
-                                              FileName,
-                                              &AbsFileName);
-            FileName = AbsFileName;
-            if (!NT_SUCCESS(Status))
-            {
-                return Status;
-            }
 
-            return STATUS_UNSUCCESSFUL;
-        }
-
-        //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
+    //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
 
-        DPRINT("PathName to open: %S\n", FileName);
+    DPRINT("PathName to open: %S\n", FileName);
 
-        /*  try first to find an existing FCB in memory  */
-        DPRINT("Checking for existing FCB in memory\n");
-        Fcb = NtfsGrabFCBFromTable(DeviceExt,
+    /*  try first to find an existing FCB in memory  */
+    DPRINT("Checking for existing FCB in memory\n");
+    Fcb = NtfsGrabFCBFromTable(DeviceExt,
+                               FileName);
+    if (Fcb == NULL)
+    {
+        DPRINT("No existing FCB found, making a new one if file exists.\n");
+        Status = NtfsGetFCBForFile(DeviceExt,
+                                   &ParentFcb,
+                                   &Fcb,
                                    FileName);
-        if (Fcb == NULL)
+        if (ParentFcb != NULL)
         {
-            DPRINT("No existing FCB found, making a new one if file exists.\n");
-            Status = NtfsGetFCBForFile(DeviceExt,
-                                       &ParentFcb,
-                                       &Fcb,
-                                       FileName);
-            if (ParentFcb != NULL)
-            {
-                NtfsReleaseFCB(DeviceExt,
-                               ParentFcb);
-            }
+            NtfsReleaseFCB(DeviceExt,
+                           ParentFcb);
+        }
 
-            if (!NT_SUCCESS (Status))
-            {
-                DPRINT("Could not make a new FCB, status: %x\n", Status);
+        if (!NT_SUCCESS (Status))
+        {
+            DPRINT("Could not make a new FCB, status: %x\n", Status);
 
-                if (AbsFileName)
-                    ExFreePool(AbsFileName);
+            if (AbsFileName)
+                ExFreePool(AbsFileName);
 
-                return Status;
-            }
+            return Status;
         }
     }
 
@@ -196,6 +239,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
     PNTFS_FCB Fcb;
 //    PWSTR FileName;
     NTSTATUS Status;
+    UNICODE_STRING FullPath;
 
     DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp);
 
@@ -213,12 +257,6 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
         return STATUS_INVALID_PARAMETER;
     }
 
-    if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
-    {
-        UNIMPLEMENTED;
-        return STATUS_NOT_IMPLEMENTED;
-    }
-
     FileObject = Stack->FileObject;
 
     if (RequestedDisposition == FILE_CREATE ||
@@ -228,10 +266,18 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
         return STATUS_ACCESS_DENIED;
     }
 
-    if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID &&
-        FileObject->FileName.Length != sizeof(ULONGLONG))
+    if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID)
     {
-        return STATUS_INVALID_PARAMETER;
+        if (FileObject->FileName.Length != sizeof(ULONGLONG))
+            return STATUS_INVALID_PARAMETER;
+
+        Status = NtfsMoonWalkID(DeviceExt, (*(PULONGLONG)FileObject->FileName.Buffer), &FullPath);
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+
+        DPRINT1("Open by ID: %I64x -> %wZ\n", (*(PULONGLONG)FileObject->FileName.Buffer) & NTFS_MFT_MASK, &FullPath);
     }
 
     /* This a open operation for the volume itself */
@@ -258,10 +304,14 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
 
     Status = NtfsOpenFile(DeviceExt,
                           FileObject,
-                          FileObject->FileName.Buffer,
-                          ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID),
+                          ((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))
     {
         if (RequestedDisposition == FILE_CREATE)
index f510157..337aa97 100644 (file)
@@ -220,8 +220,7 @@ NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
         Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
 
         DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
-        if ((Fcb->Flags & FCB_IS_OPEN_BY_ID) != FCB_IS_OPEN_BY_ID &&
-            _wcsicmp(FileName, Fcb->PathName) == 0)
+        if (_wcsicmp(FileName, Fcb->PathName) == 0)
         {
             Fcb->RefCount++;
             KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
@@ -239,38 +238,6 @@ NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
 }
 
 
-PNTFS_FCB
-NtfsGrabFCBFromTableById(PNTFS_VCB Vcb,
-                         ULONGLONG Id)
-{
-    KIRQL oldIrql;
-    PNTFS_FCB Fcb;
-    PLIST_ENTRY current_entry;
-
-    KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
-
-    current_entry = Vcb->FcbListHead.Flink;
-    while (current_entry != &Vcb->FcbListHead)
-    {
-        Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
-
-        if ((Fcb->Flags & FCB_IS_OPEN_BY_ID) == FCB_IS_OPEN_BY_ID &&
-            Fcb->MFTIndex == Id)
-        {
-            Fcb->RefCount++;
-            KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
-            return Fcb;
-        }
-
-        current_entry = current_entry->Flink;
-    }
-
-    KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
-
-    return NULL;
-}
-
-
 NTSTATUS
 NtfsFCBInitializeCache(PNTFS_VCB Vcb,
                        PNTFS_FCB Fcb)
@@ -697,42 +664,6 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
 }
 
 
-NTSTATUS
-NtfsGetFCBForFileById(PNTFS_VCB Vcb,
-                      PNTFS_FCB *pFCB,
-                      ULONGLONG Id)
-{
-    NTSTATUS Status;
-    PFILE_RECORD_HEADER FileRecord;
-
-    FileRecord = ExAllocatePoolWithTag(NonPagedPool,
-                                       Vcb->NtfsInfo.BytesPerFileRecord,
-                                       TAG_NTFS);
-    if (FileRecord == NULL)
-    {
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    Status = ReadFileRecord(Vcb, Id, FileRecord);
-    if (!NT_SUCCESS(Status))
-    {
-        ExFreePoolWithTag(FileRecord, TAG_NTFS);
-        return Status;
-    }
-
-    if ((FileRecord->Flags & FRH_IN_USE) != FRH_IN_USE)
-    {
-        ExFreePoolWithTag(FileRecord, TAG_NTFS);
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    Status = NtfsMakeFCBFromDirEntry(Vcb, NULL, NULL, FileRecord, Id, pFCB);
-
-    ExFreePoolWithTag(FileRecord, TAG_NTFS);
-
-    return Status;
-}
-
 NTSTATUS
 NtfsReadFCBAttribute(PNTFS_VCB Vcb,
                      PNTFS_FCB pFCB,
index 6f263ad..37ed519 100644 (file)
@@ -416,7 +416,6 @@ typedef struct _NTFS_ATTR_CONTEXT
 #define FCB_CACHE_INITIALIZED   0x0001
 #define FCB_IS_VOLUME_STREAM    0x0002
 #define FCB_IS_VOLUME           0x0004
-#define FCB_IS_OPEN_BY_ID       0x0008
 #define MAX_PATH                260
 
 typedef struct _FCB
@@ -601,10 +600,6 @@ PNTFS_FCB
 NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
                      PCWSTR FileName);
 
-PNTFS_FCB
-NtfsGrabFCBFromTableById(PNTFS_VCB Vcb,
-                         ULONGLONG Id);
-
 NTSTATUS
 NtfsFCBInitializeCache(PNTFS_VCB Vcb,
                        PNTFS_FCB Fcb);
@@ -626,11 +621,6 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
                   PNTFS_FCB *pFCB,
                   const PWSTR pFileName);
 
-NTSTATUS
-NtfsGetFCBForFileById(PNTFS_VCB Vcb,
-                      PNTFS_FCB *pFCB,
-                      ULONGLONG Id);
-
 NTSTATUS
 NtfsReadFCBAttribute(PNTFS_VCB Vcb,
                      PNTFS_FCB pFCB,