Jacek Caban : server: Introduce IOCTL_CONDRV_GET_RENDERER_EVENTS ioctl.

Alexandre Julliard julliard at winehq.org
Wed Jul 8 15:34:36 CDT 2020


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Jul  8 16:29:36 2020 +0200

server: Introduce IOCTL_CONDRV_GET_RENDERER_EVENTS ioctl.

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

---

 include/wine/condrv.h |  3 +++
 server/console.c      | 62 +++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/include/wine/condrv.h b/include/wine/condrv.h
index f0f6d2ea58..c713ce7314 100644
--- a/include/wine/condrv.h
+++ b/include/wine/condrv.h
@@ -29,6 +29,9 @@
 #define IOCTL_CONDRV_PEEK                  CTL_CODE(FILE_DEVICE_CONSOLE, 12, METHOD_BUFFERED, FILE_READ_ACCESS)
 #define IOCTL_CONDRV_GET_INPUT_INFO        CTL_CODE(FILE_DEVICE_CONSOLE, 13, METHOD_BUFFERED, FILE_READ_PROPERTIES)
 
+/* console renderer ioctls */
+#define IOCTL_CONDRV_GET_RENDERER_EVENTS   CTL_CODE(FILE_DEVICE_CONSOLE, 70, METHOD_BUFFERED, FILE_READ_PROPERTIES)
+
 /* IOCTL_CONDRV_GET_INPUT_INFO result */
 struct condrv_input_info
 {
diff --git a/server/console.c b/server/console.c
index ad15578374..a5925adf94 100644
--- a/server/console.c
+++ b/server/console.c
@@ -116,6 +116,7 @@ struct console_input_events
     int                            num_alloc;   /* number of allocated events */
     int                            num_used;    /* number of actually used events */
     struct console_renderer_event *events;
+    struct async_queue             read_q;      /* read queue */
 };
 
 static const struct object_ops console_input_events_ops =
@@ -141,6 +142,8 @@ static const struct object_ops console_input_events_ops =
     console_input_events_destroy      /* destroy */
 };
 
+static int console_input_events_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
+
 static const struct fd_ops console_input_events_fd_ops =
 {
     default_fd_get_poll_events,   /* get_poll_events */
@@ -151,7 +154,7 @@ static const struct fd_ops console_input_events_fd_ops =
     no_fd_flush,                  /* flush */
     no_fd_get_file_info,          /* get_file_info */
     no_fd_get_volume_info,        /* get_volume_info */
-    default_fd_ioctl,             /* ioctl */
+    console_input_events_ioctl,   /* ioctl */
     default_fd_queue_async,       /* queue_async */
     default_fd_reselect_async     /* reselect_async */
 };
@@ -300,6 +303,7 @@ static void console_input_events_destroy( struct object *obj )
 {
     struct console_input_events *evts = (struct console_input_events *)obj;
     assert( obj->ops == &console_input_events_ops );
+    free_async_queue( &evts->read_q );
     if (evts->fd) release_object( evts->fd );
     free( evts->events );
 }
@@ -319,12 +323,42 @@ static struct fd *console_input_events_get_fd( struct object* obj )
     return (struct fd*)grab_object( evts->fd );
 }
 
+/* retrieves events from the console's renderer events list */
+static int get_renderer_events( struct console_input_events* evts, struct async *async )
+{
+    struct iosb *iosb = async_get_iosb( async );
+    data_size_t num;
+
+    num = min( iosb->out_size / sizeof(evts->events[0]), evts->num_used );
+    if (num && !(iosb->out_data = malloc( num * sizeof(evts->events[0] ))))
+    {
+        async_terminate( async, STATUS_NO_MEMORY );
+        release_object( iosb );
+        return 0;
+    }
+
+    iosb->status = STATUS_SUCCESS;
+    iosb->out_size = iosb->result = num * sizeof(evts->events[0]);
+    if (num) memcpy( iosb->out_data, evts->events, iosb->result );
+    release_object( iosb );
+    async_terminate( async, STATUS_ALERTED );
+
+    if (num && num < evts->num_used)
+    {
+        memmove( &evts->events[0], &evts->events[num],
+                 (evts->num_used - num) * sizeof(evts->events[0]) );
+    }
+    evts->num_used -= num;
+    return 1;
+}
+
 /* add an event to the console's renderer events list */
 static void console_input_events_append( struct console_input* console,
 					 struct console_renderer_event* evt)
 {
     struct console_input_events* evts;
     int collapsed = FALSE;
+    struct async *async;
 
     if (!(evts = console->evt)) return;
     /* to be done even when evt has been generated by the renderer ? */
@@ -357,7 +391,12 @@ static void console_input_events_append( struct console_input* console,
         }
         evts->events[evts->num_used++] = *evt;
     }
-    wake_up( &evts->obj, 0 );
+    while (evts->num_used && (async = find_pending_async( &evts->read_q )))
+    {
+        get_renderer_events( evts, async );
+        release_object( async );
+    }
+    if (evts->num_used) wake_up( &evts->obj, 0 );
 }
 
 /* retrieves events from the console's renderer events list */
@@ -382,6 +421,7 @@ static struct console_input_events *create_console_input_events(void)
     if (!(evt = alloc_object( &console_input_events_ops ))) return NULL;
     evt->num_alloc = evt->num_used = 0;
     evt->events = NULL;
+    init_async_queue( &evt->read_q );
     if (!(evt->fd = alloc_pseudo_fd( &console_input_events_fd_ops, &evt->obj, 0 )))
     {
         release_object( evt );
@@ -1600,6 +1640,24 @@ static int console_ioctl( struct fd *fd, ioctl_code_t code, struct async *async
     }
 }
 
+static int console_input_events_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
+{
+    struct console_input_events *evts = get_fd_user( fd );
+
+    switch (code)
+    {
+    case IOCTL_CONDRV_GET_RENDERER_EVENTS:
+        set_error( STATUS_PENDING );
+        if (evts->num_used) return get_renderer_events( evts, async );
+        queue_async( &evts->read_q, async );
+        return 1;
+
+    default:
+        set_error( STATUS_INVALID_HANDLE );
+        return 0;
+    }
+}
+
 static struct object_type *console_device_get_type( struct object *obj )
 {
     static const WCHAR name[] = {'D','e','v','i','c','e'};




More information about the wine-cvs mailing list