kernel32: CreateDirectory shouldn't return ERROR_ACCESS_DENIED for the root of the drive.
According to the testbot results CreateDirectory("C:\\", NULL) fails with ERROR_ACCESS_DENIED for not administrators. However with UAC enabled and not and administrator account I get ERROR_ALREADY_EXISTS in that case with Windows 7 64-bit running on real hardware. Moreover, Wine doesn't really perform any access checks in that case and blindly assumes that returning STATUS_ACCESS_DENIED is correct behaviour for the drive's root: dlls/ntdll/directory.c,lookup_unix_name(). This patch fixes an application that can't find its data files because after it receives ERROR_ACCESS_DENIED it stops further directory traversing. Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2058505ceb
commit
c26b6afad3
|
@ -541,10 +541,53 @@ static void test_SetCurrentDirectoryA(void)
|
|||
ok( GetLastError() == ERROR_PATH_NOT_FOUND, "wrong error %d\n", GetLastError() );
|
||||
}
|
||||
|
||||
static void test_CreateDirectory_root(void)
|
||||
{
|
||||
static const WCHAR drive_c_root[] = { 'C',':','\\',0 };
|
||||
static const WCHAR drive_c[] = { 'C',':',0 };
|
||||
char curdir[MAX_PATH];
|
||||
BOOL ret;
|
||||
|
||||
GetCurrentDirectoryA(sizeof(curdir), curdir);
|
||||
|
||||
ret = SetCurrentDirectoryA("C:\\");
|
||||
ok(ret, "SetCurrentDirectory error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateDirectoryA("C:\\", NULL);
|
||||
ok(!ret, "CreateDirectory should fail\n");
|
||||
if (GetLastError() == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
win_skip("not an administrator\n");
|
||||
SetCurrentDirectoryA(curdir);
|
||||
return;
|
||||
}
|
||||
ok(GetLastError() == ERROR_ALREADY_EXISTS, "got %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateDirectoryA("C:", NULL);
|
||||
ok(!ret, "CreateDirectory should fail\n");
|
||||
ok(GetLastError() == ERROR_ALREADY_EXISTS, "got %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateDirectoryW(drive_c_root, NULL);
|
||||
ok(!ret, "CreateDirectory should fail\n");
|
||||
ok(GetLastError() == ERROR_ALREADY_EXISTS, "got %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateDirectoryW(drive_c, NULL);
|
||||
ok(!ret, "CreateDirectory should fail\n");
|
||||
ok(GetLastError() == ERROR_ALREADY_EXISTS, "got %u\n", GetLastError());
|
||||
|
||||
SetCurrentDirectoryA(curdir);
|
||||
}
|
||||
|
||||
START_TEST(directory)
|
||||
{
|
||||
init();
|
||||
|
||||
test_CreateDirectory_root();
|
||||
|
||||
test_GetWindowsDirectoryA();
|
||||
test_GetWindowsDirectoryW();
|
||||
|
||||
|
|
|
@ -2650,9 +2650,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
|||
{
|
||||
if (!stat( unix_name, &st ))
|
||||
{
|
||||
/* creation fails with STATUS_ACCESS_DENIED for the root of the drive */
|
||||
if (disposition == FILE_CREATE)
|
||||
return name_len ? STATUS_OBJECT_NAME_COLLISION : STATUS_ACCESS_DENIED;
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue