diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c index 18da18d851b..8b92f1bd42c 100644 --- a/dlls/ntdll/om.c +++ b/dlls/ntdll/om.c @@ -332,16 +332,11 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, if (!(ret = wine_server_call( req ))) { if (dest) *dest = wine_server_ptr_handle( reply->handle ); - if (reply->closed) + if (reply->closed && reply->self) { - if (reply->self) - { - int fd = server_remove_fd_from_cache( source ); - if (fd != -1) close( fd ); - } + int fd = server_remove_fd_from_cache( source ); + if (fd != -1) close( fd ); } - else if (options & DUPLICATE_CLOSE_SOURCE) - WARN( "failed to close handle %p in process %p\n", source, source_process ); } } SERVER_END_REQ; diff --git a/server/handle.c b/server/handle.c index 1d8087bbaa5..28c49c2d181 100644 --- a/server/handle.c +++ b/server/handle.c @@ -531,6 +531,13 @@ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, str { if (options & DUP_HANDLE_MAKE_GLOBAL) res = alloc_global_handle_no_access_check( obj, access ); + else if ((options & DUP_HANDLE_CLOSE_SOURCE) && src == dst && + entry && !(entry->access & RESERVED_CLOSE_PROTECT)) + { + if (attr & OBJ_INHERIT) access |= RESERVED_INHERIT; + entry->access = access; + res = src_handle; + } else res = alloc_handle_no_access_check( dst, obj, access, attr ); } @@ -581,7 +588,7 @@ DECL_HANDLER(set_handle_info) /* duplicate a handle */ DECL_HANDLER(dup_handle) { - struct process *src, *dst; + struct process *src, *dst = NULL; reply->handle = 0; if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE ))) @@ -598,7 +605,8 @@ DECL_HANDLER(dup_handle) release_object( dst ); } /* close the handle no matter what happened */ - if (req->options & DUP_HANDLE_CLOSE_SOURCE) reply->closed = !close_handle( src, req->src_handle ); + if ((req->options & DUP_HANDLE_CLOSE_SOURCE) && (src != dst || req->src_handle != reply->handle)) + reply->closed = !close_handle( src, req->src_handle ); reply->self = (src == current->process); release_object( src ); }