Signed-off-by: Daniel Lehman dlehman25@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,