Jacek Caban : conhost: Update tty output in IOCTL_CONDRV_ACTIVATE.

Alexandre Julliard julliard at winehq.org
Fri Sep 4 15:47:32 CDT 2020


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Sep  4 13:52:01 2020 +0200

conhost: Update tty output in IOCTL_CONDRV_ACTIVATE.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/conhost/conhost.c   | 14 ++++++-
 programs/conhost/tests/tty.c | 97 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c
index 9edd5971b8..9830ff0182 100644
--- a/programs/conhost/conhost.c
+++ b/programs/conhost/conhost.c
@@ -451,6 +451,17 @@ static NTSTATUS write_console_input( struct console *console, const INPUT_RECORD
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS screen_buffer_activate( struct screen_buffer *screen_buffer )
+{
+    RECT update_rect;
+    TRACE( "%p\n", screen_buffer );
+    screen_buffer->console->active = screen_buffer;
+    SetRect( &update_rect, 0, 0, screen_buffer->width - 1, screen_buffer->height - 1);
+    update_output( screen_buffer, &update_rect );
+    tty_sync( screen_buffer->console );
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS get_output_info( struct screen_buffer *screen_buffer, size_t *out_size )
 {
     struct condrv_output_info *info;
@@ -1043,8 +1054,7 @@ static NTSTATUS screen_buffer_ioctl( struct screen_buffer *screen_buffer, unsign
 
     case IOCTL_CONDRV_ACTIVATE:
         if (in_size || *out_size) return STATUS_INVALID_PARAMETER;
-        screen_buffer->console->active = screen_buffer;
-        return STATUS_SUCCESS;
+        return screen_buffer_activate( screen_buffer );
 
     case IOCTL_CONDRV_GET_MODE:
         {
diff --git a/programs/conhost/tests/tty.c b/programs/conhost/tests/tty.c
index c28928701f..9c0ec8493b 100644
--- a/programs/conhost/tests/tty.c
+++ b/programs/conhost/tests/tty.c
@@ -145,8 +145,10 @@ static BOOL expect_erase_line_(unsigned line, unsigned int cnt)
 
 enum req_type
 {
+    REQ_CREATE_SCREEN_BUFFER,
     REQ_FILL_CHAR,
     REQ_SCROLL,
+    REQ_SET_ACTIVE,
     REQ_SET_CURSOR,
     REQ_SET_TITLE,
     REQ_WRITE_CHARACTERS,
@@ -160,6 +162,7 @@ struct pseudoconsole_req
     {
         WCHAR string[1];
         COORD coord;
+        HANDLE handle;
         struct
         {
             COORD coord;
@@ -234,6 +237,33 @@ static void child_set_cursor(const unsigned int x, unsigned int y)
     ok(ret, "WriteFile failed: %u\n", GetLastError());
 }
 
+static HANDLE child_create_screen_buffer(void)
+{
+    struct pseudoconsole_req req;
+    HANDLE handle;
+    DWORD count;
+    BOOL ret;
+
+    req.type = REQ_CREATE_SCREEN_BUFFER;
+    ret = WriteFile(child_pipe, &req, sizeof(req), &count, NULL);
+    ok(ret, "WriteFile failed: %u\n", GetLastError());
+    ret = ReadFile(child_pipe, &handle, sizeof(handle), &count, NULL);
+    ok(ret, "ReadFile failed: %u\n", GetLastError());
+    return handle;
+}
+
+static void child_set_active(HANDLE handle)
+{
+    struct pseudoconsole_req req;
+    DWORD count;
+    BOOL ret;
+
+    req.type = REQ_SET_ACTIVE;
+    req.u.handle = handle;
+    ret = WriteFile(child_pipe, &req, sizeof(req), &count, NULL);
+    ok(ret, "WriteFile failed: %u\n", GetLastError());
+}
+
 #define child_write_output(a,b,c,d,e,f,g,h,j,k,l,m,n) child_write_output_(__LINE__,a,b,c,d,e,f,g,h,j,k,l,m,n)
 static void child_write_output_(unsigned int line, CHAR_INFO *buf, unsigned int size_x, unsigned int size_y,
                                 unsigned int coord_x, unsigned int coord_y, unsigned int left,
@@ -303,6 +333,7 @@ static void child_fill_character(WCHAR ch, DWORD count, int x, int y)
 static void test_tty_output(void)
 {
     CHAR_INFO char_info_buf[2048], char_info;
+    HANDLE sb, sb2;
     unsigned int i;
 
     /* simple write chars */
@@ -532,6 +563,52 @@ static void test_tty_output(void)
     expect_output_sequence("\x1b[4;3H");   /* set cursor */
     expect_output_sequence("\x1b[?25h");   /* show cursor */
     expect_empty_output();
+
+    sb = child_create_screen_buffer();
+    child_set_active(sb);
+    expect_hide_cursor();
+    expect_output_sequence("\x1b[H");      /* set cursor */
+    for (i = 0; i < 40; i++)
+    {
+        expect_erase_line(30);
+        if (i != 39) expect_output_sequence("\r\n");
+    }
+    expect_output_sequence("\x1b[H");      /* set cursor */
+    expect_output_sequence("\x1b[?25h");   /* show cursor */
+    expect_empty_output();
+
+    child_write_characters(L"new sb", 0, 0);
+    skip_hide_cursor();
+    expect_output_sequence("new sb");
+    ok(skip_sequence("\x1b[H") || skip_sequence("\r"), "expected set cursor\n");
+    skip_sequence("\x1b[?25h");            /* show cursor */
+    expect_empty_output();
+
+    sb2 = child_create_screen_buffer();
+    child_set_active(sb2);
+    expect_hide_cursor();
+    for (i = 0; i < 40; i++)
+    {
+        expect_erase_line(30);
+        if (i != 39) expect_output_sequence("\r\n");
+    }
+    expect_output_sequence("\x1b[H");      /* set cursor */
+    expect_output_sequence("\x1b[?25h");   /* show cursor */
+    expect_empty_output();
+
+    child_set_active(sb);
+    expect_hide_cursor();
+    expect_output_sequence("new sb");
+    expect_erase_line(24);
+    expect_output_sequence("\r\n");
+    for (i = 1; i < 40; i++)
+    {
+        expect_erase_line(30);
+        if (i != 39) expect_output_sequence("\r\n");
+    }
+    expect_output_sequence("\x1b[H");      /* set cursor */
+    expect_output_sequence("\x1b[?25h");   /* show cursor */
+    expect_empty_output();
 }
 
 static void child_process(HANDLE pipe)
@@ -552,6 +629,20 @@ static void child_process(HANDLE pipe)
         const struct pseudoconsole_req *req = (void *)buf;
         switch (req->type)
         {
+        case REQ_CREATE_SCREEN_BUFFER:
+            {
+                HANDLE handle;
+                DWORD count;
+                SetLastError(0xdeadbeef);
+                handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+                                                   FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                                                   CONSOLE_TEXTMODE_BUFFER, NULL);
+                ok(handle != INVALID_HANDLE_VALUE, "CreateConsoleScreenBuffer failed: %u\n", GetLastError());
+                ret = WriteFile(pipe, &handle, sizeof(handle), &count, NULL);
+                ok(ret, "WriteFile failed: %u\n", GetLastError());
+                break;
+            }
+
         case REQ_SCROLL:
             ret = ScrollConsoleScreenBufferW(output, &req->u.scroll.rect, NULL, req->u.scroll.dst, &req->u.scroll.fill);
             ok(ret, "ScrollConsoleScreenBuffer failed: %u\n", GetLastError());
@@ -563,6 +654,12 @@ static void child_process(HANDLE pipe)
             ok(count == req->u.fill.count, "count = %u, expected %u\n", count, req->u.fill.count);
             break;
 
+        case REQ_SET_ACTIVE:
+            output = req->u.handle;
+            ret = SetConsoleActiveScreenBuffer(output);
+            ok(ret, "SetConsoleActiveScreenBuffer failed: %u\n", GetLastError());
+            break;
+
         case REQ_SET_CURSOR:
             ret = SetConsoleCursorPosition(output, req->u.coord);
             ok(ret, "SetConsoleCursorPosition failed: %u\n", GetLastError());




More information about the wine-cvs mailing list