[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