Redesign of the server communication protocol to allow arbitrary sized
data to be exchanged.
Split request and reply structures to make backwards compatibility
easier.
Moved many console functions to dlls/kernel, added code page support,
changed a few requests to behave properly with the new protocol.
diff --git a/server/console.c b/server/console.c
index bd6dd39..4ea264e 100644
--- a/server/console.c
+++ b/server/console.c
@@ -13,10 +13,6 @@
#include <stdio.h>
#include <unistd.h>
-#include "winnt.h"
-#include "winbase.h"
-#include "wincon.h"
-
#include "handle.h"
#include "process.h"
#include "request.h"
@@ -29,7 +25,7 @@
static int console_input_signaled( struct object *obj, struct thread *thread );
/* common routine */
-static int console_get_file_info( struct object *obj, struct get_file_info_request *req );
+static int console_get_file_info( struct object *obj, struct get_file_info_reply *reply );
static const struct object_ops console_input_ops =
{
@@ -78,19 +74,21 @@
struct screen_buffer
{
struct object obj; /* object header */
- int mode; /* output mode */
- struct console_input *input; /* associated console input */
struct screen_buffer *next; /* linked list of all screen buffers */
- short int cursor_size; /* size of cursor (percentage filled) */
- short int cursor_visible;/* cursor visibility flag */
- COORD cursor; /* position of cursor */
- short int width; /* size (w-h) of the screen buffer */
- short int height;
- short int max_width; /* size (w-h) of the window given font size */
- short int max_height;
- unsigned *data; /* the data for each cell - a width x height matrix */
+ struct screen_buffer *prev;
+ struct console_input *input; /* associated console input */
+ int mode; /* output mode */
+ int cursor_size; /* size of cursor (percentage filled) */
+ int cursor_visible;/* cursor visibility flag */
+ int cursor_x; /* position of cursor */
+ int cursor_y; /* position of cursor */
+ int width; /* size (w-h) of the screen buffer */
+ int height;
+ int max_width; /* size (w-h) of the window given font size */
+ int max_height;
+ char_info_t *data; /* the data for each cell - a width x height matrix */
unsigned short attr; /* default attribute for screen buffer */
- SMALL_RECT win; /* current visible window on the screen buffer *
+ rectangle_t win; /* current visible window on the screen buffer *
* as seen in wineconsole */
};
@@ -115,6 +113,8 @@
static struct screen_buffer *screen_buffer_list;
+static const char_info_t empty_char_info = { ' ', 0x00f0 }; /* white on black space */
+
/* dumps the renderer events of a console */
static void console_input_events_dump( struct object *obj, int verbose )
{
@@ -132,20 +132,18 @@
free( evts->events );
}
-/* the rendere events list is signaled when it's not empty */
-static int console_input_events_signaled( struct object *obj, struct thread *thread )
+/* the renderer events list is signaled when it's not empty */
+static int console_input_events_signaled( struct object *obj, struct thread *thread )
{
struct console_input_events *evts = (struct console_input_events *)obj;
assert( obj->ops == &console_input_events_ops );
- return evts->num_used ? 1 : 0;
+ return (evts->num_used != 0);
}
/* add an event to the console's renderer events list */
static void console_input_events_append( struct console_input_events* evts,
struct console_renderer_event* evt)
{
- if (!evt) return;
-
/* to be done even when the renderer generates the events ? */
if (evts->num_used == evts->num_alloc)
{
@@ -158,25 +156,18 @@
}
/* retrieves events from the console's renderer events list */
-static size_t console_input_events_get( struct console_input_events* evts,
- struct console_renderer_event* evt, size_t num )
+static void console_input_events_get( struct console_input_events* evts )
{
- if (num % sizeof(*evt) != 0)
- {
- set_error( STATUS_INVALID_PARAMETER );
- return 0;
- }
- num /= sizeof(*evt);
- if (num > evts->num_used)
- num = evts->num_used;
- memcpy( evt, evts->events, num * sizeof(*evt) );
+ size_t num = get_reply_max_size() / sizeof(evts->events[0]);
+
+ if (num > evts->num_used) num = evts->num_used;
+ set_reply_data( evts->events, num * sizeof(evts->events[0]) );
if (num < evts->num_used)
{
- memmove( &evts->events[0], &evts->events[num],
- (evts->num_used - num) * sizeof(*evt) );
+ memmove( &evts->events[0], &evts->events[num],
+ (evts->num_used - num) * sizeof(evts->events[0]) );
}
evts->num_used -= num;
- return num * sizeof(struct console_renderer_event);
}
static struct console_input_events *create_console_input_events(void)
@@ -216,7 +207,7 @@
return &console_input->obj;
}
-static struct object *create_console_output( struct console_input *console_input )
+static struct screen_buffer *create_console_output( struct console_input *console_input )
{
struct screen_buffer *screen_buffer;
struct console_renderer_event evt;
@@ -231,23 +222,31 @@
screen_buffer->height = 150;
screen_buffer->max_width = 80;
screen_buffer->max_height = 25;
- screen_buffer->data = malloc( 4 * screen_buffer->width * screen_buffer->height );
- /* fill the buffer with white on black spaces */
- for (i = 0; i < screen_buffer->width * screen_buffer->height; i++)
- {
- screen_buffer->data[i] = 0x00F00020;
- }
- screen_buffer->cursor.X = 0;
- screen_buffer->cursor.Y = 0;
+ screen_buffer->cursor_x = 0;
+ screen_buffer->cursor_y = 0;
screen_buffer->attr = 0xF0;
- screen_buffer->win.Left = 0;
- screen_buffer->win.Right = screen_buffer->max_width - 1;
- screen_buffer->win.Top = 0;
- screen_buffer->win.Bottom = screen_buffer->max_height - 1;
+ screen_buffer->win.left = 0;
+ screen_buffer->win.right = screen_buffer->max_width - 1;
+ screen_buffer->win.top = 0;
+ screen_buffer->win.bottom = screen_buffer->max_height - 1;
- screen_buffer->next = screen_buffer_list;
+ if ((screen_buffer->next = screen_buffer_list)) screen_buffer->next->prev = screen_buffer;
+ screen_buffer->prev = NULL;
screen_buffer_list = screen_buffer;
+ if (!(screen_buffer->data = malloc( screen_buffer->width * screen_buffer->height *
+ sizeof(*screen_buffer->data) )))
+ {
+ release_object( screen_buffer );
+ return NULL;
+ }
+ /* clear the first row */
+ for (i = 0; i < screen_buffer->width; i++) screen_buffer->data[i] = empty_char_info;
+ /* and copy it to all other rows */
+ for (i = 1; i < screen_buffer->height; i++)
+ memcpy( &screen_buffer->data[i * screen_buffer->width], screen_buffer->data,
+ screen_buffer->width * sizeof(char_info_t) );
+
if (!console_input->active)
{
console_input->active = (struct screen_buffer*)grab_object( screen_buffer );
@@ -262,10 +261,10 @@
console_input_events_append( console_input->evt, &evt );
evt.event = CONSOLE_RENDERER_DISPLAY_EVENT;
- evt.u.display.left = screen_buffer->win.Left;
- evt.u.display.top = screen_buffer->win.Top;
- evt.u.display.width = screen_buffer->win.Right - screen_buffer->win.Left + 1;
- evt.u.display.height = screen_buffer->win.Bottom - screen_buffer->win.Top + 1;
+ evt.u.display.left = screen_buffer->win.left;
+ evt.u.display.top = screen_buffer->win.top;
+ evt.u.display.width = screen_buffer->win.right - screen_buffer->win.left + 1;
+ evt.u.display.height = screen_buffer->win.bottom - screen_buffer->win.top + 1;
console_input_events_append( console_input->evt, &evt );
evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
@@ -279,12 +278,11 @@
console_input_events_append( console_input->evt, &evt );
evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
- evt.u.cursor_pos.x = screen_buffer->cursor.X;
- evt.u.cursor_pos.y = screen_buffer->cursor.Y;
+ evt.u.cursor_pos.x = screen_buffer->cursor_x;
+ evt.u.cursor_pos.y = screen_buffer->cursor_y;
console_input_events_append( console_input->evt, &evt );
}
-
- return &screen_buffer->obj;
+ return screen_buffer;
}
/* free the console for this process */
@@ -411,11 +409,12 @@
}
/* add input events to a console input queue */
-static int write_console_input( struct console_input* console, int count, INPUT_RECORD *records )
+static int write_console_input( struct console_input* console, int count,
+ const INPUT_RECORD *records )
{
INPUT_RECORD *new_rec;
- assert(count);
+ if (!count) return 0;
if (!(new_rec = realloc( console->records,
(console->recnum + count) * sizeof(INPUT_RECORD) )))
{
@@ -433,7 +432,7 @@
}
/* retrieve a pointer to the console input records */
-static int read_console_input( handle_t handle, int count, INPUT_RECORD *rec, int flush )
+static int read_console_input( handle_t handle, int count, int flush )
{
struct console_input *console;
@@ -450,13 +449,13 @@
else
{
if (count > console->recnum) count = console->recnum;
- memcpy( rec, console->records, count * sizeof(INPUT_RECORD) );
+ set_reply_data( console->records, count * sizeof(INPUT_RECORD) );
}
if (flush)
{
int i;
for (i = count; i < console->recnum; i++)
- ((INPUT_RECORD*)console->records)[i-count] = ((INPUT_RECORD*)console->records)[i];
+ console->records[i-count] = console->records[i];
if ((console->recnum -= count) > 0)
{
INPUT_RECORD *new_rec = realloc( console->records,
@@ -474,7 +473,7 @@
}
/* set misc console input information */
-static int set_console_input_info( struct set_console_input_info_request *req,
+static int set_console_input_info( const struct set_console_input_info_request *req,
const WCHAR *title, size_t len )
{
struct console_input *console;
@@ -557,9 +556,61 @@
return 0;
}
+/* resize a screen buffer */
+static int change_screen_buffer_size( struct screen_buffer *screen_buffer,
+ int new_width, int new_height )
+{
+ int i, old_width, old_height, copy_width, copy_height;
+ char_info_t *new_data;
+
+ if (!(new_data = malloc( new_width * new_height * sizeof(*new_data) )))
+ {
+ set_error( STATUS_NO_MEMORY );
+ return 0;
+ }
+ old_width = screen_buffer->width;
+ old_height = screen_buffer->height;
+ copy_width = min( old_width, new_width );
+ copy_height = min( old_height, new_height );
+
+ /* copy all the rows */
+ for (i = 0; i < copy_height; i++)
+ {
+ memcpy( &new_data[i * new_width], &screen_buffer->data[i * old_width],
+ copy_width * sizeof(char_info_t) );
+ }
+
+ /* clear the end of each row */
+ if (new_width > old_width)
+ {
+ /* fill first row */
+ for (i = old_width; i < new_width; i++) new_data[i] = empty_char_info;
+ /* and blast it to the other rows */
+ for (i = 1; i < copy_height; i++)
+ memcpy( &new_data[i * new_width + old_width], &new_data[old_width],
+ (new_width - old_width) * sizeof(char_info_t) );
+ }
+
+ /* clear remaining rows */
+ if (new_height > old_height)
+ {
+ /* fill first row */
+ for (i = 0; i < new_width; i++) new_data[old_height * new_width + i] = empty_char_info;
+ /* and blast it to the other rows */
+ for (i = old_height+1; i < new_height; i++)
+ memcpy( &new_data[i * new_width], &new_data[old_height * new_width],
+ new_width * sizeof(char_info_t) );
+ }
+ free( screen_buffer->data );
+ screen_buffer->data = new_data;
+ screen_buffer->width = new_width;
+ screen_buffer->height = new_height;
+ return 1;
+}
+
/* set misc screen buffer information */
-static int set_console_output_info( struct screen_buffer *screen_buffer,
- struct set_console_output_info_request *req )
+static int set_console_output_info( struct screen_buffer *screen_buffer,
+ const struct set_console_output_info_request *req )
{
struct console_renderer_event evt;
@@ -589,10 +640,10 @@
set_error( STATUS_INVALID_PARAMETER );
return 0;
}
- if (screen_buffer->cursor.X != req->cursor_x || screen_buffer->cursor.Y != req->cursor_y)
+ if (screen_buffer->cursor_x != req->cursor_x || screen_buffer->cursor_y != req->cursor_y)
{
- screen_buffer->cursor.X = req->cursor_x;
- screen_buffer->cursor.Y = req->cursor_y;
+ screen_buffer->cursor_x = req->cursor_x;
+ screen_buffer->cursor_y = req->cursor_y;
evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
evt.u.cursor_pos.x = req->cursor_x;
evt.u.cursor_pos.y = req->cursor_y;
@@ -601,26 +652,9 @@
}
if (req->mask & SET_CONSOLE_OUTPUT_INFO_SIZE)
{
- int i, j;
- /* FIXME: there are also some basic minimum and max size to deal with */
- unsigned* new_data = mem_alloc( 4 * req->width * req->height );
+ /* FIXME: there are also some basic minimum and max size to deal with */
+ if (!change_screen_buffer_size( screen_buffer, req->width, req->height )) return 0;
- if (!new_data) return 0;
-
- /* fill the buffer with either the old buffer content or white on black spaces */
- for (j = 0; j < req->height; j++)
- {
- for (i = 0; i < req->width; i++)
- {
- new_data[j * req->width + i] =
- (i < screen_buffer->width && j < screen_buffer->height) ?
- screen_buffer->data[j * screen_buffer->width + i] : 0x00F00020;
- }
- }
- free( screen_buffer->data );
- screen_buffer->data = new_data;
- screen_buffer->width = req->width;
- screen_buffer->height = req->height;
evt.event = CONSOLE_RENDERER_SB_RESIZE_EVENT;
evt.u.resize.width = req->width;
evt.u.resize.height = req->height;
@@ -650,13 +684,13 @@
set_error( STATUS_INVALID_PARAMETER );
return 0;
}
- if (screen_buffer->win.Left != req->win_left || screen_buffer->win.Top != req->win_top ||
- screen_buffer->win.Right != req->win_right || screen_buffer->win.Bottom != req->win_bottom)
+ if (screen_buffer->win.left != req->win_left || screen_buffer->win.top != req->win_top ||
+ screen_buffer->win.right != req->win_right || screen_buffer->win.bottom != req->win_bottom)
{
- screen_buffer->win.Left = req->win_left;
- screen_buffer->win.Top = req->win_top;
- screen_buffer->win.Right = req->win_right;
- screen_buffer->win.Bottom = req->win_bottom;
+ screen_buffer->win.left = req->win_left;
+ screen_buffer->win.top = req->win_top;
+ screen_buffer->win.right = req->win_right;
+ screen_buffer->win.bottom = req->win_bottom;
evt.event = CONSOLE_RENDERER_DISPLAY_EVENT;
evt.u.display.left = req->win_left;
evt.u.display.top = req->win_top;
@@ -725,18 +759,16 @@
}
/* returns a line from the cachde */
-static int console_input_get_hist( struct console_input* console, WCHAR* buf, size_t len, int index )
+static size_t console_input_get_hist( struct console_input *console, int index )
{
- int ret;
+ size_t ret = 0;
- /* FIXME: don't use len yet */
- if (!console || index >= console->history_index)
+ if (index >= console->history_index) set_error( STATUS_INVALID_PARAMETER );
+ else
{
- set_error( STATUS_INVALID_PARAMETER );
- return 0;
+ ret = strlenW( console->history[index] ) * sizeof(WCHAR);
+ set_reply_data( console->history[index], min( ret, get_reply_max_size() ));
}
- ret = strlenW(console->history[index]);
- memcpy( buf, console->history[index], ret * sizeof(WCHAR) ); /* FIXME should use len */
return ret;
}
@@ -749,20 +781,20 @@
console->active, console->evt );
}
-static int console_get_file_info( struct object *obj, struct get_file_info_request *req )
+static int console_get_file_info( struct object *obj, struct get_file_info_reply *reply )
{
- if (req)
+ if (reply)
{
- req->type = FILE_TYPE_CHAR;
- req->attr = 0;
- req->access_time = 0;
- req->write_time = 0;
- req->size_high = 0;
- req->size_low = 0;
- req->links = 0;
- req->index_high = 0;
- req->index_low = 0;
- req->serial = 0;
+ reply->type = FILE_TYPE_CHAR;
+ reply->attr = 0;
+ reply->access_time = 0;
+ reply->write_time = 0;
+ reply->size_high = 0;
+ reply->size_low = 0;
+ reply->links = 0;
+ reply->index_high = 0;
+ reply->index_low = 0;
+ reply->serial = 0;
}
return FD_TYPE_CONSOLE;
}
@@ -803,113 +835,193 @@
static void screen_buffer_destroy( struct object *obj )
{
- struct screen_buffer* screen_buffer = (struct screen_buffer *)obj;
- struct screen_buffer** psb;
+ struct screen_buffer *screen_buffer = (struct screen_buffer *)obj;
assert( obj->ops == &screen_buffer_ops );
- for (psb = &screen_buffer_list; *psb; *psb = (*psb)->next)
- {
- if (*psb == screen_buffer)
- {
- *psb = screen_buffer->next;
- break;
- }
- }
+ if (screen_buffer->next) screen_buffer->next->prev = screen_buffer->prev;
+ if (screen_buffer->prev) screen_buffer->prev->next = screen_buffer->next;
+ else screen_buffer_list = screen_buffer->next;
+
if (screen_buffer->input && screen_buffer->input->active == screen_buffer)
{
struct screen_buffer* sb;
for (sb = screen_buffer_list; sb && sb->input != screen_buffer->input; sb = sb->next);
screen_buffer->input->active = sb;
}
+ if (screen_buffer->data) free( screen_buffer->data );
}
/* write data into a screen buffer */
-static int write_console_output( struct screen_buffer *screen_buffer, size_t size,
- const unsigned char* data, int mode, short int x, short int y )
+static int write_console_output( struct screen_buffer *screen_buffer, size_t size,
+ const void* data, enum char_info_mode mode,
+ int x, int y, int wrap )
{
- int uniform = mode & WRITE_CONSOLE_MODE_UNIFORM;
- unsigned *ptr;
- unsigned i, inc;
- int len;
+ int i;
+ char_info_t *end, *dest = screen_buffer->data + y * screen_buffer->width + x;
- mode &= ~WRITE_CONSOLE_MODE_UNIFORM;
+ if (y >= screen_buffer->height) return 0;
- if (mode < 0 || mode > 3)
+ if (wrap)
+ end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
+ else
+ end = screen_buffer->data + (y+1) * screen_buffer->width;
+
+ switch(mode)
{
- set_error(STATUS_INVALID_PARAMETER);
- return 0;
+ case CHAR_INFO_MODE_TEXT:
+ {
+ const WCHAR *ptr = data;
+ for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) dest->ch = ptr[i];
+ }
+ break;
+ case CHAR_INFO_MODE_ATTR:
+ {
+ const unsigned short *ptr = data;
+ for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) dest->attr = ptr[i];
+ }
+ break;
+ case CHAR_INFO_MODE_TEXTATTR:
+ {
+ const char_info_t *ptr = data;
+ for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) *dest = ptr[i];
+ }
+ break;
+ case CHAR_INFO_MODE_TEXTSTDATTR:
+ {
+ const WCHAR *ptr = data;
+ for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++)
+ {
+ dest->ch = ptr[i];
+ dest->attr = screen_buffer->attr;
+ }
+ }
+ break;
+ default:
+ set_error( STATUS_INVALID_PARAMETER );
+ return 0;
}
- /* set destination pointer and increment */
- ptr = screen_buffer->data + (y * screen_buffer->width + x);
- if (mode == WRITE_CONSOLE_MODE_ATTR) ptr = (unsigned*)((char*)ptr + 2);
- inc = (mode == WRITE_CONSOLE_MODE_TEXTATTR) ? 4 : 2;
- len = size / inc;
-
- /* crop if needed */
- if (x + len > screen_buffer->width) len = screen_buffer->width - x;
-
- for (i = 0; i < len; i++)
+ if (i && screen_buffer == screen_buffer->input->active)
{
- if (mode == WRITE_CONSOLE_MODE_TEXTSTDATTR)
- {
- memcpy( (char*)ptr + 2, &screen_buffer->attr, 2 );
- }
- memcpy( ptr++, data, inc );
- if (!uniform) data += inc;
+ struct console_renderer_event evt;
+ evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
+ evt.u.update.top = y;
+ evt.u.update.bottom = (y * screen_buffer->width + x + i - 1) / screen_buffer->width;
+ console_input_events_append( screen_buffer->input->evt, &evt );
+ }
+ return i;
+}
+
+/* fill a screen buffer with uniform data */
+static int fill_console_output( struct screen_buffer *screen_buffer, char_info_t data,
+ enum char_info_mode mode, int x, int y, int count, int wrap )
+{
+ int i;
+ char_info_t *end, *dest = screen_buffer->data + y * screen_buffer->width + x;
+
+ if (y >= screen_buffer->height) return 0;
+
+ if (wrap)
+ end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
+ else
+ end = screen_buffer->data + (y+1) * screen_buffer->width;
+
+ if (count > end - dest) count = end - dest;
+
+ switch(mode)
+ {
+ case CHAR_INFO_MODE_TEXT:
+ for (i = 0; i < count; i++) dest[i].ch = data.ch;
+ break;
+ case CHAR_INFO_MODE_ATTR:
+ for (i = 0; i < count; i++) dest[i].attr = data.attr;
+ break;
+ case CHAR_INFO_MODE_TEXTATTR:
+ for (i = 0; i < count; i++) dest[i] = data;
+ break;
+ case CHAR_INFO_MODE_TEXTSTDATTR:
+ for (i = 0; i < count; i++)
+ {
+ dest[i].ch = data.ch;
+ dest[i].attr = screen_buffer->attr;
+ }
+ break;
+ default:
+ set_error( STATUS_INVALID_PARAMETER );
+ return 0;
}
- if (len && screen_buffer == screen_buffer->input->active)
+ if (count && screen_buffer == screen_buffer->input->active)
{
- int y2;
- struct console_renderer_event evt;
-
- y2 = (y * screen_buffer->width + x + len - 1) / screen_buffer->width;
-
- evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
- evt.u.update.top = y;
- evt.u.update.bottom = y2;
- console_input_events_append( screen_buffer->input->evt, &evt );
+ struct console_renderer_event evt;
+ evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
+ evt.u.update.top = y;
+ evt.u.update.bottom = (y * screen_buffer->width + x + count - 1) / screen_buffer->width;
+ console_input_events_append( screen_buffer->input->evt, &evt );
}
- return len;
+ return i;
}
/* read data from a screen buffer */
-static int read_console_output( struct screen_buffer *screen_buffer, size_t size, void* data,
- short int x, short int y, short int w, short int h,
- short int* eff_w, short int* eff_h )
+static void read_console_output( struct screen_buffer *screen_buffer, int x, int y,
+ enum char_info_mode mode, int wrap )
{
- int j;
+ int i;
+ char_info_t *end, *src = screen_buffer->data + y * screen_buffer->width + x;
- if (size < w * h * 4 || x >= screen_buffer->width || y >= screen_buffer->height)
- {
- set_error(STATUS_INVALID_PARAMETER);
- return 0;
- }
+ if (y >= screen_buffer->height) return;
- *eff_w = w;
- *eff_h = h;
- if (x + w > screen_buffer->width) *eff_w = screen_buffer->width - x;
- if (y + h > screen_buffer->height) *eff_h = screen_buffer->height - y;
+ if (wrap)
+ end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
+ else
+ end = screen_buffer->data + (y+1) * screen_buffer->width;
- for (j = 0; j < *eff_h; j++)
+ switch(mode)
{
- memcpy( (char*)data + 4 * j * w, &screen_buffer->data[(y + j) * screen_buffer->width + x],
- *eff_w * 4 );
+ case CHAR_INFO_MODE_TEXT:
+ {
+ WCHAR *data;
+ int count = min( end - 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;
+ int count = min( end - 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;
+ int count = min( end - 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];
+ }
+ }
+ break;
+ default:
+ set_error( STATUS_INVALID_PARAMETER );
+ break;
}
-
- return *eff_w * *eff_h;
}
/* scroll parts of a screen buffer */
-static void scroll_console_output( handle_t handle, short int xsrc, short int ysrc,
- short int xdst, short int ydst, short int w, short int h )
+static void scroll_console_output( handle_t handle, int xsrc, int ysrc, int xdst, int ydst,
+ int w, int h )
{
struct screen_buffer *screen_buffer;
int j;
- unsigned* psrc;
- unsigned* pdst;
+ char_info_t *psrc, *pdst;
struct console_renderer_event evt;
if (!(screen_buffer = (struct screen_buffer *)get_handle_obj( current->process, handle,
@@ -934,7 +1046,7 @@
for (j = h; j > 0; j--)
{
- memcpy(pdst, psrc, w * 4);
+ memcpy(pdst, psrc, w * sizeof(*pdst) );
pdst -= screen_buffer->width;
psrc -= screen_buffer->width;
}
@@ -949,7 +1061,7 @@
/* we use memmove here because when psrc and pdst are the same,
* copies are done on the same row, so the dst and src blocks
* can overlap */
- memmove( pdst, psrc, w * 4 );
+ memmove( pdst, psrc, w * sizeof(*pdst) );
pdst += screen_buffer->width;
psrc += screen_buffer->width;
}
@@ -976,35 +1088,35 @@
process = (req->pid) ? get_process_from_id( req->pid ) :
(struct process *)grab_object( renderer->parent );
- req->handle_in = 0;
- req->event = 0;
+ reply->handle_in = 0;
+ reply->event = 0;
if (!process) return;
if (process != renderer && process->console)
- {
- set_error( STATUS_ACCESS_DENIED );
- goto the_end;
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ goto the_end;
}
if ((console = (struct console_input*)create_console_input( renderer )))
{
- if ((in = alloc_handle( renderer, console, req->access, req->inherit )))
- {
- if ((evt = alloc_handle( renderer, console->evt,
- SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, FALSE )))
- {
- if (process != renderer)
- {
- process->console = (struct console_input*)grab_object( console );
- console->num_proc++;
- }
- req->handle_in = in;
- req->event = evt;
- release_object( console );
- goto the_end;
- }
- close_handle( renderer, in, NULL );
- }
- free_console( process );
+ if ((in = alloc_handle( renderer, console, req->access, req->inherit )))
+ {
+ if ((evt = alloc_handle( renderer, console->evt,
+ SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, FALSE )))
+ {
+ if (process != renderer)
+ {
+ process->console = (struct console_input*)grab_object( console );
+ console->num_proc++;
+ }
+ reply->handle_in = in;
+ reply->event = evt;
+ release_object( console );
+ goto the_end;
+ }
+ close_handle( renderer, in, NULL );
+ }
+ free_console( process );
}
the_end:
release_object( process );
@@ -1019,14 +1131,12 @@
/* let the renderer peek the events it's waiting on */
DECL_HANDLER(get_console_renderer_events)
{
- struct console_input_events* evt;
- size_t len = 0;
+ struct console_input_events *evt;
evt = (struct console_input_events *)get_handle_obj( current->process, req->handle,
- GENERIC_WRITE, &console_input_events_ops );
+ GENERIC_WRITE, &console_input_events_ops );
if (!evt) return;
- len = console_input_events_get( evt, get_req_data(req), get_req_data_size(req) );
- set_req_data_size( req, len );
+ console_input_events_get( evt );
release_object( evt );
}
@@ -1035,70 +1145,66 @@
{
struct object *obj = NULL;
- req->handle = 0;
+ reply->handle = 0;
switch (req->from)
{
- case 0:
- if (current->process->console && current->process->console->renderer)
- obj = grab_object( (struct object*)current->process->console );
- break;
- case 1:
- if (current->process->console && current->process->console->renderer &&
- current->process->console->active)
- obj = grab_object( (struct object*)current->process->console->active );
- break;
+ case 0:
+ if (current->process->console && current->process->console->renderer)
+ obj = grab_object( (struct object*)current->process->console );
+ break;
+ case 1:
+ if (current->process->console && current->process->console->renderer &&
+ current->process->console->active)
+ obj = grab_object( (struct object*)current->process->console->active );
+ break;
default:
- if ((obj = get_handle_obj( current->process, (handle_t)req->from,
- GENERIC_READ|GENERIC_WRITE, &console_input_ops )))
- {
- struct console_input* console = (struct console_input*)obj;
- obj = (console->active) ? grab_object( console->active ) : NULL;
- release_object( console );
- }
- break;
+ if ((obj = get_handle_obj( current->process, (handle_t)req->from,
+ GENERIC_READ|GENERIC_WRITE, &console_input_ops )))
+ {
+ struct console_input* console = (struct console_input*)obj;
+ obj = (console->active) ? grab_object( console->active ) : NULL;
+ release_object( console );
+ }
+ break;
}
/* FIXME: req->share is not used (as in screen buffer creation) */
if (obj)
{
- req->handle = alloc_handle( current->process, obj, req->access, req->inherit );
- release_object( obj );
+ reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
+ release_object( obj );
}
- if (!req->handle && !get_error()) set_error( STATUS_ACCESS_DENIED );
+ else if (!get_error()) set_error( STATUS_ACCESS_DENIED );
}
/* set info about a console input */
DECL_HANDLER(set_console_input_info)
{
- set_console_input_info( req, get_req_data(req), get_req_data_size(req) );
+ set_console_input_info( req, get_req_data(), get_req_data_size() );
}
/* get info about a console (output only) */
DECL_HANDLER(get_console_input_info)
{
- struct console_input *console = 0;
+ struct console_input *console;
- set_req_data_size( req, 0 );
if (!(console = console_input_get( req->handle, GENERIC_READ ))) return;
-
if (console->title)
{
- size_t len = strlenW( console->title ) * sizeof(WCHAR);
- if (len > get_req_data_size(req)) len = get_req_data_size(req);
- memcpy( get_req_data(req), console->title, len );
- set_req_data_size( req, len );
+ size_t len = strlenW( console->title ) * sizeof(WCHAR);
+ if (len > get_reply_max_size()) len = get_reply_max_size();
+ set_reply_data( console->title, len );
}
- req->history_mode = console->history_mode;
- req->history_size = console->history_size;
- req->history_index = console->history_index;
-
+ reply->history_mode = console->history_mode;
+ reply->history_size = console->history_size;
+ reply->history_index = console->history_index;
release_object( console );
}
/* get a console mode (input or output) */
DECL_HANDLER(get_console_mode)
{
- req->mode = get_console_mode( req->handle );
+ reply->mode = get_console_mode( req->handle );
}
/* set a console mode (input or output) */
@@ -1112,47 +1218,39 @@
{
struct console_input *console;
- req->written = 0;
+ reply->written = 0;
if (!(console = (struct console_input *)get_handle_obj( current->process, req->handle,
GENERIC_WRITE, &console_input_ops )))
return;
-
- req->written = write_console_input( console, get_req_data_size(req) / sizeof(INPUT_RECORD),
- get_req_data(req) );
+ reply->written = write_console_input( console, get_req_data_size() / sizeof(INPUT_RECORD),
+ get_req_data() );
release_object( console );
}
/* fetch input records from a console input queue */
DECL_HANDLER(read_console_input)
{
- size_t size = get_req_data_size(req) / sizeof(INPUT_RECORD);
- int res = read_console_input( req->handle, size, get_req_data(req), req->flush );
- /* if size was 0 we didn't fetch anything */
- if (size) set_req_data_size( req, res * sizeof(INPUT_RECORD) );
- req->read = res;
+ int count = get_reply_max_size() / sizeof(INPUT_RECORD);
+ reply->read = read_console_input( req->handle, count, req->flush );
}
/* appends a string to console's history */
DECL_HANDLER(append_console_input_history)
{
- struct console_input* console;
+ struct console_input *console;
if (!(console = console_input_get( req->handle, GENERIC_WRITE ))) return;
- console_input_append_hist( console, get_req_data(req),
- get_req_data_size(req) / sizeof(WCHAR) );
+ console_input_append_hist( console, get_req_data(), get_req_data_size() / sizeof(WCHAR) );
release_object( console );
}
/* appends a string to console's history */
DECL_HANDLER(get_console_input_history)
{
- struct console_input* console;
- int len;
+ struct console_input *console;
if (!(console = console_input_get( req->handle, GENERIC_WRITE ))) return;
-
- len = console_input_get_hist( console, get_req_data(req), 0 /* FIXME */, req->index );
- set_req_data_size( req, len * sizeof(WCHAR));
+ reply->total = console_input_get_hist( console, req->index );
release_object( console );
}
@@ -1164,14 +1262,14 @@
if (!(console = console_input_get( req->handle_in, GENERIC_WRITE))) return;
- screen_buffer = (struct screen_buffer*)create_console_output( console );
+ screen_buffer = create_console_output( console );
if (screen_buffer)
{
- /* FIXME: should store sharing and test it when opening the CONOUT$ device
- * see file.c on how this could be done
- */
- req->handle_out = alloc_handle( current->process, screen_buffer, req->access, req->inherit );
- release_object( screen_buffer );
+ /* FIXME: should store sharing and test it when opening the CONOUT$ device
+ * see file.c on how this could be done */
+ reply->handle_out = alloc_handle( current->process, screen_buffer,
+ req->access, req->inherit );
+ release_object( screen_buffer );
}
release_object( console );
}
@@ -1179,79 +1277,84 @@
/* set info about a console screen buffer */
DECL_HANDLER(set_console_output_info)
{
- struct screen_buffer *screen_buffer;
+ struct screen_buffer *screen_buffer;
- if (!(screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
- GENERIC_WRITE, &screen_buffer_ops )))
- return;
-
- set_console_output_info( screen_buffer, req );
- release_object( screen_buffer );
+ if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
+ GENERIC_WRITE, &screen_buffer_ops)))
+ {
+ set_console_output_info( screen_buffer, req );
+ release_object( screen_buffer );
+ }
}
/* get info about a console screen buffer */
DECL_HANDLER(get_console_output_info)
{
struct screen_buffer *screen_buffer;
- size_t len = 0;
if ((screen_buffer = (struct screen_buffer *)get_handle_obj( current->process, req->handle,
- GENERIC_READ, &screen_buffer_ops )))
+ GENERIC_READ, &screen_buffer_ops)))
{
- req->cursor_size = screen_buffer->cursor_size;
- req->cursor_visible = screen_buffer->cursor_visible;
- req->cursor_x = screen_buffer->cursor.X;
- req->cursor_y = screen_buffer->cursor.Y;
- req->width = screen_buffer->width;
- req->height = screen_buffer->height;
- req->attr = screen_buffer->attr;
- req->win_left = screen_buffer->win.Left;
- req->win_top = screen_buffer->win.Top;
- req->win_right = screen_buffer->win.Right;
- req->win_bottom = screen_buffer->win.Bottom;
- req->max_width = screen_buffer->max_width;
- req->max_height = screen_buffer->max_height;
-
+ reply->cursor_size = screen_buffer->cursor_size;
+ reply->cursor_visible = screen_buffer->cursor_visible;
+ reply->cursor_x = screen_buffer->cursor_x;
+ reply->cursor_y = screen_buffer->cursor_y;
+ reply->width = screen_buffer->width;
+ reply->height = screen_buffer->height;
+ reply->attr = screen_buffer->attr;
+ reply->win_left = screen_buffer->win.left;
+ reply->win_top = screen_buffer->win.top;
+ reply->win_right = screen_buffer->win.right;
+ reply->win_bottom = screen_buffer->win.bottom;
+ reply->max_width = screen_buffer->max_width;
+ reply->max_height = screen_buffer->max_height;
release_object( screen_buffer );
}
- set_req_data_size( req, len );
}
/* read data (chars & attrs) from a screen buffer */
DECL_HANDLER(read_console_output)
{
- struct screen_buffer *screen_buffer;
- size_t size = get_req_data_size(req);
- int res;
+ struct screen_buffer *screen_buffer;
- if (!(screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
- GENERIC_READ, &screen_buffer_ops )))
- return;
-
- res = read_console_output( screen_buffer, size, get_req_data(req),
- req->x, req->y, req->w, req->h, &req->eff_w, &req->eff_h);
- /* if size was 0 we didn't fetch anything */
- if (size) set_req_data_size( req, res * 4 );
- release_object( screen_buffer );
+ if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
+ GENERIC_READ, &screen_buffer_ops )))
+ {
+ read_console_output( screen_buffer, req->x, req->y, req->mode, req->wrap );
+ reply->width = screen_buffer->width;
+ reply->height = screen_buffer->height;
+ release_object( screen_buffer );
+ }
}
/* write data (char and/or attrs) to a screen buffer */
DECL_HANDLER(write_console_output)
{
- struct screen_buffer *screen_buffer;
- size_t size = get_req_data_size(req);
- int res;
+ struct screen_buffer *screen_buffer;
- if (!(screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
- GENERIC_WRITE, &screen_buffer_ops )))
- return;
+ if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
+ GENERIC_WRITE, &screen_buffer_ops)))
+ {
+ reply->written = write_console_output( 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 );
+ }
+}
- res = write_console_output( screen_buffer, size, get_req_data(req), req->mode, req->x, req->y );
+/* fill a screen buffer with constant data (chars and/or attributes) */
+DECL_HANDLER(fill_console_output)
+{
+ struct screen_buffer *screen_buffer;
- /* if size was 0 we didn't fetch anything */
- if (size) set_req_data_size( req, res );
- req->written = res;
- release_object( screen_buffer );
+ if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
+ GENERIC_WRITE, &screen_buffer_ops)))
+ {
+ reply->written = fill_console_output( screen_buffer, req->data, req->mode,
+ req->x, req->y, req->count, req->wrap );
+ release_object( screen_buffer );
+ }
}
/* move a rect of data in a screen buffer */