Jacek Caban : conhost: Implement IOCTL_CONDRV_READ_INPUT.

Alexandre Julliard julliard at winehq.org
Wed Aug 26 15:24:44 CDT 2020


Module: wine
Branch: master
Commit: e703e2da39a411e1f0aaf6d5ff7a1fa36edb87cd
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e703e2da39a411e1f0aaf6d5ff7a1fa36edb87cd

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Aug 25 14:52:58 2020 +0200

conhost: Implement IOCTL_CONDRV_READ_INPUT.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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) );




More information about the wine-cvs mailing list