[PATCH] kernelbase: Implement GetFileInformationByHandleEx(FileFullDirectoryInfo).

Paul Gofman pgofman at codeweavers.com
Wed Feb 9 08:28:11 CST 2022


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/kernel32/tests/file.c | 60 ++++++++++++++++++++++++++++++++++----
 dlls/kernelbase/file.c     | 12 ++++++--
 include/winbase.h          | 15 ++++++++++
 3 files changed, 80 insertions(+), 7 deletions(-)

diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index f8e49491a7d..0d178306648 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -4181,11 +4181,13 @@ todo_wine_if (i == 1)
 static void test_GetFileInformationByHandleEx(void)
 {
     int i;
-    char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024], *strPtr;
-    BOOL ret;
+    char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024], buffer2[1024], *strPtr;
+    BOOL first, ret;
     DWORD ret2, written;
+    unsigned int count, count2, size;
     HANDLE directory, file;
     FILE_ID_BOTH_DIR_INFO *bothDirInfo;
+    FILE_FULL_DIR_INFO *full_dir_info;
     FILE_BASIC_INFO *basicInfo;
     FILE_STANDARD_INFO *standardInfo;
     FILE_NAME_INFO *nameInfo;
@@ -4205,7 +4207,11 @@ static void test_GetFileInformationByHandleEx(void)
         {0xdeadbeef, NULL, 0, ERROR_INVALID_PARAMETER},
         {FileIdBothDirectoryInfo, NULL, 0, ERROR_BAD_LENGTH},
         {FileIdBothDirectoryInfo, NULL, sizeof(buffer), ERROR_NOACCESS},
-        {FileIdBothDirectoryInfo, buffer, 0, ERROR_BAD_LENGTH}};
+        {FileIdBothDirectoryInfo, buffer, 0, ERROR_BAD_LENGTH},
+        {FileFullDirectoryInfo, NULL, 0, ERROR_BAD_LENGTH},
+        {FileFullDirectoryInfo, NULL, sizeof(buffer), ERROR_NOACCESS},
+        {FileFullDirectoryInfo, buffer, 0, ERROR_BAD_LENGTH},
+    };
 
     if (!pGetFileInformationByHandleEx)
     {
@@ -4236,6 +4242,7 @@ static void test_GetFileInformationByHandleEx(void)
            "got %u.\n", checks[i].errorCode, GetLastError());
     }
 
