From: Fabian Maurer dark.shadow4@web.de
--- dlls/kernel32/tests/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index c57edebb316..bad4e32bac5 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -1284,7 +1284,8 @@ static void test_CreateFileA(void) {"a", ERROR_FILE_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist file */ {"a\", ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist dir */ {"removeme", ERROR_ACCESS_DENIED, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w/o \ */ - {"removeme\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exst dir w \ */ + {"removeme\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exist dir w \ */ + {"removeme/", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exist dir w / */ {"c:", ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* device in file namespace */ {"c:", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* device in file namespace as dir */ {"c:\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, TRUE }, /* root dir w \ */
From: Fabian Maurer dark.shadow4@web.de
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57376 --- dlls/kernel32/tests/file.c | 11 +++++------ dlls/kernelbase/file.c | 5 +++++ 2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index bad4e32bac5..4b1dff8badf 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -1279,20 +1279,20 @@ static void test_CreateFileA(void) DWORD i, ret, len; static const struct test_list p[] = { - {"", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dir as file w \ */ + {"", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* dir as file w \ */ {"", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* dir as dir w \ */ {"a", ERROR_FILE_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist file */ {"a\", ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist dir */ {"removeme", ERROR_ACCESS_DENIED, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w/o \ */ - {"removeme\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exist dir w \ */ - {"removeme/", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exist dir w / */ + {"removeme\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w \ */ + {"removeme/", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w / */ {"c:", ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* device in file namespace */ {"c:", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* device in file namespace as dir */ - {"c:\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, TRUE }, /* root dir w \ */ + {"c:\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, FALSE }, /* root dir w \ */ {"c:\", ERROR_SUCCESS, ERROR_ACCESS_DENIED, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* root dir w \ as dir */ {"c:c:\windows", ERROR_INVALID_NAME, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* invalid path */ {"\\?\c:", ERROR_SUCCESS, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL,FALSE }, /* dev namespace drive */ - {"\\?\c:\", ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dev namespace drive w \ */ + {"\\?\c:\", ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL, FALSE }, /* dev namespace drive w \ */ {NULL, 0, -1, 0, FALSE} }; BY_HANDLE_FILE_INFORMATION Finfo; @@ -1488,7 +1488,6 @@ static void test_CreateFileA(void) FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL ); - todo_wine ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND, "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %lu\n", filename, GetLastError()); diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 249f476eb7e..81bb8a378cc 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -883,6 +883,11 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileW( LPCWSTR filename, DWORD access, DWO */ if (status == STATUS_OBJECT_NAME_COLLISION) SetLastError( ERROR_FILE_EXISTS ); + else if (status == STATUS_FILE_IS_A_DIRECTORY) + { + WCHAR last = filename[wcslen(filename) - 1]; + SetLastError(last == '\' || last == '/' ? ERROR_PATH_NOT_FOUND : ERROR_ACCESS_DENIED); + } else SetLastError( RtlNtStatusToDosError(status) ); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149435
Your paranoid android.
=== debian11b (64 bit WoW report) ===
kernel32: profile.c:1013: Test failed: Expected ERROR_ACCESS_DENIED, got 3
Jinoh Kang (@iamahuman) commented about dlls/kernelbase/file.c:
*/ if (status == STATUS_OBJECT_NAME_COLLISION) SetLastError( ERROR_FILE_EXISTS );
else if (status == STATUS_FILE_IS_A_DIRECTORY)
{
WCHAR last = filename[wcslen(filename) - 1];
SetLastError(last == '\\' || last == '/' ? ERROR_PATH_NOT_FOUND : ERROR_ACCESS_DENIED);
}
I believe this causes regression for some drivers that handle `IRP_MJ_CREATE` and may return `STATUS_FILE_IS_A_DIRECTORY` from there.
`NtCreateFile()` is ***not*** just a wrapper for `open()`. For custom devices like `\.\MyCustomDriver`, it delegates to the third-party driver. The third-party driver might return `STATUS_FILE_IS_A_DIRECTORY` *but* still expect it to be translated to `ERROR_ACCESS_DENIED` even with the trailing slash.
I suspect the real culprit is that `NtCreateFile()` is incorrectly translating Unix `EISDIR` to `STATUS_FILE_IS_A_DIRECTORY` *unconditionally*. In this case, the bug needs to be fixed in ntdll, not kernelbase.