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)
|
#define IOCTL_CONDRV_SET_TITLE CTL_CODE(FILE_DEVICE_CONSOLE, 16, METHOD_BUFFERED, FILE_WRITE_PROPERTIES)
|
||||||
|
|
||||||
/* console output ioctls */
|
/* 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_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_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)
|
#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 */
|
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 */
|
/* IOCTL_CONDRV_GET_OUTPUT_INFO result */
|
||||||
struct condrv_output_info
|
struct condrv_output_info
|
||||||
{
|
{
|
||||||
|
|
|
@ -1249,7 +1249,85 @@ static struct fd *screen_buffer_get_fd( struct object *obj )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write data into a screen buffer */
|
/* 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,
|
const void* data, enum char_info_mode mode,
|
||||||
int x, int y, int wrap )
|
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();
|
screen_buffer->mode = *(unsigned int *)get_req_data();
|
||||||
return 1;
|
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:
|
case IOCTL_CONDRV_GET_OUTPUT_INFO:
|
||||||
{
|
{
|
||||||
struct condrv_output_info *info;
|
struct condrv_output_info *info;
|
||||||
|
@ -2140,7 +2233,7 @@ DECL_HANDLER(write_console_output)
|
||||||
release_object( screen_buffer );
|
release_object( screen_buffer );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
reply->written = write_console_output( screen_buffer, get_req_data_size(), get_req_data(),
|
reply->written = write_console_output_req( screen_buffer, get_req_data_size(), get_req_data(),
|
||||||
req->mode, req->x, req->y, req->wrap );
|
req->mode, req->x, req->y, req->wrap );
|
||||||
reply->width = screen_buffer->width;
|
reply->width = screen_buffer->width;
|
||||||
reply->height = screen_buffer->height;
|
reply->height = screen_buffer->height;
|
||||||
|
|
|
@ -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_MODE);
|
||||||
CASE(IOCTL_CONDRV_SET_OUTPUT_INFO);
|
CASE(IOCTL_CONDRV_SET_OUTPUT_INFO);
|
||||||
CASE(IOCTL_CONDRV_WRITE_INPUT);
|
CASE(IOCTL_CONDRV_WRITE_INPUT);
|
||||||
|
CASE(IOCTL_CONDRV_WRITE_OUTPUT);
|
||||||
CASE(FSCTL_DISMOUNT_VOLUME);
|
CASE(FSCTL_DISMOUNT_VOLUME);
|
||||||
CASE(FSCTL_PIPE_DISCONNECT);
|
CASE(FSCTL_PIPE_DISCONNECT);
|
||||||
CASE(FSCTL_PIPE_LISTEN);
|
CASE(FSCTL_PIPE_LISTEN);
|
||||||
|
|
Loading…
Reference in New Issue