From 8b0feb253bc569a39e724a8da006735166fc1b32 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 27 Jan 2006 15:50:38 +0100 Subject: [PATCH] server: Make the FILE_SHARE_DELETE sharing checks depend on DELETE access instead of on the FILE_DELETE_ON_CLOSE flag (based on a patch by Mike McCormack). --- dlls/kernel/file.c | 3 +++ dlls/kernel/path.c | 2 +- dlls/kernel/tests/file.c | 20 ++++++++++++++------ dlls/ntdll/file.c | 4 ++-- dlls/ntdll/tests/change.c | 2 -- server/fd.c | 12 ++++++++---- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/dlls/kernel/file.c b/dlls/kernel/file.c index 34a42153c7f..9c5973a62bc 100644 --- a/dlls/kernel/file.c +++ b/dlls/kernel/file.c @@ -1348,7 +1348,10 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, else options |= FILE_NON_DIRECTORY_FILE; if (attributes & FILE_FLAG_DELETE_ON_CLOSE) + { options |= FILE_DELETE_ON_CLOSE; + access |= DELETE; + } if (!(attributes & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_ALERT; if (attributes & FILE_FLAG_RANDOM_ACCESS) diff --git a/dlls/kernel/path.c b/dlls/kernel/path.c index 0608f178096..66c1e849be0 100644 --- a/dlls/kernel/path.c +++ b/dlls/kernel/path.c @@ -1277,7 +1277,7 @@ BOOL WINAPI RemoveDirectoryW( LPCWSTR path ) attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; - status = NtOpenFile( &handle, GENERIC_READ, &attr, &io, + status = NtOpenFile( &handle, DELETE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (status == STATUS_SUCCESS) diff --git a/dlls/kernel/tests/file.c b/dlls/kernel/tests/file.c index 3310670f271..093a893e1de 100644 --- a/dlls/kernel/tests/file.c +++ b/dlls/kernel/tests/file.c @@ -1081,15 +1081,23 @@ static inline int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD ac if (!access1 || !access2) return 1; if ((access1 & GENERIC_READ) && !(sharing2 & FILE_SHARE_READ)) return 0; if ((access1 & GENERIC_WRITE) && !(sharing2 & FILE_SHARE_WRITE)) return 0; + if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return 0; if ((access2 & GENERIC_READ) && !(sharing1 & FILE_SHARE_READ)) return 0; if ((access2 & GENERIC_WRITE) && !(sharing1 & FILE_SHARE_WRITE)) return 0; + if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return 0; return 1; } static void test_file_sharing(void) { - static const DWORD access_modes[4] = { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE }; - static const DWORD sharing_modes[4] = { 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE }; + static const DWORD access_modes[] = + { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE, + DELETE, GENERIC_READ|DELETE, GENERIC_WRITE|DELETE, GENERIC_READ|GENERIC_WRITE|DELETE }; + static const DWORD sharing_modes[] = + { 0, FILE_SHARE_READ, + FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_DELETE, + FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE }; int a1, s1, a2, s2; int ret; HANDLE h, h2; @@ -1103,9 +1111,9 @@ static void test_file_sharing(void) } CloseHandle( h ); - for (a1 = 0; a1 < 4; a1++) + for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++) { - for (s1 = 0; s1 < 4; s1++) + for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++) { h = CreateFileA( filename, access_modes[a1], sharing_modes[s1], NULL, OPEN_EXISTING, 0, 0 ); @@ -1114,9 +1122,9 @@ static void test_file_sharing(void) ok(0,"couldn't create file \"%s\" (err=%ld)\n",filename,GetLastError()); return; } - for (a2 = 0; a2 < 4; a2++) + for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++) { - for (s2 = 0; s2 < 4; s2++) + for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++) { SetLastError(0xdeadbeef); h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2], diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 9ef22620313..b817283c230 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -2052,8 +2052,8 @@ NTSTATUS WINAPI NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes ) IO_STATUS_BLOCK io; TRACE("%p\n", ObjectAttributes); - status = NtCreateFile( &hFile, GENERIC_READ | GENERIC_WRITE, ObjectAttributes, - &io, NULL, 0, + status = NtCreateFile( &hFile, GENERIC_READ | GENERIC_WRITE | DELETE, + ObjectAttributes, &io, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_DELETE_ON_CLOSE, NULL, 0 ); if (status == STATUS_SUCCESS) status = NtClose(hFile); diff --git a/dlls/ntdll/tests/change.c b/dlls/ntdll/tests/change.c index d07cb841a12..c347799d2b5 100644 --- a/dlls/ntdll/tests/change.c +++ b/dlls/ntdll/tests/change.c @@ -113,7 +113,6 @@ static void test_ntncdf(void) r = WaitForSingleObject( hdir, 0 ); ok( r == WAIT_OBJECT_0, "event wasn't ready\n" ); - todo_wine { r = RemoveDirectoryW( path ); ok( r == FALSE, "failed to remove directory\n"); @@ -121,7 +120,6 @@ static void test_ntncdf(void) r = RemoveDirectoryW( path ); ok( r == TRUE, "failed to remove directory\n"); - } } START_TEST(change) diff --git a/server/fd.c b/server/fd.c index a142acdb8f2..ed988215df2 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1283,7 +1283,6 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari { unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; unsigned int existing_access = 0; - int unlink = 0; struct list *ptr; /* if access mode is 0, sharing mode is ignored */ @@ -1298,16 +1297,15 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari { existing_sharing &= fd_ptr->sharing; existing_access |= fd_ptr->access; - if (fd_ptr->closed->unlink[0]) unlink = 1; } } if ((access & FILE_UNIX_READ_ACCESS) && !(existing_sharing & FILE_SHARE_READ)) return 0; if ((access & FILE_UNIX_WRITE_ACCESS) && !(existing_sharing & FILE_SHARE_WRITE)) return 0; + if ((access & DELETE) && !(existing_sharing & FILE_SHARE_DELETE)) return 0; if ((existing_access & FILE_UNIX_READ_ACCESS) && !(sharing & FILE_SHARE_READ)) return 0; if ((existing_access & FILE_UNIX_WRITE_ACCESS) && !(sharing & FILE_SHARE_WRITE)) return 0; - if (fd->closed->unlink[0] && !(existing_sharing & FILE_SHARE_DELETE)) return 0; - if (unlink && !(sharing & FILE_SHARE_DELETE)) return 0; + if ((existing_access & DELETE) && !(sharing & FILE_SHARE_DELETE)) return 0; return 1; } @@ -1329,6 +1327,12 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce const char *unlink_name = ""; int rw_mode; + if ((options & FILE_DELETE_ON_CLOSE) && !(access & DELETE)) + { + set_error( STATUS_INVALID_PARAMETER ); + return NULL; + } + if (!(fd = alloc_fd_object())) return NULL; if (options & FILE_DELETE_ON_CLOSE) unlink_name = name;