kernelbase: Move Unicode conversion from ReadConsoleA to conhost.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2020-11-19 17:59:16 +01:00 committed by Alexandre Julliard
parent ee77a96dae
commit a66eab0dfb
4 changed files with 88 additions and 36 deletions

View File

@ -1585,24 +1585,15 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleOutputCharacterW( HANDLE handle, LPCWS
/***********************************************************************
* ReadConsoleA (kernelbase.@)
*/
BOOL WINAPI ReadConsoleA( HANDLE handle, void *buffer, DWORD length, DWORD *ret_count, void *reserved )
BOOL WINAPI ReadConsoleA( HANDLE handle, void *buffer, DWORD length, DWORD *count, void *reserved )
{
LPWSTR strW = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) );
DWORD count = 0;
BOOL ret;
if (!strW)
if (length > INT_MAX)
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
if ((ret = ReadConsoleW( handle, strW, length, &count, NULL )))
{
count = WideCharToMultiByte( GetConsoleCP(), 0, strW, count, buffer, length, NULL, NULL );
if (ret_count) *ret_count = count;
}
HeapFree( GetProcessHeap(), 0, strW );
return ret;
return console_ioctl( handle, IOCTL_CONDRV_READ_FILE, NULL, 0, buffer, length, count );
}

View File

@ -30,16 +30,17 @@
/* console input ioctls */
#define IOCTL_CONDRV_READ_CONSOLE CTL_CODE(FILE_DEVICE_CONSOLE, 10, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_READ_INPUT CTL_CODE(FILE_DEVICE_CONSOLE, 11, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_WRITE_INPUT CTL_CODE(FILE_DEVICE_CONSOLE, 12, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_CONDRV_PEEK CTL_CODE(FILE_DEVICE_CONSOLE, 13, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_GET_INPUT_INFO CTL_CODE(FILE_DEVICE_CONSOLE, 14, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_SET_INPUT_INFO CTL_CODE(FILE_DEVICE_CONSOLE, 15, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_CONDRV_GET_TITLE CTL_CODE(FILE_DEVICE_CONSOLE, 16, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_SET_TITLE CTL_CODE(FILE_DEVICE_CONSOLE, 17, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_CONDRV_CTRL_EVENT CTL_CODE(FILE_DEVICE_CONSOLE, 18, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_CONDRV_BEEP CTL_CODE(FILE_DEVICE_CONSOLE, 19, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_CONDRV_FLUSH CTL_CODE(FILE_DEVICE_CONSOLE, 20, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_CONDRV_READ_FILE CTL_CODE(FILE_DEVICE_CONSOLE, 11, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_READ_INPUT CTL_CODE(FILE_DEVICE_CONSOLE, 12, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_WRITE_INPUT CTL_CODE(FILE_DEVICE_CONSOLE, 13, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_CONDRV_PEEK CTL_CODE(FILE_DEVICE_CONSOLE, 14, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_GET_INPUT_INFO CTL_CODE(FILE_DEVICE_CONSOLE, 15, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_SET_INPUT_INFO CTL_CODE(FILE_DEVICE_CONSOLE, 16, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_CONDRV_GET_TITLE CTL_CODE(FILE_DEVICE_CONSOLE, 17, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_CONDRV_SET_TITLE CTL_CODE(FILE_DEVICE_CONSOLE, 18, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_CONDRV_CTRL_EVENT CTL_CODE(FILE_DEVICE_CONSOLE, 19, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_CONDRV_BEEP CTL_CODE(FILE_DEVICE_CONSOLE, 20, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_CONDRV_FLUSH CTL_CODE(FILE_DEVICE_CONSOLE, 21, METHOD_BUFFERED, FILE_ANY_ACCESS)
/* console output ioctls */
#define IOCTL_CONDRV_WRITE_CONSOLE CTL_CODE(FILE_DEVICE_CONSOLE, 30, METHOD_BUFFERED, FILE_WRITE_ACCESS)

View File

