[PATCH 0/2] MR5737: Draft: kernelbase: Use ERROR_DIRECTORY for FindFirstFileExW on invalid name.
When `FindFirstFileA` is called with `<path>/<file>/*` (where file is expected to be a directory), Windows uses the `ERROR_DIRECTORY` error. This patch changes Wine's implementation to match Windows. This fixes a crash in Unity of Command II. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5737
From: Brendan McGrath <bmcgrath(a)codeweavers.com> --- dlls/kernel32/tests/file.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 02625140702..9e5c1e4c594 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -2715,6 +2715,7 @@ static void test_FindFirstFileA(void) char buffer[5] = "C:\\"; char buffer2[100]; char nonexistent[MAX_PATH]; + BOOL found = FALSE; /* try FindFirstFileA on "C:\" */ buffer[0] = get_windows_drive(); @@ -2746,10 +2747,32 @@ static void test_FindFirstFileA(void) ok( FindNextFileA( handle, &data ), "FindNextFile failed\n" ); ok( !strcmp( data.cFileName, ".." ), "FindNextFile should return '..' as second entry\n" ); while (FindNextFileA( handle, &data )) + { ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ), "FindNextFile shouldn't return '%s'\n", data.cFileName ); + if (!found && (data.dwFileAttributes == FILE_ATTRIBUTE_NORMAL || + data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)) + { + GetWindowsDirectoryA( buffer2, sizeof(buffer2) ); + strcat(buffer2, "\\"); + strcat(buffer2, data.cFileName); + strcat(buffer2, "\\*"); + found = TRUE; + } + } ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 ); + ok ( found, "Windows dir should not be empty\n" ); + if (found) + { + SetLastError( 0xdeadbeef ); + handle = FindFirstFileA(buffer2, &data); + err = GetLastError(); + ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); + todo_wine + ok ( err == ERROR_DIRECTORY, "Bad Error number %x\n", err ); + } + /* try FindFirstFileA on "C:\foo\" */ SetLastError( 0xdeadbeaf ); if (!GetTempFileNameA( buffer, "foo", 0, nonexistent )) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5737
From: Brendan McGrath <bmcgrath(a)codeweavers.com> --- dlls/kernel32/tests/file.c | 1 - dlls/kernelbase/file.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 9e5c1e4c594..940b1441e19 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -2769,7 +2769,6 @@ static void test_FindFirstFileA(void) handle = FindFirstFileA(buffer2, &data); err = GetLastError(); ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); - todo_wine ok ( err == ERROR_DIRECTORY, "Bad Error number %x\n", err ); } diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index f842f549061..e7b4a7676ad 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -1262,6 +1262,8 @@ HANDLE WINAPI DECLSPEC_HOTPATCH FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_ { if (status == STATUS_OBJECT_NAME_NOT_FOUND) SetLastError( ERROR_PATH_NOT_FOUND ); + else if (status == STATUS_OBJECT_NAME_INVALID) + SetLastError( ERROR_DIRECTORY ); else SetLastError( RtlNtStatusToDosError(status) ); goto error; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5737
Is it possible NtOpenFile() should return STATUS_NOT_A_DIRECTORY in this case? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5737#note_71520
On Tue May 28 08:16:35 2024 +0000, Nikolay Sivov wrote:
Is it possible NtOpenFile() should return STATUS_NOT_A_DIRECTORY in this case? I just tested on Windows, and that's exactly what it does. I'll update the MR.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5737#note_71530
participants (3)
-
Brendan McGrath -
Brendan McGrath (@redmcg) -
Nikolay Sivov (@nsivov)