server: Implement the special file sharing rules for memory mappings.
This commit is contained in:
parent
028bca4cc5
commit
fd504b6289
|
@ -1827,16 +1827,16 @@ static void test_file_sharing(void)
|
|||
if (h2 == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]))
|
||||
todo_wine ok( is_win9x, /* there's no sharing at all with a mapping on win9x */
|
||||
"open failed for modes map %x/%x/%x\n",
|
||||
mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
|
||||
ok( is_win9x, /* there's no sharing at all with a mapping on win9x */
|
||||
"open failed for modes map %x/%x/%x\n",
|
||||
mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
|
||||
ok( ret == ERROR_SHARING_VIOLATION,
|
||||
"wrong error code %d\n", ret );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]))
|
||||
todo_wine ok( broken(1), /* no checking on nt4 */
|
||||
ok( broken(1), /* no checking on nt4 */
|
||||
"open succeeded for modes map %x/%x/%x\n",
|
||||
mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
|
||||
ok( ret == 0xdeadbeef /* Win9x */ ||
|
||||
|
@ -1852,11 +1852,17 @@ static void test_file_sharing(void)
|
|||
h2 = CreateFileA( filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, CREATE_ALWAYS, 0, 0 );
|
||||
ret = GetLastError();
|
||||
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
|
||||
if ((mapping_modes[a1] & SEC_IMAGE) || is_win9x)
|
||||
{
|
||||
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
|
||||
ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
|
||||
}
|
||||
else todo_wine
|
||||
{
|
||||
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
|
||||
ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
|
||||
}
|
||||
if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
|
||||
|
||||
/* try DELETE_ON_CLOSE over an existing mapping */
|
||||
SetLastError(0xdeadbeef);
|
||||
|
@ -1868,12 +1874,12 @@ static void test_file_sharing(void)
|
|||
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
|
||||
ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
|
||||
}
|
||||
else if (mapping_modes[a1] & SEC_IMAGE)
|
||||
else if (mapping_modes[a1] & SEC_IMAGE) todo_wine
|
||||
{
|
||||
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
|
||||
todo_wine ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
|
||||
ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
|
||||
}
|
||||
else todo_wine
|
||||
else
|
||||
{
|
||||
ok( h2 != INVALID_HANDLE_VALUE, "open failed for map %x err %u\n", mapping_modes[a1], ret );
|
||||
}
|
||||
|
|
16
server/fd.c
16
server/fd.c
|
@ -1489,7 +1489,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
|
|||
}
|
||||
|
||||
/* duplicate an fd object for a different user */
|
||||
struct fd *dup_fd_object( struct fd *orig )
|
||||
struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing, unsigned int options )
|
||||
{
|
||||
struct fd *fd = alloc_object( &fd_ops );
|
||||
|
||||
|
@ -1499,9 +1499,9 @@ struct fd *dup_fd_object( struct fd *orig )
|
|||
fd->user = NULL;
|
||||
fd->inode = NULL;
|
||||
fd->closed = NULL;
|
||||
fd->access = orig->access;
|
||||
fd->options = orig->options;
|
||||
fd->sharing = orig->sharing;
|
||||
fd->access = access;
|
||||
fd->options = options;
|
||||
fd->sharing = sharing;
|
||||
fd->unix_fd = -1;
|
||||
fd->signaled = 0;
|
||||
fd->fs_locks = 0;
|
||||
|
@ -1555,8 +1555,6 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari
|
|||
unsigned int existing_access = 0;
|
||||
struct list *ptr;
|
||||
|
||||
/* if access mode is 0, sharing mode is ignored */
|
||||
if (!access) sharing = existing_sharing;
|
||||
fd->access = access;
|
||||
fd->sharing = sharing;
|
||||
|
||||
|
@ -1565,7 +1563,8 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari
|
|||
struct fd *fd_ptr = LIST_ENTRY( ptr, struct fd, inode_entry );
|
||||
if (fd_ptr != fd)
|
||||
{
|
||||
existing_sharing &= fd_ptr->sharing;
|
||||
/* if access mode is 0, sharing mode is ignored */
|
||||
if (fd_ptr->access) existing_sharing &= fd_ptr->sharing;
|
||||
existing_access |= fd_ptr->access;
|
||||
}
|
||||
}
|
||||
|
@ -1573,6 +1572,9 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari
|
|||
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_MAPPING_WRITE) && !(sharing & FILE_SHARE_WRITE)) return 0;
|
||||
if ((existing_access & FILE_MAPPING_IMAGE) && (access & FILE_SHARE_WRITE)) return 0;
|
||||
if (!access) return 1; /* if access mode is 0, sharing mode is ignored (except for mappings) */
|
||||
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 ((existing_access & DELETE) && !(sharing & FILE_SHARE_DELETE)) return 0;
|
||||
|
|
|
@ -58,7 +58,8 @@ extern struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned i
|
|||
unsigned int sharing, unsigned int options );
|
||||
extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
|
||||
int unix_fd, struct object *user, unsigned int options );
|
||||
extern struct fd *dup_fd_object( struct fd *orig );
|
||||
extern struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing,
|
||||
unsigned int options );
|
||||
extern void *get_fd_user( struct fd *fd );
|
||||
extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user );
|
||||
extern unsigned int get_fd_options( struct fd *fd );
|
||||
|
@ -158,4 +159,8 @@ extern void fd_copy_completion( struct fd *src, struct fd *dst );
|
|||
/* access rights that require Unix write permission */
|
||||
#define FILE_UNIX_WRITE_ACCESS (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
|
||||
|
||||
/* magic file access rights for mappings */
|
||||
#define FILE_MAPPING_IMAGE 0x80000000
|
||||
#define FILE_MAPPING_WRITE 0x40000000
|
||||
|
||||
#endif /* __WINE_SERVER_FILE_H */
|
||||
|
|
|
@ -457,6 +457,8 @@ static struct object *create_mapping( struct directory *root, const struct unico
|
|||
|
||||
if (handle)
|
||||
{
|
||||
unsigned int mapping_access = 0;
|
||||
|
||||
if (!(protect & VPROT_COMMITTED))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
|
@ -464,7 +466,13 @@ static struct object *create_mapping( struct directory *root, const struct unico
|
|||
}
|
||||
if (!(file = get_file_obj( current->process, handle, access ))) goto error;
|
||||
fd = get_obj_fd( (struct object *)file );
|
||||
mapping->fd = dup_fd_object( fd );
|
||||
|
||||
/* file sharing rules for mappings are different so we use magic the access rights */
|
||||
if (protect & VPROT_IMAGE) mapping_access |= FILE_MAPPING_IMAGE;
|
||||
else if (protect & VPROT_WRITE) mapping_access |= FILE_MAPPING_WRITE;
|
||||
mapping->fd = dup_fd_object( fd, mapping_access,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT );
|
||||
release_object( file );
|
||||
release_object( fd );
|
||||
if (!mapping->fd) goto error;
|
||||
|
|
Loading…
Reference in New Issue