server: Introduce IOCTL_CONDRV_READ_OUTPUT ioctl.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7a31d40139
commit
44052219aa
|
@ -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 */
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue