From: Elizabeth Figura <zfigura@codeweavers.com> Using FileIdExtdBothDirectoryInformation introduced a regression in the game "Monster Hunter Stories 3: Twisted Reflection Trial" distributed via Steam, which prevents DLSS from being enabled. The game calls FindFirstFileEx() while hotpatching NtQueryDirectoryFile(). The hook's purpose is unclear, but using FileIdExtdBothDirectoryInformation or FileIdExtdDirectoryInformation causes it to essentially reject almost all of the files enumerated, returning as if the directory were empty, except for the first and last calls made. Fixes: 221f03e447d5c583412d0288a6200045ba84d800 --- dlls/kernelbase/file.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 7c079260af9..57bfe7fe871 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -63,7 +63,7 @@ typedef struct #define FIND_FIRST_MAGIC 0xc0ffee11 -static const UINT max_entry_size = offsetof( FILE_ID_EXTD_BOTH_DIRECTORY_INFORMATION, FileName[256] ); +static const UINT max_entry_size = offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] ); const WCHAR windows_dir[] = L"C:\\windows"; const WCHAR system_dir[] = L"C:\\windows\\system32"; @@ -1406,7 +1406,7 @@ HANDLE WINAPI DECLSPEC_HOTPATCH FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_ { RtlInitUnicodeString( &mask_str, fixedup_mask ); status = NtQueryDirectoryFile( info->handle, 0, NULL, NULL, &io, info->data, info->data_size, - FileIdExtdBothDirectoryInformation, FALSE, &mask_str, TRUE ); + FileBothDirectoryInformation, FALSE, &mask_str, TRUE ); } if (fixedup_mask != mask) HeapFree( GetProcessHeap(), 0, fixedup_mask ); if (status) @@ -1506,7 +1506,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FindNextFileA( HANDLE handle, WIN32_FIND_DATAA *da BOOL WINAPI DECLSPEC_HOTPATCH FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *data ) { FIND_FIRST_INFO *info = handle; - FILE_ID_EXTD_BOTH_DIRECTORY_INFORMATION *dir_info; + FILE_BOTH_DIR_INFORMATION *dir_info; BOOL ret = FALSE; NTSTATUS status; @@ -1529,7 +1529,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *da if (info->data_size) status = NtQueryDirectoryFile( info->handle, 0, NULL, NULL, &io, info->data, info->data_size, - FileIdExtdBothDirectoryInformation, FALSE, NULL, FALSE ); + FileBothDirectoryInformation, FALSE, NULL, FALSE ); else status = STATUS_NO_MORE_FILES; @@ -1546,7 +1546,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *da info->data_pos = 0; } - dir_info = (FILE_ID_EXTD_BOTH_DIRECTORY_INFORMATION *)(info->data + info->data_pos); + dir_info = (FILE_BOTH_DIR_INFORMATION *)(info->data + info->data_pos); if (dir_info->NextEntryOffset) info->data_pos += dir_info->NextEntryOffset; else info->data_pos = info->data_len; @@ -1566,7 +1566,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *da data->ftLastWriteTime = *(FILETIME *)&dir_info->LastWriteTime; data->nFileSizeHigh = dir_info->EndOfFile.QuadPart >> 32; data->nFileSizeLow = (DWORD)dir_info->EndOfFile.QuadPart; - data->dwReserved0 = dir_info->ReparsePointTag; + /* We intentionally do not use FileIdExtdBothDirectoryInformation here; + * it breaks certain hotpatchers. Windows returns the reparse tag in + * EaSize for FileBothDirectoryInformation. */ + data->dwReserved0 = 0; + if (dir_info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + data->dwReserved0 = dir_info->EaSize; data->dwReserved1 = 0; memcpy( data->cFileName, dir_info->FileName, dir_info->FileNameLength ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10105