[FASTFAT] Don't mix FileNameInformation and FileNamesInformation (and support the...
authorPierre Schweitzer <pierre@reactos.org>
Sat, 9 Dec 2017 11:33:29 +0000 (12:33 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 9 Dec 2017 11:37:34 +0000 (12:37 +0100)
This commit fixes weird behavior in our FastFAT implementation. It was mixing two classes:
FileNameInformation and FileNamesInformation. It was handling FileNameInformation like
FileNamesInformation and was filling buffer with FILE_NAMES_INFORMATION structure instead
of FILE_NAME_INFORMATION structure (how many things did that break?!).
Also, it wasn't implementing the FileNamesInformation class at all. This is required by
ntdll_winetest:directory which doesn't expect it to fail and thus, attempts to read
never filled in memory.

This commit fixes the winetest crash, and may fix other weird FS behavior.

CORE-13367

drivers/filesystems/fastfat/dir.c

index db96257..284c04b 100644 (file)
@@ -89,6 +89,47 @@ FsdSystemTimeToDosDateTime(
 static
 NTSTATUS
 VfatGetFileNameInformation(
+    PVFAT_DIRENTRY_CONTEXT DirContext,
+    PFILE_NAME_INFORMATION pInfo,
+    ULONG BufferLength,
+    PULONG Written,
+    BOOLEAN First)
+{
+    NTSTATUS Status;
+    ULONG BytesToCopy = 0;
+
+    *Written = 0;
+    Status = STATUS_BUFFER_OVERFLOW;
+
+    if (FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName) > BufferLength)
+        return Status;
+
+    if (First || (BufferLength >= FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName) + DirContext->LongNameU.Length))
+    {
+        pInfo->FileNameLength = DirContext->LongNameU.Length;
+
+        *Written = FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName);
+        if (BufferLength > FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName))
+        {
+            BytesToCopy = min(DirContext->LongNameU.Length, BufferLength - FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName));
+            RtlCopyMemory(pInfo->FileName,
+                         DirContext->LongNameU.Buffer,
+                         BytesToCopy);
+            *Written += BytesToCopy;
+
+            if (BytesToCopy == DirContext->LongNameU.Length)
+            {
+                Status = STATUS_SUCCESS;
+            }
+        }
+    }
+
+    return Status;
+}
+
+static
+NTSTATUS
+VfatGetFileNamesInformation(
     PVFAT_DIRENTRY_CONTEXT DirContext,
     PFILE_NAMES_INFORMATION pInfo,
     ULONG BufferLength,
@@ -622,7 +663,7 @@ DoQuery(
             {
                 case FileNameInformation:
                     Status = VfatGetFileNameInformation(&DirContext,
-                                                        (PFILE_NAMES_INFORMATION)Buffer,
+                                                        (PFILE_NAME_INFORMATION)Buffer,
                                                         BufferLength,
                                                         &Written,
                                                         Buffer0 == NULL);
@@ -655,6 +696,14 @@ DoQuery(
                                                         Buffer0 == NULL);
                     break;
 
+                case FileNamesInformation:
+                    Status = VfatGetFileNamesInformation(&DirContext,
+                                                         (PFILE_NAMES_INFORMATION)Buffer,
+                                                         BufferLength,
+                                                         &Written,
+                                                         Buffer0 == NULL);
+                     break;
+
                 default:
                     Status = STATUS_INVALID_INFO_CLASS;
                     break;