diff --git a/server/async.c b/server/async.c
index 7978a9089952cd4aee55e6b28967ba0b47da2150..fb722bc7468260566f36679e17df206f76abb58b 100644
--- a/server/async.c
+++ b/server/async.c
@@ -117,7 +117,7 @@ static int async_get_fd( struct object *obj )
 {
     struct async *async = (struct async *)obj;
     assert( obj->ops == &async_ops );
-    return dup( async->obj.fd );
+    return async->obj.fd;
 }
 
 static int async_get_info( struct object *obj, struct get_file_info_request *req ) {
diff --git a/server/console.c b/server/console.c
index dcdc28722ebced4c567241ab2e85c70852abd182..7454c9ac394d43d7590c5dc166642e0bb4d21909 100644
--- a/server/console.c
+++ b/server/console.c
@@ -354,7 +354,7 @@ static int console_input_get_fd( struct object *obj )
 {
     struct console_input *console = (struct console_input *)obj;
     assert( obj->ops == &console_input_ops );
-    return dup( console->obj.fd );
+    return console->obj.fd;
 }
 
 static int console_get_info( struct object *obj, struct get_file_info_request *req )
@@ -395,7 +395,7 @@ static int screen_buffer_get_fd( struct object *obj )
 {
     struct screen_buffer *console = (struct screen_buffer *)obj;
     assert( obj->ops == &screen_buffer_ops );
-    return dup( console->obj.fd );
+    return console->obj.fd;
 }
 
 static void screen_buffer_destroy( struct object *obj )
@@ -481,7 +481,7 @@ DECL_HANDLER(set_console_fd)
 
     if (!(obj = get_handle_obj( current->process, req->file_handle,
                                 GENERIC_READ | GENERIC_WRITE, NULL ))) return;
-    if ((fd_in = obj->ops->get_fd( obj )) == -1)
+    if ((fd_in = dup(obj->ops->get_fd( obj ))) == -1)
     {
         release_object( obj );
         return;
diff --git a/server/file.c b/server/file.c
index e0ce8a762858087b44c8f072baad839e92b9a3de..0c8aaae3792c0548a7d61525b88b1c980ed3c59b 100644
--- a/server/file.c
+++ b/server/file.c
@@ -235,7 +235,7 @@ static int file_get_fd( struct object *obj )
 {
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
-    return dup( file->obj.fd );
+    return file->obj.fd;
 }
 
 static int file_flush( struct object *obj )
@@ -474,8 +474,13 @@ DECL_HANDLER(get_handle_fd)
     req->fd = -1;
     if ((obj = get_handle_obj( current->process, req->handle, req->access, NULL )))
     {
-        if ((req->fd = get_handle_fd( current->process, req->handle, req->access )) == -1)
-            send_client_fd( current, obj->ops->get_fd( obj ), req->handle );
+        int fd = get_handle_fd( current->process, req->handle, req->access );
+        if (fd != -1) req->fd = fd;
+        else if (!get_error())
+        {
+            if ((fd = obj->ops->get_fd( obj )) != -1)
+                send_client_fd( current, fd, req->handle );
+        }
         release_object( obj );
     }
 }
diff --git a/server/handle.c b/server/handle.c
index 6a3e1f613c35a314ff77aa30a21019b560dc540c..c3b8a05071a729d8421483486abd19bb73e37462 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -362,7 +362,6 @@ int get_handle_fd( struct process *process, int handle, unsigned int access )
 {
     struct handle_entry *entry;
 
-    if (HANDLE_IS_GLOBAL(handle)) return -1;  /* no fd cache for global handles */
     if (!(entry = get_handle( process, handle ))) return -1;
     if ((entry->access & access) != access)
     {
diff --git a/server/mapping.c b/server/mapping.c
index 38d1d899befc7e29d47e59e16f40200b0a48bdd7..43a67d8aaef4ace9b1b3d504b2a56bf0aaa71062 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -91,7 +91,11 @@ static void init_page_size(void)
 inline static int get_mmap_fd( struct file *file )
 {
     struct object *obj;
-    if (!(obj = (struct object *)file)) return -1;
+    if (!(obj = (struct object *)file))
+    {
+        set_error( STATUS_INVALID_HANDLE );
+        return -1;
+    }
     return obj->ops->get_fd( obj );
 }
 
@@ -100,8 +104,8 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
                                  IMAGE_SECTION_HEADER *sec, int nb_sec )
 {
     int i, max_size, total_size, pos;
-    char *buffer = NULL; 
-    int shared_fd = -1;
+    char *buffer = NULL;
+    int shared_fd;
     long toread;
 
     /* compute the total size of the shared mapping */
@@ -147,12 +151,10 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
         }
         if (write( shared_fd, buffer, sec[i].SizeOfRawData ) != sec[i].SizeOfRawData) goto error;
     }
-    close( shared_fd );
     free( buffer );
     return 1;
 
  error:
-    if (shared_fd != -1) close( shared_fd );
     if (buffer) free( buffer );
     return 0;
 }
@@ -193,13 +195,11 @@ static int get_image_params( struct mapping *mapping )
     if (mapping->header_size > mapping->size_low) goto error;
 
     lseek( fd, filepos, SEEK_SET );
