Commit 923d582f authored by Alexandre Julliard's avatar Alexandre Julliard

server: Implement the file sharing check when truncating a file that has an existing mapping.

parent fd504b62
...@@ -649,12 +649,10 @@ static void test_CopyFileA(void) ...@@ -649,12 +649,10 @@ static void test_CopyFileA(void)
ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
ret = CopyFileA(source, dest, FALSE); ret = CopyFileA(source, dest, FALSE);
todo_wine { ok(!ret, "CopyFileA: expected failure\n");
ok(!ret, "CopyFileA: expected failure\n"); ok(GetLastError() == ERROR_USER_MAPPED_FILE ||
ok(GetLastError() == ERROR_USER_MAPPED_FILE || broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x */
broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x and WinMe */ "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
"CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
}
CloseHandle(hmapfile); CloseHandle(hmapfile);
CloseHandle(hfile); CloseHandle(hfile);
...@@ -1857,7 +1855,7 @@ static void test_file_sharing(void) ...@@ -1857,7 +1855,7 @@ static void test_file_sharing(void)
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] ); 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] ); ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
} }
else todo_wine else
{ {
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] ); 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] ); ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
......
...@@ -1549,7 +1549,8 @@ void set_no_fd_status( struct fd *fd, unsigned int status ) ...@@ -1549,7 +1549,8 @@ void set_no_fd_status( struct fd *fd, unsigned int status )
/* check if the desired access is possible without violating */ /* check if the desired access is possible without violating */
/* the sharing mode of other opens of the same file */ /* the sharing mode of other opens of the same file */
static int check_sharing( struct fd *fd, unsigned int access, unsigned int sharing ) static unsigned int check_sharing( struct fd *fd, unsigned int access, unsigned int sharing,
unsigned int open_flags, unsigned int options )
{ {
unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
unsigned int existing_access = 0; unsigned int existing_access = 0;
...@@ -1569,16 +1570,21 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari ...@@ -1569,16 +1570,21 @@ 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_READ_ACCESS) && !(existing_sharing & FILE_SHARE_READ)) ||
if ((access & FILE_UNIX_WRITE_ACCESS) && !(existing_sharing & FILE_SHARE_WRITE)) return 0; ((access & FILE_UNIX_WRITE_ACCESS) && !(existing_sharing & FILE_SHARE_WRITE)) ||
if ((access & DELETE) && !(existing_sharing & FILE_SHARE_DELETE)) return 0; ((access & DELETE) && !(existing_sharing & FILE_SHARE_DELETE)))
if ((existing_access & FILE_MAPPING_WRITE) && !(sharing & FILE_SHARE_WRITE)) return 0; return STATUS_SHARING_VIOLATION;
if ((existing_access & FILE_MAPPING_IMAGE) && (access & FILE_SHARE_WRITE)) return 0; if (((existing_access & FILE_MAPPING_WRITE) && !(sharing & FILE_SHARE_WRITE)) ||
if (!access) return 1; /* if access mode is 0, sharing mode is ignored (except for mappings) */ ((existing_access & FILE_MAPPING_IMAGE) && (access & FILE_SHARE_WRITE)))
if ((existing_access & FILE_UNIX_READ_ACCESS) && !(sharing & FILE_SHARE_READ)) return 0; return STATUS_SHARING_VIOLATION;
if ((existing_access & FILE_UNIX_WRITE_ACCESS) && !(sharing & FILE_SHARE_WRITE)) return 0; if ((existing_access & FILE_MAPPING_ACCESS) && (open_flags & O_TRUNC))
if ((existing_access & DELETE) && !(sharing & FILE_SHARE_DELETE)) return 0; return STATUS_USER_MAPPED_FILE;
return 1; if (!access) return 0; /* if access mode is 0, sharing mode is ignored (except for mappings) */
if (((existing_access & FILE_UNIX_READ_ACCESS) && !(sharing & FILE_SHARE_READ)) ||
((existing_access & FILE_UNIX_WRITE_ACCESS) && !(sharing & FILE_SHARE_WRITE)) ||
((existing_access & DELETE) && !(sharing & FILE_SHARE_DELETE)))
return STATUS_SHARING_VIOLATION;
return 0;
} }
/* sets the user of an fd that previously had no user */ /* sets the user of an fd that previously had no user */
...@@ -1659,6 +1665,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce ...@@ -1659,6 +1665,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
/* only bother with an inode for normal files and directories */ /* only bother with an inode for normal files and directories */
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
{ {
unsigned int err;
struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd ); struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd );
if (!inode) if (!inode)
...@@ -1685,10 +1692,10 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce ...@@ -1685,10 +1692,10 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
set_error( STATUS_FILE_IS_A_DIRECTORY ); set_error( STATUS_FILE_IS_A_DIRECTORY );
return NULL; return NULL;
} }
if (!check_sharing( fd, access, sharing )) if ((err = check_sharing( fd, access, sharing, flags, options )))
{ {
release_object( fd ); release_object( fd );
set_error( STATUS_SHARING_VIOLATION ); set_error( err );
return NULL; return NULL;
} }
strcpy( closed_fd->unlink, unlink_name ); strcpy( closed_fd->unlink, unlink_name );
......
...@@ -160,7 +160,8 @@ extern void fd_copy_completion( struct fd *src, struct fd *dst ); ...@@ -160,7 +160,8 @@ extern void fd_copy_completion( struct fd *src, struct fd *dst );
#define FILE_UNIX_WRITE_ACCESS (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA) #define FILE_UNIX_WRITE_ACCESS (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
/* magic file access rights for mappings */ /* magic file access rights for mappings */
#define FILE_MAPPING_IMAGE 0x80000000 #define FILE_MAPPING_IMAGE 0x80000000 /* set for SEC_IMAGE mappings */
#define FILE_MAPPING_WRITE 0x40000000 #define FILE_MAPPING_WRITE 0x40000000 /* set for writable shared mappings */
#define FILE_MAPPING_ACCESS 0x20000000 /* set for all mappings */
#endif /* __WINE_SERVER_FILE_H */ #endif /* __WINE_SERVER_FILE_H */
...@@ -457,7 +457,7 @@ static struct object *create_mapping( struct directory *root, const struct unico ...@@ -457,7 +457,7 @@ static struct object *create_mapping( struct directory *root, const struct unico
if (handle) if (handle)
{ {
unsigned int mapping_access = 0; unsigned int mapping_access = FILE_MAPPING_ACCESS;
if (!(protect & VPROT_COMMITTED)) if (!(protect & VPROT_COMMITTED))
{ {
......
...@@ -4629,6 +4629,7 @@ static const struct ...@@ -4629,6 +4629,7 @@ static const struct
{ "TOO_MANY_OPENED_FILES", STATUS_TOO_MANY_OPENED_FILES }, { "TOO_MANY_OPENED_FILES", STATUS_TOO_MANY_OPENED_FILES },
{ "UNSUCCESSFUL", STATUS_UNSUCCESSFUL }, { "UNSUCCESSFUL", STATUS_UNSUCCESSFUL },
{ "USER_APC", STATUS_USER_APC }, { "USER_APC", STATUS_USER_APC },
{ "USER_MAPPED_FILE", STATUS_USER_MAPPED_FILE },
{ "VOLUME_DISMOUNTED", STATUS_VOLUME_DISMOUNTED }, { "VOLUME_DISMOUNTED", STATUS_VOLUME_DISMOUNTED },
{ "WAS_LOCKED", STATUS_WAS_LOCKED }, { "WAS_LOCKED", STATUS_WAS_LOCKED },
{ NULL, 0 } { NULL, 0 }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment