From: Elizabeth Figura zfigura@codeweavers.com
Do not delegate to the current process's queue, either, but use the queue for this object.
I/O acts on the current process's console, but the handle signaled state is the same across all handles to this object, and reflects the signaled state of the console of the process that created the object. --- dlls/kernel32/tests/console.c | 8 +++---- server/console.c | 39 +++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index dbffafc2dcf..76880607119 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4168,7 +4168,7 @@ static void test_unbound_handles_child(DWORD parent_pid, UINT_PTR parent_input_i ok(ret, "got error %lu\n", GetLastError());
ret = WaitForSingleObject(parent_input, 0); - todo_wine ok(!ret, "got %d\n", ret); + ok(!ret, "got %d\n", ret); ret = WaitForSingleObject(parent_output, 0); todo_wine ok(!ret, "got %d\n", ret);
@@ -4227,7 +4227,7 @@ static void test_unbound_handles_child(DWORD parent_pid, UINT_PTR parent_input_i ok(ret == TRUE, "got error %lu\n", GetLastError());
ret = WaitForSingleObject(unbound_input, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); + ok(ret == WAIT_TIMEOUT, "got %d\n", ret); CloseHandle(unbound_input);
ret = WaitForSingleObject(parent_input, 0); @@ -4241,7 +4241,7 @@ static void test_unbound_handles_child(DWORD parent_pid, UINT_PTR parent_input_i ok(!ret, "got %d\n", ret);
ret = WaitForSingleObject(parent_input, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); + ok(ret == WAIT_TIMEOUT, "got %d\n", ret); ret = WaitForSingleObject(parent_output, 0); todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } @@ -4350,7 +4350,7 @@ static void test_FreeConsole(HANDLE input, HANDLE orig_output) ret = WaitForSingleObject(unbound_output, 0); todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); ret = WaitForSingleObject(unbound_input, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); + ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
/* Create a new console. * diff --git a/server/console.c b/server/console.c index 75fc79627ae..ef985e8fdd0 100644 --- a/server/console.c +++ b/server/console.c @@ -296,12 +296,14 @@ struct console_input { struct object obj; /* object header */ struct fd *fd; /* pseudo-fd */ + struct list entry; /* entry in console_input_list */ + struct console *console; /* associated console at creation time */ };
static void console_input_dump( struct object *obj, int verbose ); +static int console_input_signaled( struct object *obj, struct wait_queue_entry *entry ); static struct object *console_input_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); static struct fd *console_input_get_fd( struct object *obj ); static void console_input_destroy( struct object *obj );
@@ -310,9 +312,9 @@ static const struct object_ops console_input_ops = sizeof(struct console_input), /* size */ &device_type, /* type */ console_input_dump, /* dump */ - console_input_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ + add_queue, /* add_queue */ + remove_queue, /* remove_queue */ + console_input_signaled, /* signaled */ no_satisfied, /* satisfied */ no_signal, /* signal */ console_input_get_fd, /* get_fd */ @@ -463,6 +465,7 @@ static const struct fd_ops console_connection_fd_ops = };
static struct list screen_buffer_list = LIST_INIT(screen_buffer_list); +static struct list console_input_list = LIST_INIT(console_input_list);
static int queue_host_ioctl( struct console_server *server, unsigned int code, unsigned int output, struct async *async, struct async_queue *queue ); @@ -742,6 +745,7 @@ static void console_dump( struct object *obj, int verbose ) static void console_destroy( struct object *obj ) { struct console *console = (struct console *)obj; + struct console_input *input; struct screen_buffer *curr;
assert( obj->ops == &console_ops ); @@ -760,6 +764,12 @@ static void console_destroy( struct object *obj ) if (curr->input == console) curr->input = NULL; }
+ LIST_FOR_EACH_ENTRY( input, &console_input_list, struct console_input, entry ) + { + if (input->console == console) + input->console = NULL; + } + free_async_queue( &console->ioctl_q ); free_async_queue( &console->read_q ); if (console->fd) @@ -1327,6 +1337,8 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni release_object( console_input ); return NULL; } + console_input->console = current->process->console; + list_add_head( &console_input_list, &console_input->entry ); return &console_input->obj; }
@@ -1402,14 +1414,12 @@ static void console_input_dump( struct object *obj, int verbose ) fputs( "console Input device\n", stderr ); }
-static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ) +static int console_input_signaled( struct object *obj, struct wait_queue_entry *entry ) { - if (!current->process->console) - { - set_error( STATUS_ACCESS_DENIED ); - return 0; - } - return console_add_queue( ¤t->process->console->obj, entry ); + struct console_input *console_input = (struct console_input *)obj; + assert( obj->ops == &console_input_ops ); + if (!console_input->console) return 0; + return console_input->console->signaled; }
static struct fd *console_input_get_fd( struct object *obj ) @@ -1431,6 +1441,7 @@ static void console_input_destroy( struct object *obj )
assert( obj->ops == &console_input_ops ); if (console_input->fd) release_object( console_input->fd ); + list_remove( &console_input->entry ); }
static void console_input_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) @@ -1558,6 +1569,7 @@ DECL_HANDLER(get_next_console_request) else if (!server->console->signaled) { struct screen_buffer *screen_buffer; + struct console_input *input;
server->console->signaled = 1; wake_up( &server->console->obj, 0 ); @@ -1566,6 +1578,11 @@ DECL_HANDLER(get_next_console_request) if (screen_buffer->input == server->console) wake_up( &screen_buffer->obj, 0 ); } + LIST_FOR_EACH_ENTRY( input, &console_input_list, struct console_input, entry ) + { + if (input->console == server->console) + wake_up( &input->obj, 0 ); + } }
if (req->read)