Module: wine Branch: master Commit: f4661f1b38c479bd08baee93d9ddb1f9e93c173d URL: https://source.winehq.org/git/wine.git/?a=commit;h=f4661f1b38c479bd08baee93d...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Aug 28 14:27:05 2020 +0200
conhost: Implement IOCTL_CONDRV_READ_OUTPUT.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
programs/conhost/conhost.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index 4fbfc19a08..d17a8f4e68 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -545,6 +545,84 @@ static NTSTATUS write_output( struct screen_buffer *screen_buffer, const struct return STATUS_SUCCESS; }
+static NTSTATUS read_output( struct screen_buffer *screen_buffer, const struct condrv_output_params *params, + size_t *out_size ) +{ + enum char_info_mode mode; + unsigned int x, y, width; + unsigned int i, count; + + x = params->x; + y = params->y; + mode = params->mode; + width = params->width; + TRACE( "(%u %u) mode %u width %u\n", x, y, mode, width ); + + switch(mode) + { + case CHAR_INFO_MODE_TEXT: + { + WCHAR *data; + char_info_t *src; + if (x >= screen_buffer->width || y >= screen_buffer->height) + { + *out_size = 0; + return STATUS_SUCCESS; + } + src = screen_buffer->data + y * screen_buffer->width + x; + count = min( screen_buffer->data + screen_buffer->height * screen_buffer->width - src, + *out_size / sizeof(*data) ); + *out_size = count * sizeof(*data); + if (!(data = alloc_ioctl_buffer( *out_size ))) return STATUS_NO_MEMORY; + for (i = 0; i < count; i++) data[i] = src[i].ch; + } + break; + case CHAR_INFO_MODE_ATTR: + { + unsigned short *data; + char_info_t *src; + if (x >= screen_buffer->width || y >= screen_buffer->height) + { + *out_size = 0; + return STATUS_SUCCESS; + } + src = screen_buffer->data + y * screen_buffer->width + x; + count = min( screen_buffer->data + screen_buffer->height * screen_buffer->width - src, + *out_size / sizeof(*data) ); + *out_size = count * sizeof(*data); + if (!(data = alloc_ioctl_buffer( *out_size ))) return STATUS_NO_MEMORY; + for (i = 0; i < count; i++) data[i] = src[i].attr; + } + break; + case CHAR_INFO_MODE_TEXTATTR: + { + SMALL_RECT *region; + char_info_t *data; + if (!width || *out_size < sizeof(*region) || x >= screen_buffer->width || y >= screen_buffer->height) + return STATUS_INVALID_PARAMETER; + count = min( (*out_size - sizeof(*region)) / (width * sizeof(*data)), screen_buffer->height - y ); + width = min( width, screen_buffer->width - x ); + *out_size = sizeof(*region) + width * count * sizeof(*data); + if (!(region = alloc_ioctl_buffer( *out_size ))) return STATUS_NO_MEMORY; + region->Left = x; + region->Top = y; + region->Right = x + width - 1; + region->Bottom = y + count - 1; + data = (char_info_t *)(region + 1); + for (i = 0; i < count; i++) + { + memcpy( &data[i * width], &screen_buffer->data[(y + i) * screen_buffer->width + x], + width * sizeof(*data) ); + } + } + break; + default: + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + static NTSTATUS set_console_title( struct console *console, const WCHAR *in_title, size_t size ) { WCHAR *title = NULL; @@ -599,6 +677,10 @@ static NTSTATUS screen_buffer_ioctl( struct screen_buffer *screen_buffer, unsign return STATUS_INVALID_PARAMETER; return write_output( screen_buffer, in_data, in_size, out_size );
+ case IOCTL_CONDRV_READ_OUTPUT: + if (in_size != sizeof(struct condrv_output_params)) return STATUS_INVALID_PARAMETER; + return read_output( screen_buffer, in_data, out_size ); + case IOCTL_CONDRV_GET_OUTPUT_INFO: if (in_size || *out_size < sizeof(struct condrv_output_info)) return STATUS_INVALID_PARAMETER; return get_output_info( screen_buffer, out_size );