From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/ntdll/tests/file.c | 6 ------ server/fd.c | 13 ++++++++++++- 2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index ba6e8564968..e06a25338b2 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -3021,7 +3021,6 @@ static void test_file_disposition_information(void) ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res ); /* can't open the deleted file */ handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); - todo_wine ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); if (handle3 != INVALID_HANDLE_VALUE) CloseHandle( handle3 ); @@ -3158,9 +3157,7 @@ static void test_file_disposition_information(void) ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res ); /* can't open the deleted file */ handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); - todo_wine ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); - todo_wine ok( GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError()); if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2); @@ -3214,9 +3211,7 @@ static void test_file_disposition_information(void) ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res ); /* can't open the deleted directory */ handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); - todo_wine ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); - todo_wine ok(GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError()); if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2 ); CloseHandle( handle ); @@ -3239,7 +3234,6 @@ static void test_file_disposition_information(void) ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res ); /* can't open the deleted directory */ handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); - todo_wine ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); if (handle3 != INVALID_HANDLE_VALUE) CloseHandle( handle3 ); diff --git a/server/fd.c b/server/fd.c index 292850682fd..cf6bbb1eae9 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1133,6 +1133,10 @@ static void inode_close_pending( struct inode *inode, int keep_unlinks ) } }
+/* returns: + * bit0-1 or'ed unlink value of all open & closed fd + * bit2-3 or'ed unlink value of all closed fd only + */ static unsigned int inode_propagate_unlink( struct fd *fd, unsigned or_mask, unsigned and_mask ) { struct list *ptr; @@ -1153,7 +1157,7 @@ static unsigned int inode_propagate_unlink( struct fd *fd, unsigned or_mask, uns struct closed_fd *closed_fd = LIST_ENTRY( ptr, struct closed_fd, entry ); if (closed_fd->unix_name && fd->unix_name && !strcmp(closed_fd->unix_name, fd->unix_name)) { - unlink |= closed_fd->unlink; + unlink |= closed_fd->unlink | (closed_fd->unlink << 2); closed_fd->unlink |= or_mask; closed_fd->unlink &= ~and_mask; } @@ -2057,6 +2061,13 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
/* get existing unlink value from open/closed fd */ fd->closed->unlink = inode_propagate_unlink( fd, 0, 0 ); + /* either unlink=delete-on-close in closed fd, or unlink=disposition in any fd */ + if (fd->closed->unlink & 6) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + goto error; + } + fd->closed->unlink &= 3; if (flags & O_TRUNC) { if (S_ISDIR(st.st_mode))