@ -20,6 +20,7 @@
*/
#include <assert.h>
#include <limits.h>
#include "conhost.h"
@ -450,14 +451,44 @@ static NTSTATUS read_console_input( struct console *console, size_t out_size )
static void read_from_buffer( struct console *console, size_t out_size )
{
out_size = min( out_size, console->read_buffer_count * sizeof(WCHAR) );
read_complete( console, STATUS_SUCCESS, console->read_buffer, out_size, console->record_count != 0 );
if (out_size / sizeof(WCHAR) < console->read_buffer_count)
size_t len, read_len = 0;
char *buf = NULL;
switch( console->read_ioctl )
{
memmove( console->read_buffer, console->read_buffer + out_size / sizeof(WCHAR),
console->read_buffer_count * sizeof(WCHAR) - out_size );
case IOCTL_CONDRV_READ_CONSOLE:
out_size = min( out_size, console->read_buffer_count * sizeof(WCHAR) );
read_complete( console, STATUS_SUCCESS, console->read_buffer, out_size, console->record_count != 0 );
read_len = out_size / sizeof(WCHAR);
break;
case IOCTL_CONDRV_READ_FILE:
read_len = len = 0;
while (read_len < console->read_buffer_count && len < out_size)
{
len += WideCharToMultiByte( console->input_cp, 0, console->read_buffer + read_len, 1, NULL, 0, NULL, NULL );
read_len++;
}
if (len)
{
if (!(buf = malloc( len )))
{
read_complete( console, STATUS_NO_MEMORY, NULL, 0, console->record_count != 0 );
return;
}
WideCharToMultiByte( console->input_cp, 0, console->read_buffer, read_len, buf, len, NULL, NULL );
}
len = min( out_size, len );
read_complete( console, STATUS_SUCCESS, buf, len, console->record_count != 0 );
free( buf );
break;
}
if (!(console->read_buffer_count -= out_size / sizeof(WCHAR)))
if (read_len < console->read_buffer_count)
{
memmove( console->read_buffer, console->read_buffer + read_len,
(console->read_buffer_count - read_len) * sizeof(WCHAR) );
}
if (!(console->read_buffer_count -= read_len))
free( console->read_buffer );
}
@ -1184,6 +1215,7 @@ static NTSTATUS process_console_input( struct console *console )
if (console->record_count) read_console_input( console, console->pending_read );
return STATUS_SUCCESS;
case IOCTL_CONDRV_READ_CONSOLE:
case IOCTL_CONDRV_READ_FILE:
break;
default:
return STATUS_SUCCESS;
@ -1244,9 +1276,17 @@ static NTSTATUS process_console_input( struct console *console )
else if (ir.Event.KeyEvent.uChar.UnicodeChar && !(ir.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED))
edit_line_insert( console, &ir.Event.KeyEvent.uChar.UnicodeChar, 1 );
if (!(console->mode & ENABLE_LINE_INPUT) && ctx->status == STATUS_PENDING &&
ctx->len >= console->pending_read / sizeof(WCHAR))
ctx->status = STATUS_SUCCESS;
if (!(console->mode & ENABLE_LINE_INPUT) && ctx->status == STATUS_PENDING)
{
if (console->read_ioctl == IOCTL_CONDRV_READ_FILE)
{
if (WideCharToMultiByte(console->input_cp, 0, ctx->buf, ctx->len, NULL, 0, NULL, NULL)
>= console->pending_read)
ctx->status = STATUS_SUCCESS;
}
else if (ctx->len >= console->pending_read / sizeof(WCHAR))
ctx->status = STATUS_SUCCESS;
}
}
if (console->record_count > i) memmove( console->records, console->records + i,
@ -1285,10 +1325,17 @@ static NTSTATUS process_console_input( struct console *console )
return STATUS_SUCCESS;
}
static NTSTATUS read_console( struct console *console, size_t out_size )
static NTSTATUS read_console( struct console *console, unsigned int ioctl, size_t out_size )
{
TRACE("\n");
if (out_size > INT_MAX)
{
read_complete( console, STATUS_NO_MEMORY, NULL, 0, console->record_count );
return STATUS_NO_MEMORY;
}
console->read_ioctl = ioctl;
if (!out_size || console->read_buffer_count)
{
read_from_buffer( console, out_size );
@ -1301,7 +1348,6 @@ static NTSTATUS read_console( struct console *console, size_t out_size )
console->edit_line.status = STATUS_PENDING;
if (edit_line_grow( console, 1 )) console->edit_line.buf[0] = 0;
console->read_ioctl = IOCTL_CONDRV_READ_CONSOLE;
console->pending_read = out_size;
return process_console_input( console );
}
@ -2368,7 +2414,13 @@ static NTSTATUS console_input_ioctl( struct console *console, unsigned int code,
case IOCTL_CONDRV_READ_CONSOLE:
if (in_size || *out_size % sizeof(WCHAR)) return STATUS_INVALID_PARAMETER;
ensure_tty_input_thread( console );
status = read_console( console, *out_size );
status = read_console( console, code, *out_size );
*out_size = 0;
return status;
case IOCTL_CONDRV_READ_FILE:
ensure_tty_input_thread( console );
status = read_console( console, code, *out_size );
*out_size = 0;
return status;

View File

@ -867,7 +867,15 @@ static struct object *create_console_server( void )
static int is_blocking_read_ioctl( unsigned int code )
{
return code == IOCTL_CONDRV_READ_INPUT || code == IOCTL_CONDRV_READ_CONSOLE;
switch (code)
{
case IOCTL_CONDRV_READ_INPUT:
case IOCTL_CONDRV_READ_CONSOLE:
case IOCTL_CONDRV_READ_FILE:
return 1;
default:
return 0;
}
}
static int console_input_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )