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).
This commit is contained in:
parent
d37a119ee6
commit
8b0feb253b
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
12
server/fd.c
12
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;
|
||||
|
|
Loading…
Reference in New Issue