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.
From: Brendan McGrath bmcgrath@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 ))
From: Brendan McGrath bmcgrath@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;
Is it possible NtOpenFile() should return STATUS_NOT_A_DIRECTORY in this case?
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.