[NTFS]
[reactos.git] / reactos / drivers / filesystems / ntfs / dirctl.c
index 254cc19..088b69f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2002,2003 ReactOS Team
+ *  Copyright (C) 2002, 2003, 2014 ReactOS Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -20,7 +20,9 @@
  * PROJECT:          ReactOS kernel
  * FILE:             drivers/filesystem/ntfs/dirctl.c
  * PURPOSE:          NTFS filesystem driver
- * PROGRAMMER:       Eric Kohl
+ * PROGRAMMERS:      Eric Kohl
+ *                   Pierre Schweitzer (pierre@reactos.org)
+ *                   HervĂ© Poussineau (hpoussin@reactos.org)
  */
 
 /* INCLUDES *****************************************************************/
@@ -135,7 +137,15 @@ NtfsGetNameInformation(PDEVICE_EXTENSION DeviceExt,
 
     DPRINT("NtfsGetNameInformation() called\n");
 
-    FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
+    FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX);
+    if (FileName == NULL)
+    {
+        FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
+        if (FileName == NULL)
+        {
+            FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
+        }
+    }
     ASSERT(FileName != NULL);
 
     Length = FileName->NameLength * sizeof (WCHAR);
@@ -163,7 +173,15 @@ NtfsGetDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
 
     DPRINT("NtfsGetDirectoryInformation() called\n");
 
-    FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
+    FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX);
+    if (FileName == NULL)
+    {
+        FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
+        if (FileName == NULL)
+        {
+            FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
+        }
+    }
     ASSERT(FileName != NULL);
 
     Length = FileName->NameLength * sizeof (WCHAR);
@@ -204,7 +222,15 @@ NtfsGetFullDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
 
     DPRINT("NtfsGetFullDirectoryInformation() called\n");
 
-    FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
+    FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX);
+    if (FileName == NULL)
+    {
+        FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
+        if (FileName == NULL)
+        {
+            FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
+        }
+    }
     ASSERT(FileName != NULL);
 
     Length = FileName->NameLength * sizeof (WCHAR);
@@ -242,12 +268,21 @@ NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
                                 ULONG BufferLength)
 {
     ULONG Length;
-    PFILENAME_ATTRIBUTE FileName;
+    PFILENAME_ATTRIBUTE FileName, ShortFileName;
 
     DPRINT("NtfsGetBothDirectoryInformation() called\n");
 
-    FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
+    FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX);
+    if (FileName == NULL)
+    {
+        FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
+        if (FileName == NULL)
+        {
+            FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
+        }
+    }
     ASSERT(FileName != NULL);
+    ShortFileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
 
     Length = FileName->NameLength * sizeof (WCHAR);
     if ((sizeof(FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength)
@@ -258,6 +293,19 @@ NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
         ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG));
     RtlCopyMemory(Info->FileName, FileName->Name, Length);
 
+    if (ShortFileName)
+    {
+        /* Should we upcase the filename? */
+        ASSERT(ShortFileName->NameLength <= ARRAYSIZE(Info->ShortName));
+        Info->ShortNameLength = ShortFileName->NameLength * sizeof(WCHAR);
+        RtlCopyMemory(Info->ShortName, ShortFileName->Name, Info->ShortNameLength);
+    }
+    else
+    {
+        Info->ShortName[0] = 0;
+        Info->ShortNameLength = 0;
+    }
+
     Info->CreationTime.QuadPart = FileName->CreationTime;
     Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
     Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
@@ -272,9 +320,6 @@ NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
 //  Info->FileIndex=;
     Info->EaSize = 0;
 
-    Info->ShortName[0] = 0;
-    Info->ShortNameLength = 0;
-
     return STATUS_SUCCESS;
 }
 
@@ -299,7 +344,7 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
     NTSTATUS Status = STATUS_SUCCESS;
     PFILE_RECORD_HEADER FileRecord;
     PNTFS_ATTR_CONTEXT DataContext;
-    ULONGLONG MFTRecord;
+    ULONGLONG MFTRecord, OldMFTRecord = 0;
     UNICODE_STRING Pattern;
 
     DPRINT1("NtfsQueryDirectory() called\n");
@@ -326,16 +371,23 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
         if (!Ccb->DirectorySearchPattern)
         {
             First = TRUE;
-            Ccb->DirectorySearchPattern =
-                ExAllocatePoolWithTag(NonPagedPool, SearchPattern->Length + sizeof(WCHAR), TAG_NTFS);
+            Pattern.Length = 0;
+            Pattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
+            Ccb->DirectorySearchPattern = Pattern.Buffer =
+                ExAllocatePoolWithTag(NonPagedPool, Pattern.MaximumLength, TAG_NTFS);
             if (!Ccb->DirectorySearchPattern)
             {
                 return STATUS_INSUFFICIENT_RESOURCES;
             }
 
-            memcpy(Ccb->DirectorySearchPattern,
-                   SearchPattern->Buffer,
-                   SearchPattern->Length);
+            Status = RtlUpcaseUnicodeString(&Pattern, SearchPattern, FALSE);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("RtlUpcaseUnicodeString('%wZ') failed with status 0x%08lx\n", &Pattern, Status);
+                ExFreePoolWithTag(Ccb->DirectorySearchPattern, TAG_NTFS);
+                Ccb->DirectorySearchPattern = NULL;
+                return Status;
+            }
             Ccb->DirectorySearchPattern[SearchPattern->Length / sizeof(WCHAR)] = 0;
         }
     }
@@ -353,9 +405,8 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
     }
 
     RtlInitUnicodeString(&Pattern, Ccb->DirectorySearchPattern);
-
-    DPRINT1("Search pattern '%S'\n", Ccb->DirectorySearchPattern);
-    DPRINT1("In: '%S'\n", Fcb->PathName);
+    DPRINT("Search pattern '%S'\n", Ccb->DirectorySearchPattern);
+    DPRINT("In: '%S'\n", Fcb->PathName);
 
     /* Determine directory index */
     if (Stack->Flags & SL_INDEX_SPECIFIED)
@@ -388,10 +439,21 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
                                 &DataContext,
                                 &MFTRecord,
                                 Fcb->MFTIndex);
-      //DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry);
 
         if (NT_SUCCESS(Status))
         {
+            /* HACK: files with both a short name and a long name are present twice in the index.
+             * Ignore the second entry, if it is immediately following the first one.
+             */
+            if (MFTRecord == OldMFTRecord)
+            {
+                DPRINT("Ignoring duplicate MFT entry 0x%x\n", MFTRecord);
+                Ccb->Entry++;
+                ExFreePoolWithTag(FileRecord, TAG_NTFS);
+                continue;
+            }
+            OldMFTRecord = MFTRecord;
+
             switch (FileInformationClass)
             {
                 case FileNameInformation: