Signed-off-by: Paul Gofman pgofman@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;