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

Alexandre Julliard julliard at winehq.org
Tue Nov 24 12:40:20 CST 2009


Module: wine
Branch: master
Commit: 923d582f0769af65dc79bf6cad884e96989c8915
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=923d582f0769af65dc79bf6cad884e96989c8915

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Nov 23 17:24:09 2009 +0100

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

---

 dlls/kernel32/tests/file.c |   12 +++++-------
 server/fd.c                |   33 ++++++++++++++++++++-------------
 server/file.h              |    5 +++--
 server/mapping.c           |    2 +-
 server/trace.c             |    1 +
 5 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index dc95f63..35ca3c6 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -649,12 +649,10 @@ static void test_CopyFileA(void)
     ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
 
     ret = CopyFileA(source, dest, FALSE);
-    todo_wine {
-        ok(!ret, "CopyFileA: expected failure\n");
-        ok(GetLastError() == ERROR_USER_MAPPED_FILE ||
-           broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x and WinMe */
-           "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
-    }
+    ok(!ret, "CopyFileA: expected failure\n");
+    ok(GetLastError() == ERROR_USER_MAPPED_FILE ||
+       broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x */
+       "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
 
     CloseHandle(hmapfile);
     CloseHandle(hfile);
@@ -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( 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( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
diff --git a/server/fd.c b/server/fd.c
index 7d15138..ee1a9d3 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1549,7 +1549,8 @@ void set_no_fd_status( struct fd *fd, unsigned int status )
 
 /* check if the desired access is possible without violating */
 /* 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_access = 0;
@@ -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_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;
-    return 1;
+    if (((access & FILE_UNIX_READ_ACCESS) && !(existing_sharing & FILE_SHARE_READ)) ||
+        ((access & FILE_UNIX_WRITE_ACCESS) && !(existing_sharing & FILE_SHARE_WRITE)) ||
+        ((access & DELETE) && !(existing_sharing & FILE_SHARE_DELETE)))
+        return STATUS_SHARING_VIOLATION;
+    if (((existing_access & FILE_MAPPING_WRITE) && !(sharing & FILE_SHARE_WRITE)) ||
+        ((existing_access & FILE_MAPPING_IMAGE) && (access & FILE_SHARE_WRITE)))
+        return STATUS_SHARING_VIOLATION;
+    if ((existing_access & FILE_MAPPING_ACCESS) && (open_flags & O_TRUNC))
+        return STATUS_USER_MAPPED_FILE;
+    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 */
@@ -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 */
     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 );
 
         if (!inode)
@@ -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 );
             return NULL;
         }
-        if (!check_sharing( fd, access, sharing ))
+        if ((err = check_sharing( fd, access, sharing, flags, options )))
         {
             release_object( fd );
-            set_error( STATUS_SHARING_VIOLATION );
+            set_error( err );
             return NULL;
         }
         strcpy( closed_fd->unlink, unlink_name );
diff --git a/server/file.h b/server/file.h
index 91dd034..a49fc4d 100644
--- a/server/file.h
+++ b/server/file.h
@@ -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)
 
 /* magic file access rights for mappings */
-#define FILE_MAPPING_IMAGE  0x80000000
-#define FILE_MAPPING_WRITE  0x40000000
+#define FILE_MAPPING_IMAGE  0x80000000  /* set for SEC_IMAGE mappings */
+#define FILE_MAPPING_WRITE  0x40000000  /* set for writable shared mappings */
+#define FILE_MAPPING_ACCESS 0x20000000  /* set for all mappings */
 
 #endif  /* __WINE_SERVER_FILE_H */
diff --git a/server/mapping.c b/server/mapping.c
index d8bc527..1cf53b9 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -457,7 +457,7 @@ static struct object *create_mapping( struct directory *root, const struct unico
 
     if (handle)
     {
-        unsigned int mapping_access = 0;
+        unsigned int mapping_access = FILE_MAPPING_ACCESS;
 
         if (!(protect & VPROT_COMMITTED))
         {
diff --git a/server/trace.c b/server/trace.c
index a4b1faa..6c503f9 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -4629,6 +4629,7 @@ static const struct
     { "TOO_MANY_OPENED_FILES",       STATUS_TOO_MANY_OPENED_FILES },
     { "UNSUCCESSFUL",                STATUS_UNSUCCESSFUL },
     { "USER_APC",                    STATUS_USER_APC },
+    { "USER_MAPPED_FILE",            STATUS_USER_MAPPED_FILE },
     { "VOLUME_DISMOUNTED",           STATUS_VOLUME_DISMOUNTED },
     { "WAS_LOCKED",                  STATUS_WAS_LOCKED },
     { NULL, 0 }




More information about the wine-cvs mailing list