-    close( fd );
     free( sec );
     return 1;
 
  error:
     lseek( fd, filepos, SEEK_SET );
-    close( fd );
     if (sec) free( sec );
     set_error( STATUS_INVALID_FILE_FOR_SECTION );
     return 0;
diff --git a/server/pipe.c b/server/pipe.c
index 7838c12caf5ef07d14bf95aebbfa66989a95b656..47dfb61a1a2a254c439beb55baa98c53e6d72122 100644
--- a/server/pipe.c
+++ b/server/pipe.c
@@ -122,7 +122,7 @@ static int pipe_get_fd( struct object *obj )
         set_error( STATUS_PIPE_BROKEN );
         return -1;
     }
-    return dup( pipe->obj.fd );
+    return pipe->obj.fd;
 }
 
 static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
diff --git a/server/registry.c b/server/registry.c
index af7ba8a051004f8c6f1b055bbd5b6a35fa084cd3..4fa5a4ebf4ca19f48d5f1b30e73f524c7fc48928 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -1340,7 +1340,7 @@ static void load_registry( struct key *key, int handle )
     int fd;
 
     if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL ))) return;
-    fd = obj->ops->get_fd( obj );
+    fd = dup(obj->ops->get_fd( obj ));
     release_object( obj );
     if (fd != -1)
     {
@@ -1435,7 +1435,7 @@ static void save_registry( struct key *key, int handle )
         return;
     }
     if (!(obj = get_handle_obj( current->process, handle, GENERIC_WRITE, NULL ))) return;
-    fd = obj->ops->get_fd( obj );
+    fd = dup(obj->ops->get_fd( obj ));
     release_object( obj );
     if (fd != -1)
     {
diff --git a/server/request.c b/server/request.c
index fff02dd4531ad52add279c5c610d555a3dc5e0bf..7a8498bbe197a5f61dd9fb0e977257e9b5e31707 100644
--- a/server/request.c
+++ b/server/request.c
@@ -259,6 +259,9 @@ int send_client_fd( struct thread *thread, int fd, int handle )
 {
     int ret;
 
+    if (debug_level)
+        fprintf( stderr, "%08x: *fd* %d = %d\n", (unsigned int)thread, handle, fd );
+
 #ifdef HAVE_MSGHDR_ACCRIGHTS
     msghdr.msg_accrightslen = sizeof(fd);
     msghdr.msg_accrights = (void *)&fd;
@@ -272,7 +275,6 @@ int send_client_fd( struct thread *thread, int fd, int handle )
     myiovec.iov_len  = sizeof(handle);
 
     ret = sendmsg( thread->obj.fd, &msghdr, 0 );
-    close( fd );
 
     if (ret > 0) return 0;
     if (errno == EPIPE)
@@ -381,6 +383,7 @@ struct object *create_request_socket( struct thread *thread )
     }
     sock->thread = thread;
     send_client_fd( thread, fd[1], -1 );
+    close( fd[1] );
     set_select_events( &sock->obj, POLLIN );
     return &sock->obj;
 }
diff --git a/server/serial.c b/server/serial.c
index 7d30d4dc957c4d1ad7ed7f9c863ec41344658706..f32f8a3eb7d4db5f5c0b4abb3670ff0299f337e3 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -154,7 +154,7 @@ static int serial_get_fd( struct object *obj )
 {
     struct serial *serial = (struct serial *)obj;
     assert( obj->ops == &serial_ops );
-    return dup( serial->obj.fd );
+    return serial->obj.fd;
 }
 
 static int serial_get_info( struct object *obj, struct get_file_info_request *req )
diff --git a/server/sock.c b/server/sock.c
index c5f41e4f0d5ae3a35a4ab56e3357d54337a5f61a..ec7a0676d64f4e481f63ed246b1d6ef1326775bb 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -255,12 +255,8 @@ static int sock_get_poll_events( struct object *obj )
 static int sock_get_fd( struct object *obj )
 {
     struct sock *sock = (struct sock *)obj;
-    int fd;
     assert( obj->ops == &sock_ops );
-    fd = dup( sock->obj.fd );
-    if (fd==-1)
-    	sock_set_error();
-    return fd;
+    return sock->obj.fd;
 }
 
 static void sock_destroy( struct object *obj )
diff --git a/server/thread.c b/server/thread.c
index 12e937716e1603299705a06c409f3b9709339921..272614068f4fbbc04adee0d9fe2e10eeefd98c15 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -109,6 +109,8 @@ static int alloc_client_buffer( struct thread *thread )
     send_client_fd( thread, fd_pipe[0], -1 );
     send_client_fd( thread, fd, -1 );
     send_reply( thread );
+    close( fd_pipe[0] );
+    close( fd );
     return 1;
 
  error:
@@ -691,6 +693,7 @@ DECL_HANDLER(new_thread)
                                              THREAD_ALL_ACCESS, req->inherit )) != -1)
             {
                 send_client_fd( current, sock[1], req->handle );
+                close( sock[1] );
                 /* thread object will be released when the thread gets killed */
                 add_process_thread( current->process, thread );
                 return;