Module: wine Branch: master Commit: e703e2da39a411e1f0aaf6d5ff7a1fa36edb87cd URL: https://source.winehq.org/git/wine.git/?a=commit;h=e703e2da39a411e1f0aaf6d5f...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Aug 25 14:52:58 2020 +0200
conhost: Implement IOCTL_CONDRV_READ_INPUT.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/kernel32/tests/console.c | 1 + programs/conhost/conhost.c | 53 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index afc91ecfce..09c48ee705 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -3968,6 +3968,7 @@ static void test_pseudo_console_child(HANDLE input) ok(ret, "SetConsoleMode failed: %u\n", GetLastError());
test_console_title(); + test_WriteConsoleInputW(input); }
static DWORD WINAPI read_pipe_proc( void *handle ) diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index 525ca9058e..d65a605f04 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -48,6 +48,7 @@ struct console INPUT_RECORD *records; /* input records */ unsigned int record_count; /* number of input records */ unsigned int record_size; /* size of input records buffer */ + size_t pending_read; /* size of pending read buffer */ WCHAR *title; /* console title */ size_t title_len; /* length of console title */ struct history_line **history; /* lines history */ @@ -75,6 +76,36 @@ static void *alloc_ioctl_buffer( size_t size ) return ioctl_buffer; }
+static NTSTATUS read_console_input( struct console *console, size_t out_size ) +{ + size_t count = min( out_size / sizeof(INPUT_RECORD), console->record_count ); + NTSTATUS status; + + TRACE("count %u\n", count); + + SERVER_START_REQ( get_next_console_request ) + { + req->handle = wine_server_obj_handle( console->server ); + req->signal = count < console->record_count; + req->read = 1; + req->status = STATUS_SUCCESS; + wine_server_add_data( req, console->records, count * sizeof(*console->records) ); + status = wine_server_call( req ); + } + SERVER_END_REQ; + if (status) + { + ERR( "failed: %#x\n", status ); + return status; + } + + if (count < console->record_count) + memmove( console->records, console->records + count, + (console->record_count - count) * sizeof(*console->records) ); + console->record_count -= count; + return STATUS_SUCCESS; +} + /* add input events to a console input queue */ static NTSTATUS write_console_input( struct console *console, const INPUT_RECORD *records, unsigned int count ) @@ -115,6 +146,11 @@ static NTSTATUS write_console_input( struct console *console, const INPUT_RECORD } } console->record_count += count; + if (count && console->pending_read) + { + read_console_input( console, console->pending_read ); + console->pending_read = 0; + } return STATUS_SUCCESS; }
@@ -156,6 +192,23 @@ static NTSTATUS console_input_ioctl( struct console *console, unsigned int code, TRACE( "set %x mode\n", console->mode ); return STATUS_SUCCESS;
+ case IOCTL_CONDRV_READ_INPUT: + { + unsigned int blocking; + NTSTATUS status; + if (in_size && in_size != sizeof(blocking)) return STATUS_INVALID_PARAMETER; + blocking = in_size && *(unsigned int *)in_data; + if (blocking && !console->record_count && *out_size) + { + TRACE( "pending read" ); + console->pending_read = *out_size; + return STATUS_PENDING; + } + status = read_console_input( console, *out_size ); + *out_size = 0; + return status; + } + case IOCTL_CONDRV_WRITE_INPUT: if (in_size % sizeof(INPUT_RECORD) || *out_size) return STATUS_INVALID_PARAMETER; return write_console_input( console, in_data, in_size / sizeof(INPUT_RECORD) );