[PATCH 3/3] server: Fail when creating an existing file without write permission.

Daniel Lehman dlehman25 at gmail.com
Fri Oct 23 00:53:16 CDT 2020


Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---
 dlls/kernel32/tests/file.c |  5 +----
 dlls/ntdll/tests/file.c    |  3 +--
 server/fd.c                | 19 ++++++++++++++-----
 server/file.c              |  2 +-
 server/file.h              |  2 ++
 5 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index cc7a518b9c3..ffa1d3e2e32 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -4116,15 +4116,12 @@ todo_wine_if (i == 1)
         SetLastError(0xdeadbeef);
         hfile2 = CreateFileA(file_name, td2[i].access, td2[i].share2 ? td2[i].share2 : td2[i].share,
                              NULL, td2[i].disposition, 0, 0);
-todo_wine_if(i == 1 || i == 18 || i == 19)
+todo_wine_if(i == 18 || i == 19)
         ok(GetLastError() == td2[i].error, "%d: expected %d, got %d\n", i, td2[i].error, GetLastError());
-todo_wine_if(i == 1 || i == 19)
-{
         if (td2[i].error && (td2[i].error != ERROR_ALREADY_EXISTS))
             ok(hfile2 == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
         else
             ok(hfile2 != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError());
-}
         if (hfile2 != INVALID_HANDLE_VALUE)
             CloseHandle(hfile2);
         CloseHandle(hfile);
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 5e956d8a66c..bc369ee9354 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -4117,11 +4117,10 @@ static void test_NtCreateFile(void)
                                FILE_ATTRIBUTE_NORMAL, td2[i].share2 ? td2[i].share2 : td2[i].share,
                                td2[i].disposition, 0, NULL, 0);
 
-        todo_wine_if(i == 1 || i == 19 || i == 24 || i == 26)
+        todo_wine_if(i == 24 || i == 26)
         ok(status == td2[i].status, "%d: expected %#x got %#x\n", i, td2[i].status, status);
         if (!status)
         {
-            todo_wine_if(i == 1 || i == 19)
             ok(io.Information == td2[i].result,"%d: expected %#x got %#lx\n", i, td2[i].result, io.Information);
             CloseHandle(handle2);
         }
diff --git a/server/fd.c b/server/fd.c
index edb59b0d540..a4cd633ae04 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1585,7 +1585,7 @@ static void fd_destroy( struct object *obj )
 /* check if the desired access is possible without violating */
 /* the sharing mode of other opens of the same file */
 static unsigned int check_sharing( struct fd *fd, unsigned int access, unsigned int sharing,
-                                   unsigned int open_flags, unsigned int options )
+                                   unsigned int open_flags, unsigned int options, int create )
 {
     /* only a few access bits are meaningful wrt sharing */
     const unsigned int read_access = FILE_READ_DATA | FILE_EXECUTE;
@@ -1627,6 +1627,9 @@ static unsigned int check_sharing( struct fd *fd, unsigned int access, unsigned
         ((existing_access & write_access) && !(sharing & FILE_SHARE_WRITE)) ||
         ((existing_access & DELETE) && !(sharing & FILE_SHARE_DELETE)))
         return STATUS_SHARING_VIOLATION;
+    if ((create == FILE_OVERWRITE_IF || create == FILE_OVERWRITE) &&
+        !(existing_sharing & FILE_SHARE_WRITE))
+        return STATUS_SHARING_VIOLATION;
     return 0;
 }
 
@@ -1772,7 +1775,7 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha
         fd->closed = closed;
         fd->inode = (struct inode *)grab_object( orig->inode );
         list_add_head( &fd->inode->open, &fd->inode_entry );
-        if ((err = check_sharing( fd, access, sharing, 0, options )))
+        if ((err = check_sharing( fd, access, sharing, 0, options, -1 )))
         {
             set_error( err );
             goto failed;
@@ -1831,9 +1834,15 @@ char *dup_fd_name( struct fd *root, const char *name )
     return ret;
 }
 
+struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
+                           unsigned int access, unsigned int sharing, unsigned int options )
+{
+    return open_fd2( root, name, flags, mode, access, sharing, options, -1 );
+}
+
 /* open() wrapper that returns a struct fd with no fd user set */
-struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode, unsigned int access,
-                    unsigned int sharing, unsigned int options )
+struct fd *open_fd2( struct fd *root, const char *name, int flags, mode_t *mode, unsigned int access,
+                     unsigned int sharing, unsigned int options, int create )
 {
     struct stat st;
     struct closed_fd *closed_fd;
@@ -1949,7 +1958,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
             set_error( STATUS_FILE_IS_A_DIRECTORY );
             goto error;
         }
-        if ((err = check_sharing( fd, access, sharing, flags, options )))
+        if ((err = check_sharing( fd, access, sharing, flags, options, create )))
         {
             set_error( err );
             goto error;
diff --git a/server/file.c b/server/file.c
index 4690af2424e..9cdc8f31a85 100644
--- a/server/file.c
+++ b/server/file.c
@@ -255,7 +255,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
     access = generic_file_map_access( access );
 
     /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
-    fd = open_fd( root, name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options );
+    fd = open_fd2( root, name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options, create );
     if (!fd) goto done;
 
     if (S_ISDIR(mode))
diff --git a/server/file.h b/server/file.h
index 2fb634fad8d..48fea7de816 100644
--- a/server/file.h
+++ b/server/file.h
@@ -80,6 +80,8 @@ extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct obje
                                    unsigned int options );
 extern struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
                            unsigned int access, unsigned int sharing, unsigned int options );
+extern struct fd *open_fd2( struct fd *root, const char *name, int flags, mode_t *mode,
+                            unsigned int access, unsigned int sharing, unsigned int options, int create );
 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, unsigned int access, unsigned int sharing,
-- 
2.25.1




More information about the wine-devel mailing list