kernel32: Always use conhost for WriteConsoleW.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2020-10-13 16:27:11 +02:00 committed by Alexandre Julliard
parent 1b192ce4cb
commit 143c210360
1 changed files with 9 additions and 196 deletions

View File

@ -357,116 +357,6 @@ BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
return TRUE;
}
/******************************************************************
* CONSOLE_WriteChars
*
* WriteConsoleOutput helper: hides server call semantics
* writes a string at a given pos with standard attribute
*/
static int CONSOLE_WriteChars(HANDLE handle, const WCHAR *str, size_t length, COORD *coord)
{
struct condrv_output_params *params;
DWORD written = 0, size;
if (!length) return 0;
size = sizeof(*params) + length * sizeof(WCHAR);
if (!(params = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
params->mode = CHAR_INFO_MODE_TEXTSTDATTR;
params->x = coord->X;
params->y = coord->Y;
params->width = 0;
memcpy( params + 1, str, length * sizeof(*str) );
if (DeviceIoControl( handle, IOCTL_CONDRV_WRITE_OUTPUT, params, size,
&written, sizeof(written), NULL, NULL ))
coord->X += written;
HeapFree( GetProcessHeap(), 0, params );
return written;
}
/******************************************************************
* next_line
*
* WriteConsoleOutput helper: handles passing to next line (+scrolling if necessary)
*
*/
static BOOL next_line(HANDLE hCon, CONSOLE_SCREEN_BUFFER_INFO* csbi)
{
SMALL_RECT src;
CHAR_INFO ci;
COORD dst;
csbi->dwCursorPosition.X = 0;
csbi->dwCursorPosition.Y++;
if (csbi->dwCursorPosition.Y < csbi->dwSize.Y) return TRUE;
src.Top = 1;
src.Bottom = csbi->dwSize.Y - 1;
src.Left = 0;
src.Right = csbi->dwSize.X - 1;
dst.X = 0;
dst.Y = 0;
ci.Attributes = csbi->wAttributes;
ci.Char.UnicodeChar = ' ';
csbi->dwCursorPosition.Y--;
if (!ScrollConsoleScreenBufferW(hCon, &src, NULL, dst, &ci))
return FALSE;
return TRUE;
}
/******************************************************************
* write_block
*
* WriteConsoleOutput helper: writes a block of non special characters
* Block can spread on several lines, and wrapping, if needed, is
* handled
*
*/
static BOOL write_block(HANDLE hCon, CONSOLE_SCREEN_BUFFER_INFO* csbi,
DWORD mode, LPCWSTR ptr, int len)
{
int blk; /* number of chars to write on current line */
int done; /* number of chars already written */
if (len <= 0) return TRUE;
if (mode & ENABLE_WRAP_AT_EOL_OUTPUT) /* writes remaining on next line */
{
for (done = 0; done < len; done += blk)
{
blk = min(len - done, csbi->dwSize.X - csbi->dwCursorPosition.X);
if (CONSOLE_WriteChars(hCon, ptr + done, blk, &csbi->dwCursorPosition) != blk)
return FALSE;
if (csbi->dwCursorPosition.X == csbi->dwSize.X && !next_line(hCon, csbi))
return FALSE;
}
}
else
{
int pos = csbi->dwCursorPosition.X;
/* FIXME: we could reduce the number of loops
* but, in most cases we wouldn't gain lots of time (it would only
* happen if we're asked to overwrite more than twice the part of the line,
* which is unlikely
*/
for (done = 0; done < len; done += blk)
{
blk = min(len - done, csbi->dwSize.X - csbi->dwCursorPosition.X);
csbi->dwCursorPosition.X = pos;
if (CONSOLE_WriteChars(hCon, ptr + done, blk, &csbi->dwCursorPosition) != blk)
return FALSE;
}
}
return TRUE;
}
/***********************************************************************
* WriteConsoleA (KERNEL32.@)
@ -492,95 +382,18 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleA( HANDLE handle, LPCVOID buffer, DWOR
/***********************************************************************
* WriteConsoleW (KERNEL32.@)
*/
BOOL WINAPI WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite,
LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleW( HANDLE handle, const void *buffer, DWORD length,
DWORD *written, void *reserved )
{
DWORD mode;
DWORD nw = 0;
const WCHAR* psz = lpBuffer;
CONSOLE_SCREEN_BUFFER_INFO csbi;
int k, first = 0;
IO_STATUS_BLOCK io;
BOOL ret;
TRACE("%p %s %d %p %p\n",
hConsoleOutput, debugstr_wn(lpBuffer, nNumberOfCharsToWrite),
nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved);
TRACE( "(%p,%s,%d,%p,%p)\n", handle, debugstr_wn(buffer, length), length, written, reserved );
if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = 0;
if (!NtDeviceIoControlFile(hConsoleOutput, NULL, NULL, NULL, &io, IOCTL_CONDRV_WRITE_CONSOLE, (void *)lpBuffer,
nNumberOfCharsToWrite * sizeof(WCHAR), NULL, 0))
{
if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
return TRUE;
}
if (!GetConsoleMode(hConsoleOutput, &mode) || !GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
return FALSE;
if (!nNumberOfCharsToWrite) return TRUE;
if (mode & ENABLE_PROCESSED_OUTPUT)
{
unsigned int i;
for (i = 0; i < nNumberOfCharsToWrite; i++)
{
switch (psz[i])
{
case '\b': case '\t': case '\n': case '\a': case '\r':
/* don't handle here the i-th char... done below */
if ((k = i - first) > 0)
{
if (!write_block(hConsoleOutput, &csbi, mode, &psz[first], k))
goto the_end;
nw += k;
}
first = i + 1;
nw++;
}
switch (psz[i])
{
case '\b':
if (csbi.dwCursorPosition.X > 0) csbi.dwCursorPosition.X--;
break;
case '\t':
{
static const WCHAR tmp[] = {' ',' ',' ',' ',' ',' ',' ',' '};
if (!write_block(hConsoleOutput, &csbi, mode, tmp,
((csbi.dwCursorPosition.X + 8) & ~7) - csbi.dwCursorPosition.X))
goto the_end;
}
break;
case '\n':
next_line(hConsoleOutput, &csbi);
break;
case '\a':
Beep(400, 300);
break;
case '\r':
csbi.dwCursorPosition.X = 0;
break;
default:
break;
}
}
}
/* write the remaining block (if any) if processed output is enabled, or the
* entire buffer otherwise
*/
if ((k = nNumberOfCharsToWrite - first) > 0)
{
if (!write_block(hConsoleOutput, &csbi, mode, &psz[first], k))
goto the_end;
nw += k;
}
the_end:
SetConsoleCursorPosition(hConsoleOutput, csbi.dwCursorPosition);
if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = nw;
return nw != 0;
ret = DeviceIoControl( handle, IOCTL_CONDRV_WRITE_CONSOLE, (void *)buffer,
length * sizeof(WCHAR), NULL, 0, NULL, NULL );
if (written) *written = ret ? length : 0;
if (!ret) SetLastError( ERROR_INVALID_HANDLE );
return ret;
}