+    first = TRUE;
     while (TRUE)
     {
         memset(buffer, 0xff, sizeof(buffer));
@@ -4243,8 +4250,51 @@ static void test_GetFileInformationByHandleEx(void)
         if (!ret && GetLastError() == ERROR_NO_MORE_FILES)
             break;
         ok(ret, "GetFileInformationByHandleEx: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
-        if (!ret)
-            break;
+
+        if (first)
+        {
+            count = 1;
+            bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
+            while (bothDirInfo->NextEntryOffset)
+            {
+                ++count;
+                size = offsetof(FILE_ID_BOTH_DIR_INFO, FileName[bothDirInfo->FileNameLength / 2]);
+                size = (size + 7) & ~7;
+                ok(bothDirInfo->NextEntryOffset == size,
+                        "Got unexpected structure size, NextEntryOffset %u (%u).\n", bothDirInfo->NextEntryOffset,
+                        size);
+                bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset);
+            }
+            size = offsetof(FILE_FULL_DIR_INFO, FileName[bothDirInfo->FileNameLength / 2]);
+            ret = pGetFileInformationByHandleEx(directory, FileFullDirectoryRestartInfo, buffer2, sizeof(buffer2));
+            ok(ret, "failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
+
+            count2 = 0;
+            bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
+            full_dir_info = (FILE_FULL_DIR_INFO *)buffer2;
+            while (1)
+            {
+                ++count2;
+                ok(bothDirInfo->FileNameLength == full_dir_info->FileNameLength,
+                        "FileNameLength does not match, count2 %u.\n", count2);
+                ok(!memcmp(bothDirInfo->FileName, full_dir_info->FileName, full_dir_info->FileNameLength),
+                        "FileName does not match, count %u.\n", count2);
+
+                if (!full_dir_info->NextEntryOffset || !bothDirInfo->NextEntryOffset)
+                    break;
+
+                size = offsetof(FILE_FULL_DIR_INFO, FileName[full_dir_info->FileNameLength / 2]);
+                size = (size + 7) & ~7;
+                ok(full_dir_info->NextEntryOffset == size,
+                        "Got unexpected structure size, NextEntryOffset %u (%u).\n", bothDirInfo->NextEntryOffset,
+                        size);
+                full_dir_info = (FILE_FULL_DIR_INFO *)(((char *)full_dir_info) + full_dir_info->NextEntryOffset);
+                bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset);
+            }
+            ok(count2 == count, "Got unexpected count2 %u, count %u.\n", count2, count);
+            first = FALSE;
+        }
+
         bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
         while (TRUE)
         {
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
index 576e03eb62b..c1d9401f5c2 100644
--- a/dlls/kernelbase/file.c
+++ b/dlls/kernelbase/file.c
@@ -2954,13 +2954,13 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetFileInformationByHandleEx( HANDLE handle, FILE_
     NTSTATUS status;
     IO_STATUS_BLOCK io;
 
+    TRACE( "%p, %u, %p, %u.\n", handle, class, info, size );
+
     switch (class)
     {
     case FileStreamInfo:
     case FileCompressionInfo:
     case FileRemoteProtocolInfo:
-    case FileFullDirectoryInfo:
-    case FileFullDirectoryRestartInfo:
     case FileStorageInfo:
     case FileAlignmentInfo:
     case FileIdExtdDirectoryInfo:
@@ -2969,6 +2969,13 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetFileInformationByHandleEx( HANDLE handle, FILE_
         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
         return FALSE;
 
+    case FileFullDirectoryRestartInfo:
+    case FileFullDirectoryInfo:
+        status = NtQueryDirectoryFile( handle, NULL, NULL, NULL, &io, info, size,
+                                       FileFullDirectoryInformation, FALSE, NULL,
+                                       (class == FileFullDirectoryRestartInfo) );
+        break;
+
     case FileAttributeTagInfo:
         status = NtQueryInformationFile( handle, &io, info, size, FileAttributeTagInformation );
         break;
@@ -3002,6 +3009,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetFileInformationByHandleEx( HANDLE handle, FILE_
     case FileIoPriorityHintInfo:
     case FileEndOfFileInfo:
     default:
+        WARN( "class %u is not supported.\n", class );
         SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
diff --git a/include/winbase.h b/include/winbase.h
index 0a0bfde9d10..b2d5ca68d42 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -823,6 +823,21 @@ typedef struct _FILE_ID_BOTH_DIR_INFO {
     WCHAR         FileName[1];
 } FILE_ID_BOTH_DIR_INFO, *PFILE_ID_BOTH_DIR_INFO;
 
+typedef struct _FILE_FULL_DIR_INFO {
+    ULONG         NextEntryOffset;
+    ULONG         FileIndex;
+    LARGE_INTEGER CreationTime;
+    LARGE_INTEGER LastAccessTime;
+    LARGE_INTEGER LastWriteTime;
+    LARGE_INTEGER ChangeTime;
+    LARGE_INTEGER EndOfFile;
+    LARGE_INTEGER AllocationSize;
+    ULONG         FileAttributes;
+    ULONG         FileNameLength;
+    ULONG         EaSize;
+    WCHAR         FileName[1];
+} FILE_FULL_DIR_INFO, *PFILE_FULL_DIR_INFO;
+
 typedef struct _FILE_BASIC_INFO {
     LARGE_INTEGER CreationTime;
     LARGE_INTEGER LastAccessTime;
-- 
2.34.1




More information about the wine-devel mailing list