Jacek Caban : server: Use separated fd ops for unbound console output.

Alexandre Julliard julliard at winehq.org
Fri Nov 27 16:04:40 CST 2020


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Nov 27 18:14:12 2020 +0100

server: Use separated fd ops for unbound console output.

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

---

 dlls/kernel32/tests/console.c |  7 ++++
 server/console.c              | 82 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 79 insertions(+), 10 deletions(-)

diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c
index 5e604e949f6..ea6af85c15a 100644
--- a/dlls/kernel32/tests/console.c
+++ b/dlls/kernel32/tests/console.c
@@ -3878,6 +3878,13 @@ static void test_FreeConsole(void)
     ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
        "ReadFile returned %x %u\n", ret, GetLastError());
 
+    ret = WriteFile(unbound_input, "test", 4, &size, NULL);
+    ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+       "ReadFile returned %x %u\n", ret, GetLastError());
+
+    ret = GetConsoleMode(unbound_input, &mode);
+    ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+       "GetConsoleMode returned %x %u\n", ret, GetLastError());
     ret = GetConsoleMode(unbound_output, &mode);
     ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
        "GetConsoleMode returned %x %u\n", ret, GetLastError());
diff --git a/server/console.c b/server/console.c
index 7cffa512f0e..295db7767b2 100644
--- a/server/console.c
+++ b/server/console.c
@@ -346,15 +346,22 @@ static const struct fd_ops console_input_fd_ops =
     default_fd_reselect_async     /* reselect_async */
 };
 
+struct console_output
+{
+    struct object         obj;         /* object header */
+    struct fd            *fd;          /* pseudo-fd */
+};
+
 static void console_output_dump( struct object *obj, int verbose );
 static int console_output_add_queue( struct object *obj, struct wait_queue_entry *entry );
 static struct fd *console_output_get_fd( struct object *obj );
 static struct object *console_output_open_file( struct object *obj, unsigned int access,
                                                 unsigned int sharing, unsigned int options );
+static void console_output_destroy( struct object *obj );
 
 static const struct object_ops console_output_ops =
 {
-    sizeof(struct object),            /* size */
+    sizeof(struct console_output),    /* size */
     console_output_dump,              /* dump */
     console_device_get_type,          /* get_type */
     console_output_add_queue,         /* add_queue */
@@ -373,7 +380,25 @@ static const struct object_ops console_output_ops =
     console_output_open_file,         /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
     no_close_handle,                  /* close_handle */
-    no_destroy                        /* destroy */
+    console_output_destroy            /* destroy */
+};
+
+static int console_output_write( struct fd *fd, struct async *async, file_pos_t pos );
+static int console_output_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
+
+static const struct fd_ops console_output_fd_ops =
+{
+    default_fd_get_poll_events,   /* get_poll_events */
+    default_poll_event,           /* poll_event */
+    console_get_fd_type,          /* get_fd_type */
+    no_fd_read,                   /* read */
+    console_output_write,         /* write */
+    no_fd_flush,                  /* flush */
+    console_get_file_info,        /* get_file_info */
+    console_get_volume_info,      /* get_volume_info */
+    console_output_ioctl,         /* ioctl */
+    default_fd_queue_async,       /* queue_async */
+    default_fd_reselect_async     /* reselect_async */
 };
 
 struct console_connection
@@ -1254,8 +1279,17 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni
 
     if (name->len == sizeof(outputW) && !memcmp( name->str, outputW, name->len ))
     {
+        struct console_output *console_output;
         name->len = 0;
-        return alloc_object( &console_output_ops );
+        if (!(console_output = alloc_object( &console_output_ops ))) return NULL;
+        console_output->fd = alloc_pseudo_fd( &console_output_fd_ops, &console_output->obj,
+                                             FILE_SYNCHRONOUS_IO_NONALERT );
+        if (!console_output->fd)
+        {
+            release_object( console_output );
+            return NULL;
+        }
+        return &console_output->obj;
     }
 
     if (name->len == sizeof(screen_bufferW) && !memcmp( name->str, screen_bufferW, name->len ))
@@ -1392,13 +1426,9 @@ static int console_output_add_queue( struct object *obj, struct wait_queue_entry
 
 static struct fd *console_output_get_fd( struct object *obj )
 {
-    if (!current->process->console || !current->process->console->active)
-    {
-        set_error( STATUS_ACCESS_DENIED );
-        return NULL;
-    }
-
-    return get_obj_fd( &current->process->console->active->obj );
+    struct console_output *console_output = (struct console_output *)obj;
+    assert( obj->ops == &console_output_ops );
+    return (struct fd *)grab_object( console_output->fd );
 }
 
 static struct object *console_output_open_file( struct object *obj, unsigned int access,
@@ -1407,6 +1437,38 @@ static struct object *console_output_open_file( struct object *obj, unsigned int
     return grab_object( obj );
 }
 
+static void console_output_destroy( struct object *obj )
+{
+    struct console_output *console_output = (struct console_output *)obj;
+
+    assert( obj->ops == &console_output_ops );
+    if (console_output->fd) release_object( console_output->fd );
+}
+
+static int console_output_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
+{
+    struct console *console = current->process->console;
+
+    if (!console || !console->active)
+    {
+        set_error( STATUS_INVALID_HANDLE );
+        return 0;
+    }
+    return screen_buffer_ioctl( console->active->fd, code, async );
+}
+
+static int console_output_write( struct fd *fd, struct async *async, file_pos_t pos )
+{
+    struct console *console = current->process->console;
+
+    if (!console || !console->active)
+    {
+        set_error( STATUS_INVALID_HANDLE );
+        return 0;
+    }
+    return screen_buffer_write( console->active->fd, async, pos );
+}
+
 struct object *create_console_device( struct object *root, const struct unicode_str *name,
                                       unsigned int attr, const struct security_descriptor *sd )
 {




More information about the wine-cvs mailing list