server: Introduce IOCTL_CONDRV_WRITE_OUTPUT ioctl.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
29288c0bc0
commit
5b795b658d
|
@ -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_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)
|
||||
#define IOCTL_CONDRV_ACTIVATE CTL_CODE(FILE_DEVICE_CONSOLE, 34, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
|
@ -82,6 +83,16 @@ struct condrv_input_info_params
|
|||
struct condrv_input_info info; /* input_info */
|
||||
};
|
||||
|
||||
/* IOCTL_CONDRV_WRITE_OUTPUT */
|
||||
struct condrv_write_output_params
|
||||
{
|
||||
unsigned int x; /* destination position */
|
||||
unsigned int y;
|
||||
unsigned int mode; /* char info mode */
|
||||
unsigned int width; /* width of output rectangle, 0 for wrapped mode */
|
||||
/* followed by an array of data with type depending on mode */
|
||||
};
|
||||
|
||||
/* IOCTL_CONDRV_GET_OUTPUT_INFO result */
|
||||
struct condrv_output_info
|
||||
{
|
||||
|
|
|
@ -1249,7 +1249,85 @@ static struct fd *screen_buffer_get_fd( struct object *obj )
|
|||
}
|
||||
|
||||
/* write data into a screen buffer */
|
||||
static int write_console_output( struct screen_buffer *screen_buffer, data_size_t size,
|
||||
static void write_console_output( struct screen_buffer *screen_buffer, const struct condrv_write_output_params *params,
|
||||
data_size_t size )
|
||||
{
|
||||
unsigned int i, entry_size, entry_cnt, x, y;
|
||||
char_info_t *dest;
|
||||
char *src;
|
||||
|
||||
entry_size = params->mode == CHAR_INFO_MODE_TEXTATTR ? sizeof(char_info_t) : sizeof(WCHAR);
|
||||
if (size % entry_size)
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
if (params->x >= screen_buffer->width) return;
|
||||
entry_cnt = size / entry_size;
|
||||
|
||||
for (i = 0, src = (char *)(params + 1); i < entry_cnt; i++, src += entry_size)
|
||||
{
|
||||
if (params->width)
|
||||
{
|
||||
x = params->x + i % params->width;
|
||||
y = params->y + i / params->width;
|
||||
if (x >= screen_buffer->width) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = (params->x + i) % screen_buffer->width;
|
||||
y = params->y + (params->x + i) / screen_buffer->width;
|
||||
}
|
||||
if (y >= screen_buffer->height) break;
|
||||
|
||||
dest = &screen_buffer->data[y * screen_buffer->width + x];
|
||||
switch(params->mode)
|
||||
{
|
||||
case CHAR_INFO_MODE_TEXT:
|
||||
dest->ch = *(const WCHAR *)src;
|
||||
break;
|
||||
case CHAR_INFO_MODE_ATTR:
|
||||
dest->attr = *(const unsigned short *)src;
|
||||
break;
|
||||
case CHAR_INFO_MODE_TEXTATTR:
|
||||
*dest = *(const char_info_t *)src;
|
||||
break;
|
||||
case CHAR_INFO_MODE_TEXTSTDATTR:
|
||||
dest->ch = *(const WCHAR *)src;
|
||||
dest->attr = screen_buffer->attr;
|
||||
break;
|
||||
default:
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (i && screen_buffer == screen_buffer->input->active)
|
||||
{
|
||||
struct condrv_renderer_event evt;
|
||||
evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
|
||||
memset(&evt.u, 0, sizeof(evt.u));
|
||||
evt.u.update.top = params->y;
|
||||
evt.u.update.bottom = params->width
|
||||
? min( params->y + entry_cnt / params->width, screen_buffer->height ) - 1
|
||||
: params->y + (params->x + i - 1) / screen_buffer->width;
|
||||
console_input_events_append( screen_buffer->input, &evt );
|
||||
}
|
||||
|
||||
if (get_reply_max_size() == sizeof(SMALL_RECT))
|
||||
{
|
||||
SMALL_RECT region;
|
||||
region.Left = params->x;
|
||||
region.Top = params->y;
|
||||
region.Right = min( params->x + params->width, screen_buffer->width ) - 1;
|
||||
region.Bottom = min( params->y + entry_cnt / params->width, screen_buffer->height ) - 1;
|
||||
set_reply_data( ®ion, sizeof(region) );
|
||||
}
|
||||
else set_reply_data( &i, sizeof(i) );
|
||||
}
|
||||
|
||||
/* write data into a screen buffer */
|
||||
static int write_console_output_req( struct screen_buffer *screen_buffer, data_size_t size,
|
||||
const void* data, enum char_info_mode mode,
|
||||
int x, int y, int wrap )
|
||||
{
|
||||
|
@ -1660,6 +1738,21 @@ 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_WRITE_OUTPUT:
|
||||
if (get_req_data_size() < sizeof(struct condrv_write_output_params) ||
|
||||
(get_reply_max_size() != sizeof(SMALL_RECT) && get_reply_max_size() != sizeof(unsigned int)))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
if (console_input_is_bare( screen_buffer->input ))
|
||||
{
|
||||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
return 0;
|
||||
}
|
||||
write_console_output( screen_buffer, get_req_data(), get_req_data_size() - sizeof(struct condrv_write_output_params) );
|
||||
return !get_error();
|
||||
|
||||
case IOCTL_CONDRV_GET_OUTPUT_INFO:
|
||||
{
|
||||
struct condrv_output_info *info;
|
||||
|
@ -2140,8 +2233,8 @@ DECL_HANDLER(write_console_output)
|
|||
release_object( screen_buffer );
|
||||
return;
|
||||
}
|
||||
reply->written = write_console_output( screen_buffer, get_req_data_size(), get_req_data(),
|
||||
req->mode, req->x, req->y, req->wrap );
|
||||
reply->written = write_console_output_req( screen_buffer, get_req_data_size(), get_req_data(),
|
||||
req->mode, req->x, req->y, req->wrap );
|
||||
reply->width = screen_buffer->width;
|
||||
reply->height = screen_buffer->height;
|
||||
release_object( screen_buffer );
|
||||
|
|
|
@ -127,6 +127,7 @@ static void dump_ioctl_code( const char *prefix, const ioctl_code_t *code )
|
|||
CASE(IOCTL_CONDRV_SET_MODE);
|
||||
CASE(IOCTL_CONDRV_SET_OUTPUT_INFO);
|
||||
CASE(IOCTL_CONDRV_WRITE_INPUT);
|
||||
CASE(IOCTL_CONDRV_WRITE_OUTPUT);
|
||||
CASE(FSCTL_DISMOUNT_VOLUME);
|
||||
CASE(FSCTL_PIPE_DISCONNECT);
|
||||
CASE(FSCTL_PIPE_LISTEN);
|
||||
|
|
Loading…
Reference in New Issue