Commit 4b461128 authored by Alexandre Julliard's avatar Alexandre Julliard

Added input queue to server-side console object,

read/write_console_input requests, and use them for Read/WriteConsoleInput.
parent 0b78af7c
......@@ -510,6 +510,31 @@ struct get_console_info_reply
};
/* Add input records to a console input queue */
struct write_console_input_request
{
int handle; /* handle to the console input */
int count; /* number of input records */
/* INPUT_RECORD records[0]; */ /* input records */
};
struct write_console_input_reply
{
int written; /* number of records written */
};
/* Fetch input records from a console input queue */
struct read_console_input_request
{
int handle; /* handle to the console input */
int count; /* max number of records to retrieve */
int flush; /* flush the retrieved records from the queue? */
};
struct read_console_input_reply
{
/* INPUT_RECORD records[0]; */ /* input records */
};
/* Create a change notification */
struct create_change_notification_request
{
......
......@@ -203,6 +203,7 @@ extern int create_pipe( struct object *obj[2] );
/* console functions */
struct tagINPUT_RECORD;
extern int create_console( int fd, struct object *obj[2] );
extern int set_console_fd( int handle, int fd, int pid );
extern int get_console_mode( int handle, int *mode );
......@@ -211,6 +212,8 @@ extern int set_console_info( int handle, struct set_console_info_request *req,
const char *title );
extern int get_console_info( int handle, struct get_console_info_reply *reply,
const char **title );
extern int write_console_input( int handle, int count, struct tagINPUT_RECORD *records );
extern int read_console_input( int handle, int count, int flush );
/* change notification functions */
......
......@@ -47,6 +47,8 @@ enum request
REQ_SET_CONSOLE_MODE,
REQ_SET_CONSOLE_INFO,
REQ_GET_CONSOLE_INFO,
REQ_WRITE_CONSOLE_INPUT,
REQ_READ_CONSOLE_INPUT,
REQ_CREATE_CHANGE_NOTIFICATION,
REQ_CREATE_MAPPING,
REQ_GET_MAPPING_INFO,
......@@ -101,6 +103,8 @@ DECL_HANDLER(get_console_mode);
DECL_HANDLER(set_console_mode);
DECL_HANDLER(set_console_info);
DECL_HANDLER(get_console_info);
DECL_HANDLER(write_console_input);
DECL_HANDLER(read_console_input);
DECL_HANDLER(create_change_notification);
DECL_HANDLER(create_mapping);
DECL_HANDLER(get_mapping_info);
......@@ -152,6 +156,8 @@ static const struct handler {
{ (void(*)())req_set_console_mode, sizeof(struct set_console_mode_request) },
{ (void(*)())req_set_console_info, sizeof(struct set_console_info_request) },
{ (void(*)())req_get_console_info, sizeof(struct get_console_info_request) },
{ (void(*)())req_write_console_input, sizeof(struct write_console_input_request) },
{ (void(*)())req_read_console_input, sizeof(struct read_console_input_request) },
{ (void(*)())req_create_change_notification, sizeof(struct create_change_notification_request) },
{ (void(*)())req_create_mapping, sizeof(struct create_mapping_request) },
{ (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) },
......
......@@ -1102,8 +1102,7 @@ BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
lpme->szModule[min(*name, MAX_MODULE_NAME)] = '\0';
lpme->hModule = lpme->wNext;
lpme->wcUsage = pModule->count;
strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
lpme->szExePath[MAX_PATH] = '\0';
lstrcpyn32A( lpme->szExePath, NE_MODULE_NAME(pModule), sizeof(lpme->szExePath) );
lpme->wNext = pModule->next;
return TRUE;
}
......
......@@ -746,7 +746,7 @@ init MAIN_KernelInit
727 stdcall WideCharToMultiByte(long long wstr long ptr long ptr ptr) WideCharToMultiByte
728 stdcall WinExec(str long) WinExec32
729 stdcall WriteConsoleA(long ptr long ptr ptr) WriteConsole32A
730 stub WriteConsoleInputA
730 stdcall WriteConsoleInputA(long ptr long ptr) WriteConsoleInput32A
731 stub WriteConsoleInputW
732 stdcall WriteConsoleOutputA(long ptr long long ptr) WriteConsoleOutput32A
733 stub WriteConsoleOutputAttribute
......
......@@ -33,6 +33,8 @@ struct console_input
int fd; /* Unix file descriptor */
int mode; /* input mode */
struct screen_buffer *output; /* associated screen buffer */
int recnum; /* number of input records */
INPUT_RECORD *records; /* input records */
};
struct screen_buffer
......@@ -135,6 +137,8 @@ int create_console( int fd, struct object *obj[2] )
console_input->mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
console_input->output = screen_buffer;
console_input->recnum = 0;
console_input->records = NULL;
screen_buffer->fd = write_fd;
screen_buffer->mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
screen_buffer->input = console_input;
......@@ -281,6 +285,60 @@ int get_console_info( int handle, struct get_console_info_reply *reply, const ch
return 1;
}
/* add input events to a console input queue */
int write_console_input( int handle, int count, INPUT_RECORD *records )
{
INPUT_RECORD *new_rec;
struct console_input *console;
if (!(console = (struct console_input *)get_handle_obj( current->process, handle,
GENERIC_WRITE, &console_input_ops )))
return -1;
if (!(new_rec = realloc( console->records,
(console->recnum + count) * sizeof(INPUT_RECORD) )))
{
SET_ERROR( ERROR_NOT_ENOUGH_MEMORY );
release_object( console );
return -1;
}
console->records = new_rec;
memcpy( new_rec + console->recnum, records, count * sizeof(INPUT_RECORD) );
console->recnum += count;
release_object( console );
return count;
}
/* retrieve a pointer to the console input records */
int read_console_input( int handle, int count, int flush )
{
struct console_input *console;
if (!(console = (struct console_input *)get_handle_obj( current->process, handle,
GENERIC_READ, &console_input_ops )))
return -1;
if ((count < 0) || (count > console->recnum)) count = console->recnum;
send_reply( current, -1, 1, console->records, count * sizeof(INPUT_RECORD) );
if (flush)
{
int i;
for (i = count; i < console->recnum; i++)
console->records[i-count] = console->records[i];
if ((console->recnum -= count) > 0)
{
INPUT_RECORD *new_rec = realloc( console->records,
console->recnum * sizeof(INPUT_RECORD) );
if (new_rec) console->records = new_rec;
}
else
{
free( console->records );
console->records = NULL;
}
}
release_object( console );
return count;
}
static void console_input_dump( struct object *obj, int verbose )
{
struct console_input *console = (struct console_input *)obj;
......
......@@ -15,6 +15,7 @@
#include "winerror.h"
#include "winnt.h"
#include "winbase.h"
#include "wincon.h"
#define WANT_REQUEST_HANDLERS
#include "server.h"
#include "server/request.h"
......@@ -677,6 +678,25 @@ DECL_HANDLER(set_console_mode)
send_reply( current, -1, 0 );
}
/* add input records to a console input queue */
DECL_HANDLER(write_console_input)
{
struct write_console_input_reply reply;
INPUT_RECORD *records = (INPUT_RECORD *)data;
if (len != req->count * sizeof(INPUT_RECORD))
fatal_protocol_error( "write_console_input: bad length %d for %d records\n",
len, req->count );
reply.written = write_console_input( req->handle, req->count, records );
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* fetch input records from a console input queue */
DECL_HANDLER(read_console_input)
{
read_console_input( req->handle, req->count, req->flush );
}
/* create a change notification */
DECL_HANDLER(create_change_notification)
{
......
......@@ -458,6 +458,32 @@ static int dump_get_console_info_reply( struct get_console_info_reply *req, int
return (int)sizeof(*req);
}
static int dump_write_console_input_request( struct write_console_input_request *req, int len )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " count=%d", req->count );
return (int)sizeof(*req);
}
static int dump_write_console_input_reply( struct write_console_input_reply *req, int len )
{
fprintf( stderr, " written=%d", req->written );
return (int)sizeof(*req);
}
static int dump_read_console_input_request( struct read_console_input_request *req, int len )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " count=%d,", req->count );
fprintf( stderr, " flush=%d", req->flush );
return (int)sizeof(*req);
}
static int dump_read_console_input_reply( struct read_console_input_reply *req, int len )
{
return (int)sizeof(*req);
}
static int dump_create_change_notification_request( struct create_change_notification_request *req, int len )
{
fprintf( stderr, " subtree=%d,", req->subtree );
......@@ -607,6 +633,10 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
(void(*)())0 },
{ (int(*)(void *,int))dump_get_console_info_request,
(void(*)())dump_get_console_info_reply },
{ (int(*)(void *,int))dump_write_console_input_request,
(void(*)())dump_write_console_input_reply },
{ (int(*)(void *,int))dump_read_console_input_request,
(void(*)())dump_read_console_input_reply },
{ (int(*)(void *,int))dump_create_change_notification_request,
(void(*)())dump_create_change_notification_reply },
{ (int(*)(void *,int))dump_create_mapping_request,
......@@ -661,6 +691,8 @@ static const char * const req_names[REQ_NB_REQUESTS] =
"set_console_mode",
"set_console_info",
"get_console_info",
"write_console_input",
"read_console_input",
"create_change_notification",
"create_mapping",
"get_mapping_info",
......
......@@ -1043,44 +1043,122 @@ BOOL32 WINAPI ReadConsoleInput32A(HANDLE32 hConsoleInput,
LPINPUT_RECORD lpBuffer,
DWORD nLength, LPDWORD lpNumberOfEventsRead)
{
CONSOLE *console = CONSOLE_GetPtr( hConsoleInput );
TRACE(console, "(%d,%p,%ld,%p)\n",hConsoleInput, lpBuffer, nLength,
lpNumberOfEventsRead);
if (!console) {
FIXME(console, "(%d,%p,%ld,%p), No console handle!\n",hConsoleInput,
lpBuffer, nLength, lpNumberOfEventsRead);
struct read_console_input_request req;
int len;
/* Indicate that nothing was read */
*lpNumberOfEventsRead = 0;
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hConsoleInput,
K32OBJ_CONSOLE, GENERIC_READ )) == -1)
return FALSE;
req.count = nLength;
req.flush = 1;
/* loop until we get at least one event */
for (;;)
{
CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitReply( &len, NULL, 1, lpBuffer, nLength * sizeof(*lpBuffer) ))
return FALSE;
assert( !(len % sizeof(INPUT_RECORD)) );
if (len) break;
WaitForSingleObject( hConsoleInput, INFINITE32 );
}
CONSOLE_get_input(hConsoleInput);
/* SDK: return at least 1 input record */
while (!console->nrofirs) {
DWORD res;
if (lpNumberOfEventsRead) *lpNumberOfEventsRead = len / sizeof(INPUT_RECORD);
return TRUE;
}
res=WaitForSingleObject(hConsoleInput,0);
switch (res) {
case STATUS_TIMEOUT: continue;
case 0: break; /*ok*/
case WAIT_FAILED: return 0;/*FIXME: SetLastError?*/
default: break; /*hmm*/
}
CONSOLE_get_input(hConsoleInput);
}
if (nLength>console->nrofirs)
nLength = console->nrofirs;
memcpy(lpBuffer,console->irs,sizeof(INPUT_RECORD)*nLength);
if (lpNumberOfEventsRead)
*lpNumberOfEventsRead = nLength;
CONSOLE_drain_input(console,nLength);
K32OBJ_DecCount(&console->header);
/***********************************************************************
* ReadConsoleInput32W (KERNEL32.570)
*/
BOOL32 WINAPI ReadConsoleInput32W( HANDLE32 handle, LPINPUT_RECORD buffer,
DWORD count, LPDWORD read )
{
/* FIXME: Fix this if we get UNICODE input. */
return ReadConsoleInput32A( handle, buffer, count, read );
}
/***********************************************************************
* FlushConsoleInputBuffer (KERNEL32.132)
*/
BOOL32 WINAPI FlushConsoleInputBuffer( HANDLE32 handle )
{
struct read_console_input_request req;
int len;
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_CONSOLE, GENERIC_READ )) == -1)
return FALSE;
req.count = -1; /* get all records */
req.flush = 1;
CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( &len, NULL, 0 );
}
/***********************************************************************
* PeekConsoleInputA (KERNEL32.550)
*
* Gets 'count' first events (or less) from input queue.
*
* Does not need a complex console.
*/
BOOL32 WINAPI PeekConsoleInput32A( HANDLE32 handle, LPINPUT_RECORD buffer,
DWORD count, LPDWORD read )
{
struct read_console_input_request req;
int len;
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_CONSOLE, GENERIC_READ )) == -1)
return FALSE;
req.count = count;
req.flush = 0;
CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitReply( &len, NULL, 1, buffer, count * sizeof(*buffer) ))
return FALSE;
assert( !(len % sizeof(INPUT_RECORD)) );
if (read) *read = len / sizeof(INPUT_RECORD);
return TRUE;
}
/***********************************************************************
* PeekConsoleInputW (KERNEL32.551)
*/
BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput,
LPINPUT_RECORD pirBuffer,
DWORD cInRecords,
LPDWORD lpcRead)
{
/* FIXME: Hmm. Fix this if we get UNICODE input. */
return PeekConsoleInput32A(hConsoleInput,pirBuffer,cInRecords,lpcRead);
}
/******************************************************************************
* WriteConsoleInput32A [KERNEL32.730] Write data to a console input buffer
*
*/
BOOL32 WINAPI WriteConsoleInput32A( HANDLE32 handle, INPUT_RECORD *buffer,
DWORD count, LPDWORD written )
{
struct write_console_input_request req;
struct write_console_input_reply reply;
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_CONSOLE, GENERIC_WRITE )) == -1)
return FALSE;
req.count = count;
CLIENT_SendRequest( REQ_WRITE_CONSOLE_INPUT, -1, 2, &req, sizeof(req),
buffer, count * sizeof(*buffer) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
if (written) *written = reply.written;
return TRUE;
}
/***********************************************************************
* SetConsoleTitle32A (KERNEL32.476)
*
......@@ -1185,33 +1263,6 @@ BOOL32 WINAPI SetConsoleTitle32W( LPCWSTR title )
return ret;
}
/***********************************************************************
* ReadConsoleInput32W (KERNEL32.570)
*/
BOOL32 WINAPI ReadConsoleInput32W(HANDLE32 hConsoleInput,
LPINPUT_RECORD lpBuffer,
DWORD nLength, LPDWORD lpNumberOfEventsRead)
{
FIXME(console, "(%d,%p,%ld,%p): stub\n",hConsoleInput, lpBuffer, nLength,
lpNumberOfEventsRead);
return 0;
}
/***********************************************************************
* FlushConsoleInputBuffer (KERNEL32.132)
*/
BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput)
{
CONSOLE *console = CONSOLE_GetPtr( hConsoleInput );
if (!console)
return FALSE;
CONSOLE_drain_input(console,console->nrofirs);
K32OBJ_DecCount(&console->header);
return TRUE;
}
/******************************************************************************
* SetConsoleCursorPosition [KERNEL32.627]
* Sets the cursor position in console
......@@ -1271,53 +1322,6 @@ BOOL32 WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
return TRUE;
}
/***********************************************************************
* PeekConsoleInputA (KERNEL32.550)
*
* Gets 'cInRecords' first events (or less) from input queue.
*
* Does not need a complex console.
*/
BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput,
LPINPUT_RECORD pirBuffer,
DWORD cInRecords,
LPDWORD lpcRead)
{
CONSOLE *console = CONSOLE_GetPtr( hConsoleInput );
if (!console) {
FIXME(console,"(%d,%p,%ld,%p), No console handle passed!\n",hConsoleInput, pirBuffer, cInRecords, lpcRead);
/* Indicate that nothing was read */
*lpcRead = 0;
return FALSE;
}
TRACE(console,"(%d,%p,%ld,%p)\n",hConsoleInput, pirBuffer, cInRecords, lpcRead);
CONSOLE_get_input(hConsoleInput);
if (cInRecords>console->nrofirs)
cInRecords = console->nrofirs;
if (pirBuffer)
memcpy(pirBuffer,console->irs,cInRecords*sizeof(INPUT_RECORD));
if (lpcRead)
*lpcRead = cInRecords;
K32OBJ_DecCount(&console->header);
return TRUE;
}
/***********************************************************************
* PeekConsoleInputW (KERNEL32.551)
*/
BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput,
LPINPUT_RECORD pirBuffer,
DWORD cInRecords,
LPDWORD lpcRead)
{
/* FIXME: Hmm. Fix this if we get UNICODE input. */
return PeekConsoleInput32A(hConsoleInput,pirBuffer,cInRecords,lpcRead);
}
/******************************************************************************
* GetConsoleCursorInfo32 [KERNEL32.296] Gets size and visibility of console
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment