Jacek Caban : server: Introduce IOCTL_CONDRV_READ_OUTPUT ioctl.
Alexandre Julliard
julliard at winehq.org
Tue Jul 28 15:53:31 CDT 2020
Module: wine
Branch: master
Commit: 44052219aa0e6412a0f595f830c0cdf6e82ea70c
URL: https://source.winehq.org/git/wine.git/?a=commit;h=44052219aa0e6412a0f595f830c0cdf6e82ea70c
Author: Jacek Caban <jacek at codeweavers.com>
Date: Tue Jul 28 17:10:23 2020 +0200
server: Introduce IOCTL_CONDRV_READ_OUTPUT 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 | 90 +++++++++++++++++++++++++++++++++++++++++++++++++--
server/trace.c | 1 +
3 files changed, 90 insertions(+), 4 deletions(-)
diff --git a/include/wine/condrv.h b/include/wine/condrv.h
index a47a4f2775..839db84ea5 100644
--- a/include/wine/condrv.h
+++ b/include/wine/condrv.h
@@ -37,6 +37,7 @@
#define IOCTL_CONDRV_SET_TITLE CTL_CODE(FILE_DEVICE_CONSOLE, 16, METHOD_BUFFERED, FILE_WRITE_PROPERTIES)
/* console output ioctls */
+#define IOCTL_CONDRV_READ_OUTPUT CTL_CODE(FILE_DEVICE_CONSOLE, 30, METHOD_BUFFERED, FILE_READ_DATA)
#define IOCTL_CONDRV_WRITE_OUTPUT CTL_CODE(FILE_DEVICE_CONSOLE, 31, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_CONDRV_GET_OUTPUT_INFO CTL_CODE(FILE_DEVICE_CONSOLE, 32, METHOD_BUFFERED, FILE_READ_PROPERTIES)
#define IOCTL_CONDRV_SET_OUTPUT_INFO CTL_CODE(FILE_DEVICE_CONSOLE, 33, METHOD_BUFFERED, FILE_WRITE_PROPERTIES)
@@ -83,7 +84,7 @@ struct condrv_input_info_params
struct condrv_input_info info; /* input_info */
};
-/* IOCTL_CONDRV_WRITE_OUTPUT */
+/* IOCTL_CONDRV_WRITE_OUTPUT and IOCTL_CONDRV_READ_OUTPUT params */
struct condrv_output_params
{
unsigned int x; /* destination position */
diff --git a/server/console.c b/server/console.c
index 14fbd67e22..207e333ec3 100644
--- a/server/console.c
+++ b/server/console.c
@@ -1248,6 +1248,73 @@ static struct fd *screen_buffer_get_fd( struct object *obj )
return NULL;
}
+/* read data from a screen buffer */
+static void read_console_output( struct screen_buffer *screen_buffer, unsigned int x, unsigned int y,
+ enum char_info_mode mode, unsigned int width )
+{
+ unsigned int i, count;
+ char_info_t *src;
+
+ if (x >= screen_buffer->width || y >= screen_buffer->height)
+ {
+ if (width) set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+ src = screen_buffer->data + y * screen_buffer->width + x;
+
+ switch(mode)
+ {
+ case CHAR_INFO_MODE_TEXT:
+ {
+ WCHAR *data;
+ count = min( screen_buffer->data + screen_buffer->height * screen_buffer->width - src,
+ get_reply_max_size() / sizeof(*data) );
+ if ((data = set_reply_data_size( count * sizeof(*data) )))
+ {
+ for (i = 0; i < count; i++) data[i] = src[i].ch;
+ }
+ }
+ break;
+ case CHAR_INFO_MODE_ATTR:
+ {
+ unsigned short *data;
+ count = min( screen_buffer->data + screen_buffer->height * screen_buffer->width - src,
+ get_reply_max_size() / sizeof(*data) );
+ if ((data = set_reply_data_size( count * sizeof(*data) )))
+ {
+ for (i = 0; i < count; i++) data[i] = src[i].attr;
+ }
+ }
+ break;
+ case CHAR_INFO_MODE_TEXTATTR:
+ {
+ char_info_t *data;
+ SMALL_RECT *region;
+ if (!width || get_reply_max_size() < sizeof(*region))
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+ count = min( (get_reply_max_size() - sizeof(*region)) / (width * sizeof(*data)), screen_buffer->height - y );
+ width = min( width, screen_buffer->width - x );
+ if (!(region = set_reply_data_size( sizeof(*region) + width * count * sizeof(*data) ))) return;
+ 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], &src[i * screen_buffer->width], width * sizeof(*data) );
+ }
+ }
+ break;
+ default:
+ set_error( STATUS_INVALID_PARAMETER );
+ break;
+ }
+}
+
/* write data into a screen buffer */
static void write_console_output( struct screen_buffer *screen_buffer, const struct condrv_output_params *params,
data_size_t size )
@@ -1378,8 +1445,8 @@ static int fill_console_output( struct screen_buffer *screen_buffer, char_info_t
}
/* read data from a screen buffer */
-static void read_console_output( struct screen_buffer *screen_buffer, int x, int y,
- enum char_info_mode mode, int wrap )
+static void read_console_output_req( struct screen_buffer *screen_buffer, int x, int y,
+ enum char_info_mode mode, int wrap )
{
int i;
char_info_t *end, *src = screen_buffer->data + y * screen_buffer->width + x;
@@ -1676,6 +1743,23 @@ static int screen_buffer_ioctl( struct fd *fd, ioctl_code_t code, struct async *
screen_buffer->mode = *(unsigned int *)get_req_data();
return 1;
+ case IOCTL_CONDRV_READ_OUTPUT:
+ {
+ const struct condrv_output_params *params = get_req_data();
+ if (get_req_data_size() != sizeof(*params))
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return 0;
+ }
+ if (console_input_is_bare( screen_buffer->input ))
+ {
+ set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ return 0;
+ }
+ read_console_output( screen_buffer, params->x, params->y, params->mode, params->width );
+ return !get_error();
+ }
+
case IOCTL_CONDRV_WRITE_OUTPUT:
if (get_req_data_size() < sizeof(struct condrv_output_params) ||
(get_reply_max_size() != sizeof(SMALL_RECT) && get_reply_max_size() != sizeof(unsigned int)))
@@ -2150,7 +2234,7 @@ DECL_HANDLER(read_console_output)
release_object( screen_buffer );
return;
}
- read_console_output( screen_buffer, req->x, req->y, req->mode, req->wrap );
+ read_console_output_req( screen_buffer, req->x, req->y, req->mode, req->wrap );
reply->width = screen_buffer->width;
reply->height = screen_buffer->height;
release_object( screen_buffer );
diff --git a/server/trace.c b/server/trace.c
index 7cff5bf5f4..ab5a40bef8 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -124,6 +124,7 @@ static void dump_ioctl_code( const char *prefix, const ioctl_code_t *code )
CASE(IOCTL_CONDRV_GET_TITLE);
CASE(IOCTL_CONDRV_PEEK);
CASE(IOCTL_CONDRV_READ_INPUT);
+ CASE(IOCTL_CONDRV_READ_OUTPUT);
CASE(IOCTL_CONDRV_SET_MODE);
CASE(IOCTL_CONDRV_SET_OUTPUT_INFO);
CASE(IOCTL_CONDRV_WRITE_INPUT);
More information about the wine-cvs
mailing list