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.
This commit is contained in:
parent
d1a7f070d4
commit
b9b1ea9c9f
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 )
|
|||||||
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 )
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 )
|
|||||||
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
|
|||||||
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 );
|
|||||||
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);
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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
|
|||||||
|
|
||||||
|
|
||||||
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 =
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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;
|
|||||||
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 =
|
|||||||
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 =
|
|||||||
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 )
|
|||||||
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,6 +208,17 @@ static void desktop_dump( struct object *obj, int verbose )
|
|||||||
fputc( '\n', stderr );
|
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 )
|
static void desktop_destroy( struct object *obj )
|
||||||
{
|
{
|
||||||
struct desktop *desktop = (struct desktop *)obj;
|
struct desktop *desktop = (struct desktop *)obj;
|
||||||
@ -207,19 +227,6 @@ static void desktop_destroy( struct object *obj )
|
|||||||
release_object( desktop->winstation );
|
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 */
|
/* connect a process to its window station */
|
||||||
void connect_process_winstation( struct process *process, const WCHAR *name, size_t len )
|
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 (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 )
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user