This patchset aims to fix #46070 without supplying unix_name for all server files.
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- include/winternl.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/include/winternl.h b/include/winternl.h index 52af87320a5..04778c5cd59 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1633,6 +1633,20 @@ typedef struct _FILE_ALL_INFORMATION { FILE_NAME_INFORMATION NameInformation; } FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
+typedef struct _FILE_STAT_INFORMATION { + LARGE_INTEGER FileId; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; + ULONG ReparseTag; + ULONG NumberOfLinks; + ULONG EffectiveAccess; +} FILE_STAT_INFORMATION, *PFILE_STAT_INFORMATION; + typedef struct _FILE_IO_COMPLETION_NOTIFICATION_INFORMATION { ULONG Flags; } FILE_IO_COMPLETION_NOTIFICATION_INFORMATION, *PFILE_IO_COMPLETION_NOTIFICATION_INFORMATION;
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- dlls/ntdll/tests/file.c | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index da3611f74f2..3ea5eeea01f 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -4357,6 +4357,57 @@ static void test_file_attribute_tag_information(void) CloseHandle( h ); }
+static void test_file_stat_information(void) +{ + BY_HANDLE_FILE_INFORMATION info; + FILE_STAT_INFORMATION fsd; + IO_STATUS_BLOCK io; + NTSTATUS status; + HANDLE h; + BOOL ret; + + if (!(h = create_temp_file(0))) return; + + memset( &fsd, 0x11, sizeof(fsd) ); + status = pNtQueryInformationFile( h, &io, &fsd, sizeof(fsd), FileStatInformation ); + if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS) + { + skip( "FileStatInformation not supported\n" ); + CloseHandle( h ); + return; + } + ok( status == STATUS_SUCCESS, "query FileStatInformation returned %#lx\n", status ); + + memset( &info, 0x22, sizeof(info) ); + ret = GetFileInformationByHandle( h, &info ); + ok( ret, "GetFileInformationByHandle failed\n" ); + + ok( fsd.FileId.u.LowPart == info.nFileIndexLow, "expected %08lx, got %08lx\n", info.nFileIndexLow, fsd.FileId.u.LowPart ); + ok( fsd.FileId.u.HighPart == info.nFileIndexHigh, "expected %08lx, got %08lx\n", info.nFileIndexHigh, fsd.FileId.u.HighPart ); + ok( fsd.CreationTime.u.LowPart == info.ftCreationTime.dwLowDateTime, "expected %08lx, got %08lx\n", + info.ftCreationTime.dwLowDateTime, fsd.CreationTime.u.LowPart ); + ok( fsd.CreationTime.u.HighPart == info.ftCreationTime.dwHighDateTime, "expected %08lx, got %08lx\n", + info.ftCreationTime.dwHighDateTime, fsd.CreationTime.u.HighPart ); + ok( fsd.LastAccessTime.u.LowPart == info.ftLastAccessTime.dwLowDateTime, "expected %08lx, got %08lx\n", + info.ftLastAccessTime.dwLowDateTime, fsd.LastAccessTime.u.LowPart ); + ok( fsd.LastAccessTime.u.HighPart == info.ftLastAccessTime.dwHighDateTime, "expected %08lx, got %08lx\n", + info.ftLastAccessTime.dwHighDateTime, fsd.LastAccessTime.u.HighPart ); + ok( fsd.LastWriteTime.u.LowPart == info.ftLastWriteTime.dwLowDateTime, "expected %08lx, got %08lx\n", + info.ftLastWriteTime.dwLowDateTime, fsd.LastWriteTime.u.LowPart ); + ok( fsd.LastWriteTime.u.HighPart == info.ftLastWriteTime.dwHighDateTime, "expected %08lx, got %08lx\n", + info.ftLastWriteTime.dwHighDateTime, fsd.LastWriteTime.u.HighPart ); + /* TODO: ChangeTime */ + /* TODO: AllocationSize */ + ok( fsd.EndOfFile.u.LowPart == info.nFileSizeLow, "expected %08lx, got %08lx\n", info.nFileSizeLow, fsd.EndOfFile.u.LowPart ); + ok( fsd.EndOfFile.u.HighPart == info.nFileSizeHigh, "expected %08lx, got %08lx\n", info.nFileSizeHigh, fsd.EndOfFile.u.HighPart ); + ok( fsd.FileAttributes == info.dwFileAttributes, "expected %08lx, got %08lx\n", info.dwFileAttributes, fsd.FileAttributes ); + ok( !fsd.ReparseTag, "got reparse tag %#lx\n", fsd.ReparseTag ); + ok( fsd.NumberOfLinks == info.nNumberOfLinks, "expected %08lx, got %08lx\n", info.nNumberOfLinks, fsd.NumberOfLinks ); + ok( fsd.EffectiveAccess == FILE_ALL_ACCESS, "got %08lx\n", fsd.EffectiveAccess ); + + CloseHandle( h ); +} + static void rename_file( HANDLE h, const WCHAR *filename ) { FILE_RENAME_INFORMATION *fri; @@ -5900,6 +5951,7 @@ START_TEST(file) test_file_id_information(); test_file_access_information(); test_file_attribute_tag_information(); + test_file_stat_information(); test_dotfile_file_attributes(); test_file_mode(); test_file_readonly_access();
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- dlls/ntdll/tests/file.c | 2 +- dlls/ntdll/unix/file.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 3ea5eeea01f..9dd49c925b7 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -4372,7 +4372,7 @@ static void test_file_stat_information(void) status = pNtQueryInformationFile( h, &io, &fsd, sizeof(fsd), FileStatInformation ); if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS) { - skip( "FileStatInformation not supported\n" ); + win_skip( "FileStatInformation not supported\n" ); CloseHandle( h ); return; } diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index ee68e4dee9b..d15f9816c07 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4334,7 +4334,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, 0, /* FileRenameInformationEx */ 0, /* FileRenameInformationExBypassAccessCheck */ 0, /* FileDesiredStorageClassInformation */ - 0, /* FileStatInformation */ + sizeof(FILE_STAT_INFORMATION), /* FileStatInformation */ 0, /* FileMemoryPartitionInformation */ 0, /* FileStatLxInformation */ 0, /* FileCaseSensitiveInformation */ @@ -4549,6 +4549,38 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, info->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; } break; + case FileStatInformation: + if (fd_get_file_info( fd, options, &st, &attr ) == -1) status = errno_to_status( errno ); + else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) + status = STATUS_INVALID_INFO_CLASS; + else + { + FILE_STAT_INFORMATION *info = ptr; + FILE_BASIC_INFORMATION basic; + FILE_STANDARD_INFORMATION std; + FILE_ACCESS_INFORMATION access = {0}; + IO_STATUS_BLOCK inner_io; + + fill_file_info( &st, attr, &basic, FileBasicInformation ); + fill_file_info( &st, attr, &std, FileStandardInformation ); + + server_get_file_info( handle, &inner_io, &access, sizeof(access), FileAccessInformation ); + + info->FileId.QuadPart = st.st_ino; + info->CreationTime = basic.CreationTime; + info->LastAccessTime = basic.LastAccessTime; + info->LastWriteTime = basic.LastWriteTime; + info->ChangeTime = basic.ChangeTime; + info->AllocationSize = std.AllocationSize; + info->EndOfFile = std.EndOfFile; + info->FileAttributes = attr; + info->ReparseTag = 0; /* FIXME */ + if ((options & FILE_OPEN_REPARSE_POINT) && fd_is_mount_point( fd, &st )) + info->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; + info->NumberOfLinks = std.NumberOfLinks; + info->EffectiveAccess = FILE_ALL_ACCESS; /* FIXME */ + } + break; default: FIXME("Unsupported class (%d)\n", class); status = STATUS_NOT_IMPLEMENTED;
From: Jinoh Kang jinoh.kang.kr@gmail.com
It also fixes the game Unity of Command II (same bug).
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46070 --- dlls/kernelbase/file.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 67a7a34249a..2b59db43041 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -3043,27 +3043,26 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlushFileBuffers( HANDLE file ) BOOL WINAPI DECLSPEC_HOTPATCH GetFileInformationByHandle( HANDLE file, BY_HANDLE_FILE_INFORMATION *info ) { FILE_FS_VOLUME_INFORMATION volume_info; - FILE_ALL_INFORMATION all_info; + FILE_STAT_INFORMATION stat_info; IO_STATUS_BLOCK io; NTSTATUS status;
- status = NtQueryInformationFile( file, &io, &all_info, sizeof(all_info), FileAllInformation ); - if (status == STATUS_BUFFER_OVERFLOW) status = STATUS_SUCCESS; + status = NtQueryInformationFile( file, &io, &stat_info, sizeof(stat_info), FileStatInformation ); if (!set_ntstatus( status )) return FALSE;
- info->dwFileAttributes = all_info.BasicInformation.FileAttributes; - info->ftCreationTime.dwHighDateTime = all_info.BasicInformation.CreationTime.u.HighPart; - info->ftCreationTime.dwLowDateTime = all_info.BasicInformation.CreationTime.u.LowPart; - info->ftLastAccessTime.dwHighDateTime = all_info.BasicInformation.LastAccessTime.u.HighPart; - info->ftLastAccessTime.dwLowDateTime = all_info.BasicInformation.LastAccessTime.u.LowPart; - info->ftLastWriteTime.dwHighDateTime = all_info.BasicInformation.LastWriteTime.u.HighPart; - info->ftLastWriteTime.dwLowDateTime = all_info.BasicInformation.LastWriteTime.u.LowPart; + info->dwFileAttributes = stat_info.FileAttributes; + info->ftCreationTime.dwHighDateTime = stat_info.CreationTime.u.HighPart; + info->ftCreationTime.dwLowDateTime = stat_info.CreationTime.u.LowPart; + info->ftLastAccessTime.dwHighDateTime = stat_info.LastAccessTime.u.HighPart; + info->ftLastAccessTime.dwLowDateTime = stat_info.LastAccessTime.u.LowPart; + info->ftLastWriteTime.dwHighDateTime = stat_info.LastWriteTime.u.HighPart; + info->ftLastWriteTime.dwLowDateTime = stat_info.LastWriteTime.u.LowPart; info->dwVolumeSerialNumber = 0; - info->nFileSizeHigh = all_info.StandardInformation.EndOfFile.u.HighPart; - info->nFileSizeLow = all_info.StandardInformation.EndOfFile.u.LowPart; - info->nNumberOfLinks = all_info.StandardInformation.NumberOfLinks; - info->nFileIndexHigh = all_info.InternalInformation.IndexNumber.u.HighPart; - info->nFileIndexLow = all_info.InternalInformation.IndexNumber.u.LowPart; + info->nFileSizeHigh = stat_info.EndOfFile.u.HighPart; + info->nFileSizeLow = stat_info.EndOfFile.u.LowPart; + info->nNumberOfLinks = stat_info.NumberOfLinks; + info->nFileIndexHigh = stat_info.FileId.u.HighPart; + info->nFileIndexLow = stat_info.FileId.u.LowPart;
status = NtQueryVolumeInformationFile( file, &io, &volume_info, sizeof(volume_info), FileFsVolumeInformation ); if (status == STATUS_SUCCESS || status == STATUS_BUFFER_OVERFLOW)
@insn I'm assuming here that both CPython and Unity of Command II have the same bug: failing due to `GetFileInformationByHandle` on unix fd based handles. Feel free to correct me if this is not the case.