[PATCH v2] kernelbase: Implement GetFileInformationByHandleEx(FileFullDirectoryInfo).
Paul Gofman
pgofman at codeweavers.com
Wed Feb 9 09:33:13 CST 2022
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
v2:
- fix test failures on Win7.
dlls/kernel32/tests/file.c | 75 ++++++++++++++++++++++++++++++++++----
dlls/kernelbase/file.c | 12 +++++-
include/winbase.h | 15 ++++++++
3 files changed, 93 insertions(+), 9 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index f8e49491a7d..1f905cd59f8 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;
@@ -4195,17 +4197,26 @@ static void test_GetFileInformationByHandleEx(void)
FILE_DISPOSITION_INFO dispinfo;
FILE_END_OF_FILE_INFO eofinfo;
FILE_RENAME_INFO renameinfo;
+ BOOL full_dir_info_supported;
- struct {
+ struct
+ {
FILE_INFO_BY_HANDLE_CLASS handleClass;
void *ptr;
DWORD size;
DWORD errorCode;
- } checks[] = {
+ BOOL not_always_supported;
+ }
+ checks[] =
+ {
{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, TRUE},
+ {FileFullDirectoryInfo, NULL, sizeof(buffer), ERROR_NOACCESS},
+ {FileFullDirectoryInfo, buffer, 0, ERROR_BAD_LENGTH},
+ };
if (!pGetFileInformationByHandleEx)
{
@@ -4232,10 +4243,17 @@ static void test_GetFileInformationByHandleEx(void)
{
SetLastError(0xdeadbeef);
ret = pGetFileInformationByHandleEx(directory, checks[i].handleClass, checks[i].ptr, checks[i].size);
+ if (checks[i].not_always_supported && !ret && GetLastError() == ERROR_INVALID_PARAMETER)
+ {
+ win_skip("class %u is not supported, skipping the rest.\n", checks[i].handleClass);
+ break;
+ }
ok(!ret && GetLastError() == checks[i].errorCode, "GetFileInformationByHandleEx: expected error %u, "
"got %u.\n", checks[i].errorCode, GetLastError());
}
+ full_dir_info_supported = (i == ARRAY_SIZE(checks));
+ first = TRUE;
while (TRUE)
{
memset(buffer, 0xff, sizeof(buffer));
@@ -4243,8 +4261,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 (full_dir_info_supported && 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 FileFullDirectoryInfo, 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