Commit b9b1ea9c authored by Alexandre Julliard's avatar Alexandre Julliard

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.
parent d1a7f070
...@@ -53,13 +53,9 @@ static DWORD CALLBACK thread( LPVOID arg ) ...@@ -53,13 +53,9 @@ static DWORD CALLBACK thread( LPVOID arg )
trace( "thread %p desktop: %p\n", arg, d1 ); trace( "thread %p desktop: %p\n", arg, d1 );
ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg ); 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" );
SetLastError( 0xdeadbeef ); ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" );
ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
}
SetLastError( 0xdeadbeef ); SetLastError( 0xdeadbeef );
ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" ); ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" );
ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() ); ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() );
...@@ -109,7 +105,7 @@ static void test_handles(void) ...@@ -109,7 +105,7 @@ static void test_handles(void)
flags = 0; flags = 0;
ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" ); 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, ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0,
TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
...@@ -165,12 +161,9 @@ static void test_handles(void) ...@@ -165,12 +161,9 @@ static void test_handles(void)
ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" ); ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" );
ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() ); 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" );
SetLastError( 0xdeadbeef ); ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
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, ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0,
TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
...@@ -198,12 +191,9 @@ static void test_handles(void) ...@@ -198,12 +191,9 @@ static void test_handles(void)
d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS ); d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
ok( !d3, "open foobar desktop succeeded\n" ); 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( !CloseHandle(d1), "closing thread desktop handle succeeded\n" ); ok( d1 == d2, "got different handles after close\n" );
d2 = GetThreadDesktop(GetCurrentThreadId());
ok( d1 == d2, "got different handles after close\n" );
}
trace( "thread 1 desktop: %p\n", d1 ); trace( "thread 1 desktop: %p\n", d1 );
print_object( d1 ); print_object( d1 );
......
...@@ -76,6 +76,7 @@ static const struct object_ops atom_table_ops = ...@@ -76,6 +76,7 @@ static const struct object_ops atom_table_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
atom_table_destroy /* destroy */ atom_table_destroy /* destroy */
}; };
......
...@@ -73,6 +73,7 @@ static const struct object_ops change_ops = ...@@ -73,6 +73,7 @@ static const struct object_ops change_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
change_destroy /* destroy */ change_destroy /* destroy */
}; };
......
...@@ -48,6 +48,7 @@ static const struct object_ops console_input_ops = ...@@ -48,6 +48,7 @@ static const struct object_ops console_input_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
console_input_destroy /* destroy */ console_input_destroy /* destroy */
}; };
...@@ -73,6 +74,7 @@ static const struct object_ops console_input_events_ops = ...@@ -73,6 +74,7 @@ static const struct object_ops console_input_events_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
console_input_events_destroy /* destroy */ console_input_events_destroy /* destroy */
}; };
...@@ -109,6 +111,7 @@ static const struct object_ops screen_buffer_ops = ...@@ -109,6 +111,7 @@ static const struct object_ops screen_buffer_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
screen_buffer_destroy /* destroy */ screen_buffer_destroy /* destroy */
}; };
......
...@@ -74,6 +74,7 @@ static const struct object_ops debug_event_ops = ...@@ -74,6 +74,7 @@ static const struct object_ops debug_event_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
debug_event_destroy /* destroy */ debug_event_destroy /* destroy */
}; };
...@@ -91,6 +92,7 @@ static const struct object_ops debug_ctx_ops = ...@@ -91,6 +92,7 @@ static const struct object_ops debug_ctx_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
debug_ctx_destroy /* destroy */ debug_ctx_destroy /* destroy */
}; };
......
...@@ -53,6 +53,7 @@ static const struct object_ops event_ops = ...@@ -53,6 +53,7 @@ static const struct object_ops event_ops =
event_satisfied, /* satisfied */ event_satisfied, /* satisfied */
event_signal, /* signal */ event_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
no_destroy /* destroy */ no_destroy /* destroy */
}; };
......
...@@ -163,6 +163,7 @@ static const struct object_ops fd_ops = ...@@ -163,6 +163,7 @@ static const struct object_ops fd_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
fd_destroy /* destroy */ fd_destroy /* destroy */
}; };
...@@ -193,6 +194,7 @@ static const struct object_ops inode_ops = ...@@ -193,6 +194,7 @@ static const struct object_ops inode_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
inode_destroy /* destroy */ inode_destroy /* destroy */
}; };
...@@ -224,6 +226,7 @@ static const struct object_ops file_lock_ops = ...@@ -224,6 +226,7 @@ static const struct object_ops file_lock_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
no_destroy /* destroy */ no_destroy /* destroy */
}; };
......
...@@ -80,6 +80,7 @@ static const struct object_ops file_ops = ...@@ -80,6 +80,7 @@ static const struct object_ops file_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
file_get_fd, /* get_fd */ file_get_fd, /* get_fd */
no_close_handle, /* close_handle */
file_destroy /* destroy */ file_destroy /* destroy */
}; };
......
...@@ -108,6 +108,7 @@ static const struct object_ops handle_table_ops = ...@@ -108,6 +108,7 @@ static const struct object_ops handle_table_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
handle_table_destroy /* destroy */ handle_table_destroy /* destroy */
}; };
...@@ -323,6 +324,11 @@ int close_handle( struct process *process, obj_handle_t handle, int *fd ) ...@@ -323,6 +324,11 @@ int close_handle( struct process *process, obj_handle_t handle, int *fd )
return 0; return 0;
} }
obj = entry->ptr; obj = entry->ptr;
if (!obj->ops->close_handle( obj, process, handle ))
{
set_error( STATUS_INVALID_HANDLE );
return 0;
}
entry->ptr = NULL; entry->ptr = NULL;
if (fd) *fd = entry->fd; if (fd) *fd = entry->fd;
else if (entry->fd != -1) return 1; /* silently ignore close attempt if we cannot close the 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 ) ...@@ -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; 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->free) table->free = entry - table->entries;
if (entry == table->entries + table->last) shrink_handle_table( table ); 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 ); release_object( obj );
return 1; return 1;
} }
......
...@@ -79,6 +79,7 @@ static const struct object_ops hook_table_ops = ...@@ -79,6 +79,7 @@ static const struct object_ops hook_table_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
hook_table_destroy /* destroy */ hook_table_destroy /* destroy */
}; };
......
...@@ -76,6 +76,7 @@ static const struct object_ops mailslot_ops = ...@@ -76,6 +76,7 @@ static const struct object_ops mailslot_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
mailslot_get_fd, /* get_fd */ mailslot_get_fd, /* get_fd */
no_close_handle, /* close_handle */
mailslot_destroy /* destroy */ mailslot_destroy /* destroy */
}; };
...@@ -118,6 +119,7 @@ static const struct object_ops mail_writer_ops = ...@@ -118,6 +119,7 @@ static const struct object_ops mail_writer_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
mail_writer_get_fd, /* get_fd */ mail_writer_get_fd, /* get_fd */
no_close_handle, /* close_handle */
mail_writer_destroy /* destroy */ mail_writer_destroy /* destroy */
}; };
......
...@@ -64,6 +64,7 @@ static const struct object_ops mapping_ops = ...@@ -64,6 +64,7 @@ static const struct object_ops mapping_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
mapping_get_fd, /* get_fd */ mapping_get_fd, /* get_fd */
no_close_handle, /* close_handle */
mapping_destroy /* destroy */ mapping_destroy /* destroy */
}; };
......
...@@ -56,6 +56,7 @@ static const struct object_ops mutex_ops = ...@@ -56,6 +56,7 @@ static const struct object_ops mutex_ops =
mutex_satisfied, /* satisfied */ mutex_satisfied, /* satisfied */
mutex_signal, /* signal */ mutex_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
mutex_destroy /* destroy */ mutex_destroy /* destroy */
}; };
......
...@@ -112,6 +112,7 @@ static const struct object_ops named_pipe_ops = ...@@ -112,6 +112,7 @@ static const struct object_ops named_pipe_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
named_pipe_destroy /* destroy */ named_pipe_destroy /* destroy */
}; };
...@@ -132,6 +133,7 @@ static const struct object_ops pipe_server_ops = ...@@ -132,6 +133,7 @@ static const struct object_ops pipe_server_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
pipe_server_get_fd, /* get_fd */ pipe_server_get_fd, /* get_fd */
no_close_handle, /* close_handle */
pipe_server_destroy /* destroy */ pipe_server_destroy /* destroy */
}; };
...@@ -162,6 +164,7 @@ static const struct object_ops pipe_client_ops = ...@@ -162,6 +164,7 @@ static const struct object_ops pipe_client_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
pipe_client_get_fd, /* get_fd */ pipe_client_get_fd, /* get_fd */
no_close_handle, /* close_handle */
pipe_client_destroy /* destroy */ pipe_client_destroy /* destroy */
}; };
......
...@@ -294,6 +294,11 @@ struct fd *no_get_fd( struct object *obj ) ...@@ -294,6 +294,11 @@ struct fd *no_get_fd( struct object *obj )
return NULL; 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 ) void no_destroy( struct object *obj )
{ {
} }
...@@ -63,6 +63,8 @@ struct object_ops ...@@ -63,6 +63,8 @@ struct object_ops
int (*signal)(struct object *, unsigned int); int (*signal)(struct object *, unsigned int);
/* return an fd object that can be used to read/write from the object */ /* return an fd object that can be used to read/write from the object */
struct fd *(*get_fd)(struct 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 */ /* destroy on refcount == 0 */
void (*destroy)(struct object *); void (*destroy)(struct object *);
}; };
...@@ -102,6 +104,7 @@ extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry ); ...@@ -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_satisfied( struct object *obj, struct thread *thread );
extern int no_signal( struct object *obj, unsigned int access ); extern int no_signal( struct object *obj, unsigned int access );
extern struct fd *no_get_fd( struct object *obj ); 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 ); extern void no_destroy( struct object *obj );
#ifdef DEBUG_OBJECTS #ifdef DEBUG_OBJECTS
extern void dump_objects(void); extern void dump_objects(void);
...@@ -146,7 +149,6 @@ extern int get_page_size(void); ...@@ -146,7 +149,6 @@ extern int get_page_size(void);
extern void init_registry(void); extern void init_registry(void);
extern void flush_registry(void); extern void flush_registry(void);
extern void close_registry(void); extern void close_registry(void);
extern void registry_close_handle( struct object *obj, obj_handle_t hkey );
/* signal functions */ /* signal functions */
......
...@@ -70,8 +70,9 @@ static const struct object_ops process_ops = ...@@ -70,8 +70,9 @@ static const struct object_ops process_ops =
remove_queue, /* remove_queue */ remove_queue, /* remove_queue */
process_signaled, /* signaled */ process_signaled, /* signaled */
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
process_destroy /* destroy */ process_destroy /* destroy */
}; };
...@@ -119,6 +120,7 @@ static const struct object_ops startup_info_ops = ...@@ -119,6 +120,7 @@ static const struct object_ops startup_info_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
startup_info_destroy /* destroy */ startup_info_destroy /* destroy */
}; };
......
...@@ -148,6 +148,7 @@ static const struct object_ops msg_queue_ops = ...@@ -148,6 +148,7 @@ static const struct object_ops msg_queue_ops =
msg_queue_satisfied, /* satisfied */ msg_queue_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
msg_queue_destroy /* destroy */ msg_queue_destroy /* destroy */
}; };
...@@ -162,6 +163,7 @@ static const struct object_ops thread_input_ops = ...@@ -162,6 +163,7 @@ static const struct object_ops thread_input_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
thread_input_destroy /* destroy */ thread_input_destroy /* destroy */
}; };
......
...@@ -129,6 +129,7 @@ struct file_load_info ...@@ -129,6 +129,7 @@ struct file_load_info
static void key_dump( struct object *obj, int verbose ); 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 void key_destroy( struct object *obj );
static const struct object_ops key_ops = static const struct object_ops key_ops =
...@@ -141,6 +142,7 @@ static const struct object_ops key_ops = ...@@ -141,6 +142,7 @@ static const struct object_ops key_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
key_close_handle, /* close_handle */
key_destroy /* destroy */ key_destroy /* destroy */
}; };
...@@ -293,17 +295,12 @@ static struct notify *find_notify( struct key *key, obj_handle_t hkey) ...@@ -293,17 +295,12 @@ static struct notify *find_notify( struct key *key, obj_handle_t hkey)
} }
/* close the notification associated with a handle */ /* 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 key * key = (struct key *) obj;
struct notify *notify; struct notify *notify = find_notify( key, handle );
if (notify) do_notification( key, notify, 1 );
if( obj->ops != &key_ops ) return 1; /* ok to close */
return;
notify = find_notify( key, hkey );
if( !notify )
return;
do_notification( key, notify, 1 );
} }
static void key_destroy( struct object *obj ) static void key_destroy( struct object *obj )
......
...@@ -95,6 +95,7 @@ static const struct object_ops master_socket_ops = ...@@ -95,6 +95,7 @@ static const struct object_ops master_socket_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
master_socket_destroy /* destroy */ master_socket_destroy /* destroy */
}; };
......
...@@ -53,6 +53,7 @@ static const struct object_ops semaphore_ops = ...@@ -53,6 +53,7 @@ static const struct object_ops semaphore_ops =
semaphore_satisfied, /* satisfied */ semaphore_satisfied, /* satisfied */
semaphore_signal, /* signal */ semaphore_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
no_destroy /* destroy */ no_destroy /* destroy */
}; };
......
...@@ -103,6 +103,7 @@ static const struct object_ops serial_ops = ...@@ -103,6 +103,7 @@ static const struct object_ops serial_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
serial_get_fd, /* get_fd */ serial_get_fd, /* get_fd */
no_close_handle, /* close_handle */
serial_destroy /* destroy */ serial_destroy /* destroy */
}; };
......
...@@ -64,6 +64,7 @@ static const struct object_ops handler_ops = ...@@ -64,6 +64,7 @@ static const struct object_ops handler_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
handler_destroy /* destroy */ handler_destroy /* destroy */
}; };
......
...@@ -63,6 +63,7 @@ static const struct object_ops snapshot_ops = ...@@ -63,6 +63,7 @@ static const struct object_ops snapshot_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
snapshot_destroy /* destroy */ snapshot_destroy /* destroy */
}; };
......
...@@ -109,6 +109,7 @@ static const struct object_ops sock_ops = ...@@ -109,6 +109,7 @@ static const struct object_ops sock_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
sock_get_fd, /* get_fd */ sock_get_fd, /* get_fd */
no_close_handle, /* close_handle */
sock_destroy /* destroy */ sock_destroy /* destroy */
}; };
......
...@@ -94,6 +94,7 @@ static const struct object_ops thread_ops = ...@@ -94,6 +94,7 @@ static const struct object_ops thread_ops =
no_satisfied, /* satisfied */ no_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
destroy_thread /* destroy */ destroy_thread /* destroy */
}; };
......
...@@ -61,6 +61,7 @@ static const struct object_ops timer_ops = ...@@ -61,6 +61,7 @@ static const struct object_ops timer_ops =
timer_satisfied, /* satisfied */ timer_satisfied, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
timer_destroy /* destroy */ timer_destroy /* destroy */
}; };
......
...@@ -109,6 +109,7 @@ static const struct object_ops token_ops = ...@@ -109,6 +109,7 @@ static const struct object_ops token_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
no_close_handle, /* close_handle */
token_destroy /* destroy */ token_destroy /* destroy */
}; };
......
...@@ -56,8 +56,10 @@ static struct winstation *interactive_winstation; ...@@ -56,8 +56,10 @@ static struct winstation *interactive_winstation;
static struct namespace *winstation_namespace; static struct namespace *winstation_namespace;
static void winstation_dump( struct object *obj, int verbose ); 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 winstation_destroy( struct object *obj );
static void desktop_dump( struct object *obj, int verbose ); 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 void desktop_destroy( struct object *obj );
static const struct object_ops winstation_ops = static const struct object_ops winstation_ops =
...@@ -70,6 +72,7 @@ static const struct object_ops winstation_ops = ...@@ -70,6 +72,7 @@ static const struct object_ops winstation_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
winstation_close_handle, /* close_handle */
winstation_destroy /* destroy */ winstation_destroy /* destroy */
}; };
...@@ -84,6 +87,7 @@ static const struct object_ops desktop_ops = ...@@ -84,6 +87,7 @@ static const struct object_ops desktop_ops =
NULL, /* satisfied */ NULL, /* satisfied */
no_signal, /* signal */ no_signal, /* signal */
no_get_fd, /* get_fd */ no_get_fd, /* get_fd */
desktop_close_handle, /* close_handle */
desktop_destroy /* destroy */ desktop_destroy /* destroy */
}; };
...@@ -125,6 +129,11 @@ static void winstation_dump( struct object *obj, int verbose ) ...@@ -125,6 +129,11 @@ static void winstation_dump( struct object *obj, int verbose )
fputc( '\n', stderr ); 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 ) static void winstation_destroy( struct object *obj )
{ {
struct winstation *winstation = (struct winstation *)obj; struct winstation *winstation = (struct winstation *)obj;
...@@ -199,25 +208,23 @@ static void desktop_dump( struct object *obj, int verbose ) ...@@ -199,25 +208,23 @@ static void desktop_dump( struct object *obj, int verbose )
fputc( '\n', stderr ); fputc( '\n', stderr );
} }
static void desktop_destroy( struct object *obj ) static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
{ {
struct desktop *desktop = (struct desktop *)obj; struct thread *thread;
list_remove( &desktop->entry ); /* check if the handle is currently used by the process or one of its threads */
release_object( desktop->winstation ); 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;
} }
/* check if a desktop handle is currently used by the process */ static void desktop_destroy( struct object *obj )
static int is_desktop_in_use( struct process *process, obj_handle_t handle )
{ {
struct thread *thread; struct desktop *desktop = (struct desktop *)obj;
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; list_remove( &desktop->entry );
release_object( desktop->winstation );
} }
/* connect a process to its window station */ /* connect a process to its window station */
...@@ -246,13 +253,7 @@ void connect_process_winstation( struct process *process, const WCHAR *name, siz ...@@ -246,13 +253,7 @@ void connect_process_winstation( struct process *process, const WCHAR *name, siz
} }
if (winstation) if (winstation)
{ {
if ((process->winstation = alloc_handle( process, winstation, WINSTA_ALL_ACCESS, FALSE ))) 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 );
}
release_object( winstation ); release_object( winstation );
} }
clear_error(); /* ignore errors */ clear_error(); /* ignore errors */
...@@ -291,8 +292,8 @@ void close_thread_desktop( struct thread *thread ) ...@@ -291,8 +292,8 @@ void close_thread_desktop( struct thread *thread )
obj_handle_t handle = thread->desktop; obj_handle_t handle = thread->desktop;
thread->desktop = 0; thread->desktop = 0;
if (handle && !is_desktop_in_use( thread->process, handle )) if (handle) close_handle( thread->process, handle, NULL );
close_handle( thread->process, handle, NULL ); clear_error(); /* ignore errors */
} }
...@@ -328,10 +329,7 @@ DECL_HANDLER(close_winstation) ...@@ -328,10 +329,7 @@ DECL_HANDLER(close_winstation)
if ((winstation = (struct winstation *)get_handle_obj( current->process, req->handle, if ((winstation = (struct winstation *)get_handle_obj( current->process, req->handle,
0, &winstation_ops ))) 0, &winstation_ops )))
{ {
if (req->handle != current->process->winstation) if (!close_handle( current->process, req->handle, NULL )) set_error( STATUS_ACCESS_DENIED );
close_handle( current->process, req->handle, NULL );
else
set_error( STATUS_ACCESS_DENIED );
release_object( winstation ); release_object( winstation );
} }
} }
...@@ -408,10 +406,7 @@ DECL_HANDLER(close_desktop) ...@@ -408,10 +406,7 @@ DECL_HANDLER(close_desktop)
if ((desktop = (struct desktop *)get_handle_obj( current->process, req->handle, if ((desktop = (struct desktop *)get_handle_obj( current->process, req->handle,
0, &desktop_ops ))) 0, &desktop_ops )))
{ {
if (!is_desktop_in_use( current->process, req->handle )) if (!close_handle( current->process, req->handle, NULL )) set_error( STATUS_DEVICE_BUSY );
close_handle( current->process, req->handle, NULL );
else
set_error( STATUS_DEVICE_BUSY );
release_object( desktop ); release_object( desktop );
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment