From 845156cc3dc8c8c6b1b62fcb57bcdfc25c94e100 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 8 Jul 2020 16:29:36 +0200 Subject: [PATCH] server: Introduce IOCTL_CONDRV_GET_RENDERER_EVENTS ioctl. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- 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 f0f6d2ea585..c713ce73141 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 ad15578374a..a5925adf94c 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'}; -- 2.11.4.GIT