From b9b1ea9c9fcdda794790c2102c36e04d62042cc3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 9 Jun 2005 15:39:52 +0000 Subject: [PATCH] Added a close_handle method to the object operations, and use it to implement registry notifications and the strange behavior of CloseHandle on winstation/desktop handles. --- dlls/user/tests/winstation.c | 30 +++++++------------- server/atom.c | 1 + server/change.c | 1 + server/console.c | 3 ++ server/debugger.c | 2 ++ server/event.c | 1 + server/fd.c | 3 ++ server/file.c | 1 + server/handle.c | 8 ++++-- server/hook.c | 1 + server/mailslot.c | 2 ++ server/mapping.c | 1 + server/mutex.c | 1 + server/named_pipe.c | 3 ++ server/object.c | 5 ++++ server/object.h | 4 ++- server/process.c | 4 ++- server/queue.c | 2 ++ server/registry.c | 15 ++++------ server/request.c | 1 + server/semaphore.c | 1 + server/serial.c | 1 + server/signal.c | 1 + server/snapshot.c | 1 + server/sock.c | 1 + server/thread.c | 1 + server/timer.c | 1 + server/token.c | 1 + server/winstation.c | 55 ++++++++++++++++-------------------- 29 files changed, 89 insertions(+), 63 deletions(-) diff --git a/dlls/user/tests/winstation.c b/dlls/user/tests/winstation.c index 2855448d2b7..5ce2d72dd0b 100644 --- a/dlls/user/tests/winstation.c +++ b/dlls/user/tests/winstation.c @@ -53,13 +53,9 @@ static DWORD CALLBACK thread( LPVOID arg ) trace( "thread %p desktop: %p\n", arg, d1 ); ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg ); - if (0) /* FIXME: this should be todo_wine but it would break the rest of the test */ - { - SetLastError( 0xdeadbeef ); - ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() ); - } - + SetLastError( 0xdeadbeef ); + ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() ); SetLastError( 0xdeadbeef ); ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" ); ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() ); @@ -109,7 +105,7 @@ static void test_handles(void) flags = 0; ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" ); - todo_wine ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", w1 ); + ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", w1 ); ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); @@ -165,12 +161,9 @@ static void test_handles(void) ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" ); ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() ); - if (0) /* FIXME: this should be todo_wine but it would break the rest of the test */ - { - SetLastError( 0xdeadbeef ); - ok( !CloseHandle(d1), "closing thread desktop handle failed\n" ); - ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() ); - } + SetLastError( 0xdeadbeef ); + ok( !CloseHandle(d1), "closing thread desktop handle failed\n" ); + ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() ); ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); @@ -198,12 +191,9 @@ static void test_handles(void) d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS ); ok( !d3, "open foobar desktop succeeded\n" ); - if (0) /* FIXME: this should be todo_wine but it would break the rest of the test */ - { - ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" ); - d2 = GetThreadDesktop(GetCurrentThreadId()); - ok( d1 == d2, "got different handles after close\n" ); - } + ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" ); + d2 = GetThreadDesktop(GetCurrentThreadId()); + ok( d1 == d2, "got different handles after close\n" ); trace( "thread 1 desktop: %p\n", d1 ); print_object( d1 ); diff --git a/server/atom.c b/server/atom.c index 52797cac650..b1291d3dee8 100644 --- a/server/atom.c +++ b/server/atom.c @@ -76,6 +76,7 @@ static const struct object_ops atom_table_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ atom_table_destroy /* destroy */ }; diff --git a/server/change.c b/server/change.c index 51867dd7ab9..5ccdfb83742 100644 --- a/server/change.c +++ b/server/change.c @@ -73,6 +73,7 @@ static const struct object_ops change_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ change_destroy /* destroy */ }; diff --git a/server/console.c b/server/console.c index cc574185a59..871a66ebb49 100644 --- a/server/console.c +++ b/server/console.c @@ -48,6 +48,7 @@ static const struct object_ops console_input_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ console_input_destroy /* destroy */ }; @@ -73,6 +74,7 @@ static const struct object_ops console_input_events_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ console_input_events_destroy /* destroy */ }; @@ -109,6 +111,7 @@ static const struct object_ops screen_buffer_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ screen_buffer_destroy /* destroy */ }; diff --git a/server/debugger.c b/server/debugger.c index b1ba9b15c49..e8fbb0c47f3 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -74,6 +74,7 @@ static const struct object_ops debug_event_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ debug_event_destroy /* destroy */ }; @@ -91,6 +92,7 @@ static const struct object_ops debug_ctx_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ debug_ctx_destroy /* destroy */ }; diff --git a/server/event.c b/server/event.c index fa1dbbfba2c..3445185aeb5 100644 --- a/server/event.c +++ b/server/event.c @@ -53,6 +53,7 @@ static const struct object_ops event_ops = event_satisfied, /* satisfied */ event_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/fd.c b/server/fd.c index 797f77f0df5..d3143cd8f20 100644 --- a/server/fd.c +++ b/server/fd.c @@ -163,6 +163,7 @@ static const struct object_ops fd_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ fd_destroy /* destroy */ }; @@ -193,6 +194,7 @@ static const struct object_ops inode_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ inode_destroy /* destroy */ }; @@ -224,6 +226,7 @@ static const struct object_ops file_lock_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/file.c b/server/file.c index dd38e19e9e2..9000b61ef38 100644 --- a/server/file.c +++ b/server/file.c @@ -80,6 +80,7 @@ static const struct object_ops file_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ file_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ file_destroy /* destroy */ }; diff --git a/server/handle.c b/server/handle.c index efcbe27bcd1..4a708439406 100644 --- a/server/handle.c +++ b/server/handle.c @@ -108,6 +108,7 @@ static const struct object_ops handle_table_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ handle_table_destroy /* destroy */ }; @@ -323,6 +324,11 @@ int close_handle( struct process *process, obj_handle_t handle, int *fd ) return 0; } obj = entry->ptr; + if (!obj->ops->close_handle( obj, process, handle )) + { + set_error( STATUS_INVALID_HANDLE ); + return 0; + } entry->ptr = NULL; if (fd) *fd = entry->fd; else if (entry->fd != -1) return 1; /* silently ignore close attempt if we cannot close the fd */ @@ -330,8 +336,6 @@ int close_handle( struct process *process, obj_handle_t handle, int *fd ) table = handle_is_global(handle) ? global_table : process->handles; if (entry < table->entries + table->free) table->free = entry - table->entries; if (entry == table->entries + table->last) shrink_handle_table( table ); - /* hack: windows seems to treat registry handles differently */ - registry_close_handle( obj, handle ); release_object( obj ); return 1; } diff --git a/server/hook.c b/server/hook.c index 125f3467ed5..c3a0244895c 100644 --- a/server/hook.c +++ b/server/hook.c @@ -79,6 +79,7 @@ static const struct object_ops hook_table_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ hook_table_destroy /* destroy */ }; diff --git a/server/mailslot.c b/server/mailslot.c index 6f24126a475..347d19f3995 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -76,6 +76,7 @@ static const struct object_ops mailslot_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ mailslot_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ mailslot_destroy /* destroy */ }; @@ -118,6 +119,7 @@ static const struct object_ops mail_writer_ops = NULL, /* satisfied */ no_signal, /* signal */ mail_writer_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ mail_writer_destroy /* destroy */ }; diff --git a/server/mapping.c b/server/mapping.c index 046bc0b86a6..886edc62ab3 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -64,6 +64,7 @@ static const struct object_ops mapping_ops = NULL, /* satisfied */ no_signal, /* signal */ mapping_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ mapping_destroy /* destroy */ }; diff --git a/server/mutex.c b/server/mutex.c index c1b59bb85bd..c9bee831be9 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -56,6 +56,7 @@ static const struct object_ops mutex_ops = mutex_satisfied, /* satisfied */ mutex_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ mutex_destroy /* destroy */ }; diff --git a/server/named_pipe.c b/server/named_pipe.c index bbf011ef965..ab4a39db344 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -112,6 +112,7 @@ static const struct object_ops named_pipe_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ named_pipe_destroy /* destroy */ }; @@ -132,6 +133,7 @@ static const struct object_ops pipe_server_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ pipe_server_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ pipe_server_destroy /* destroy */ }; @@ -162,6 +164,7 @@ static const struct object_ops pipe_client_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ pipe_client_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ pipe_client_destroy /* destroy */ }; diff --git a/server/object.c b/server/object.c index 90aa35c90bd..1a629ece722 100644 --- a/server/object.c +++ b/server/object.c @@ -294,6 +294,11 @@ struct fd *no_get_fd( struct object *obj ) return NULL; } +int no_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) +{ + return 1; /* ok to close */ +} + void no_destroy( struct object *obj ) { } diff --git a/server/object.h b/server/object.h index 9fd658194dd..6551cf8a863 100644 --- a/server/object.h +++ b/server/object.h @@ -63,6 +63,8 @@ struct object_ops int (*signal)(struct object *, unsigned int); /* return an fd object that can be used to read/write from the object */ struct fd *(*get_fd)(struct object *); + /* close a handle to this object */ + int (*close_handle)(struct object *,struct process *,obj_handle_t); /* destroy on refcount == 0 */ void (*destroy)(struct object *); }; @@ -102,6 +104,7 @@ extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry ); extern int no_satisfied( struct object *obj, struct thread *thread ); extern int no_signal( struct object *obj, unsigned int access ); extern struct fd *no_get_fd( struct object *obj ); +extern int no_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); extern void no_destroy( struct object *obj ); #ifdef DEBUG_OBJECTS extern void dump_objects(void); @@ -146,7 +149,6 @@ extern int get_page_size(void); extern void init_registry(void); extern void flush_registry(void); extern void close_registry(void); -extern void registry_close_handle( struct object *obj, obj_handle_t hkey ); /* signal functions */ diff --git a/server/process.c b/server/process.c index f2b4012d5ad..32d3be0c4b1 100644 --- a/server/process.c +++ b/server/process.c @@ -70,8 +70,9 @@ static const struct object_ops process_ops = remove_queue, /* remove_queue */ process_signaled, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ process_destroy /* destroy */ }; @@ -119,6 +120,7 @@ static const struct object_ops startup_info_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ startup_info_destroy /* destroy */ }; diff --git a/server/queue.c b/server/queue.c index 38e5d6754d9..d827c0fd133 100644 --- a/server/queue.c +++ b/server/queue.c @@ -148,6 +148,7 @@ static const struct object_ops msg_queue_ops = msg_queue_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ msg_queue_destroy /* destroy */ }; @@ -162,6 +163,7 @@ static const struct object_ops thread_input_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ thread_input_destroy /* destroy */ }; diff --git a/server/registry.c b/server/registry.c index 5d2d0b9ba34..a38682d0974 100644 --- a/server/registry.c +++ b/server/registry.c @@ -129,6 +129,7 @@ struct file_load_info static void key_dump( struct object *obj, int verbose ); +static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void key_destroy( struct object *obj ); static const struct object_ops key_ops = @@ -141,6 +142,7 @@ static const struct object_ops key_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + key_close_handle, /* close_handle */ key_destroy /* destroy */ }; @@ -293,17 +295,12 @@ static struct notify *find_notify( struct key *key, obj_handle_t hkey) } /* close the notification associated with a handle */ -void registry_close_handle( struct object *obj, obj_handle_t hkey ) +static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) { struct key * key = (struct key *) obj; - struct notify *notify; - - if( obj->ops != &key_ops ) - return; - notify = find_notify( key, hkey ); - if( !notify ) - return; - do_notification( key, notify, 1 ); + struct notify *notify = find_notify( key, handle ); + if (notify) do_notification( key, notify, 1 ); + return 1; /* ok to close */ } static void key_destroy( struct object *obj ) diff --git a/server/request.c b/server/request.c index aa5c09de58d..4a2c80ae0f3 100644 --- a/server/request.c +++ b/server/request.c @@ -95,6 +95,7 @@ static const struct object_ops master_socket_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ master_socket_destroy /* destroy */ }; diff --git a/server/semaphore.c b/server/semaphore.c index 7886842cf07..64c34478a8f 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -53,6 +53,7 @@ static const struct object_ops semaphore_ops = semaphore_satisfied, /* satisfied */ semaphore_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/serial.c b/server/serial.c index 014142e190e..73d73ae0439 100644 --- a/server/serial.c +++ b/server/serial.c @@ -103,6 +103,7 @@ static const struct object_ops serial_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ serial_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ serial_destroy /* destroy */ }; diff --git a/server/signal.c b/server/signal.c index f3b0f5f7dd8..9ce3640016d 100644 --- a/server/signal.c +++ b/server/signal.c @@ -64,6 +64,7 @@ static const struct object_ops handler_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ handler_destroy /* destroy */ }; diff --git a/server/snapshot.c b/server/snapshot.c index 7f1670c6100..6c71b759431 100644 --- a/server/snapshot.c +++ b/server/snapshot.c @@ -63,6 +63,7 @@ static const struct object_ops snapshot_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ snapshot_destroy /* destroy */ }; diff --git a/server/sock.c b/server/sock.c index 3fa3049b976..535786e87a7 100644 --- a/server/sock.c +++ b/server/sock.c @@ -109,6 +109,7 @@ static const struct object_ops sock_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ sock_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ sock_destroy /* destroy */ }; diff --git a/server/thread.c b/server/thread.c index 3fb06c560fc..b021dc0aeab 100644 --- a/server/thread.c +++ b/server/thread.c @@ -94,6 +94,7 @@ static const struct object_ops thread_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ destroy_thread /* destroy */ }; diff --git a/server/timer.c b/server/timer.c index 2329c6c262e..c4ab0e874bc 100644 --- a/server/timer.c +++ b/server/timer.c @@ -61,6 +61,7 @@ static const struct object_ops timer_ops = timer_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ timer_destroy /* destroy */ }; diff --git a/server/token.c b/server/token.c index ca1a7ff0838..0c11edf25c2 100644 --- a/server/token.c +++ b/server/token.c @@ -109,6 +109,7 @@ static const struct object_ops token_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ token_destroy /* destroy */ }; diff --git a/server/winstation.c b/server/winstation.c index 7e7adab2187..d42ed665e63 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -56,8 +56,10 @@ static struct winstation *interactive_winstation; static struct namespace *winstation_namespace; static void winstation_dump( struct object *obj, int verbose ); +static int winstation_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void winstation_destroy( struct object *obj ); static void desktop_dump( struct object *obj, int verbose ); +static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void desktop_destroy( struct object *obj ); static const struct object_ops winstation_ops = @@ -70,6 +72,7 @@ static const struct object_ops winstation_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + winstation_close_handle, /* close_handle */ winstation_destroy /* destroy */ }; @@ -84,6 +87,7 @@ static const struct object_ops desktop_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + desktop_close_handle, /* close_handle */ desktop_destroy /* destroy */ }; @@ -125,6 +129,11 @@ static void winstation_dump( struct object *obj, int verbose ) fputc( '\n', stderr ); } +static int winstation_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) +{ + return (process->winstation != handle); +} + static void winstation_destroy( struct object *obj ) { struct winstation *winstation = (struct winstation *)obj; @@ -199,6 +208,17 @@ static void desktop_dump( struct object *obj, int verbose ) fputc( '\n', stderr ); } +static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) +{ + struct thread *thread; + + /* check if the handle is currently used by the process or one of its threads */ + if (process->desktop == handle) return 0; + LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) + if (thread->desktop == handle) return 0; + return 1; +} + static void desktop_destroy( struct object *obj ) { struct desktop *desktop = (struct desktop *)obj; @@ -207,19 +227,6 @@ static void desktop_destroy( struct object *obj ) release_object( desktop->winstation ); } -/* check if a desktop handle is currently used by the process */ -static int is_desktop_in_use( struct process *process, obj_handle_t handle ) -{ - struct thread *thread; - - if (process->desktop == handle) return 1; - - LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) - if (thread->desktop == handle) return 1; - - return 0; -} - /* connect a process to its window station */ void connect_process_winstation( struct process *process, const WCHAR *name, size_t len ) { @@ -246,13 +253,7 @@ void connect_process_winstation( struct process *process, const WCHAR *name, siz } if (winstation) { - if ((process->winstation = alloc_handle( process, winstation, WINSTA_ALL_ACCESS, FALSE ))) - { - int fd = -1; - /* FIXME: Windows doesn't do it this way */ - set_handle_info( process, process->winstation, HANDLE_FLAG_PROTECT_FROM_CLOSE, - HANDLE_FLAG_PROTECT_FROM_CLOSE, &fd ); - } + process->winstation = alloc_handle( process, winstation, WINSTA_ALL_ACCESS, FALSE ); release_object( winstation ); } clear_error(); /* ignore errors */ @@ -291,8 +292,8 @@ void close_thread_desktop( struct thread *thread ) obj_handle_t handle = thread->desktop; thread->desktop = 0; - if (handle && !is_desktop_in_use( thread->process, handle )) - close_handle( thread->process, handle, NULL ); + if (handle) close_handle( thread->process, handle, NULL ); + clear_error(); /* ignore errors */ } @@ -328,10 +329,7 @@ DECL_HANDLER(close_winstation) if ((winstation = (struct winstation *)get_handle_obj( current->process, req->handle, 0, &winstation_ops ))) { - if (req->handle != current->process->winstation) - close_handle( current->process, req->handle, NULL ); - else - set_error( STATUS_ACCESS_DENIED ); + if (!close_handle( current->process, req->handle, NULL )) set_error( STATUS_ACCESS_DENIED ); release_object( winstation ); } } @@ -408,10 +406,7 @@ DECL_HANDLER(close_desktop) if ((desktop = (struct desktop *)get_handle_obj( current->process, req->handle, 0, &desktop_ops ))) { - if (!is_desktop_in_use( current->process, req->handle )) - close_handle( current->process, req->handle, NULL ); - else - set_error( STATUS_DEVICE_BUSY ); + if (!close_handle( current->process, req->handle, NULL )) set_error( STATUS_DEVICE_BUSY ); release_object( desktop ); } }