Author: jmorlan
Date: Tue Jun 8 08:38:14 2010
New Revision: 47693
URL:
http://svn.reactos.org/svn/reactos?rev=47693&view=rev
Log:
[KERNEL32], [WIN32CSR]
- Implement ReadConsoleW's CONSOLE_READCONSOLE_CONTROL structure.
- Make pressing Insert during line input work
Modified:
trunk/reactos/dll/win32/kernel32/misc/console.c
trunk/reactos/include/reactos/subsys/csrss/csrss.h
trunk/reactos/subsystems/win32/csrss/win32csr/coninput.c
trunk/reactos/subsystems/win32/csrss/win32csr/conio.h
trunk/reactos/subsystems/win32/csrss/win32csr/conoutput.c
trunk/reactos/subsystems/win32/csrss/win32csr/guiconsole.c
trunk/reactos/subsystems/win32/csrss/win32csr/lineinput.c
trunk/reactos/subsystems/win32/csrss/win32csr/tuiconsole.c
Modified: trunk/reactos/dll/win32/kernel32/misc/console.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/misc/co…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/misc/console.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/misc/console.c [iso-8859-1] Tue Jun 8 08:38:14 2010
@@ -1698,37 +1698,45 @@
PVOID lpBuffer,
DWORD nNumberOfCharsToRead,
LPDWORD lpNumberOfCharsRead,
- PCONSOLE_READCONSOLE_CONTROL lpReserved,
+ PCONSOLE_READCONSOLE_CONTROL pInputControl,
BOOL bUnicode)
{
- PCSR_API_MESSAGE Request;
- ULONG CsrRequest;
- NTSTATUS Status;
- ULONG CharSize, CharsRead = 0;
-
- CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
- Request = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- max(sizeof(CSR_API_MESSAGE),
- CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) +
min(nNumberOfCharsToRead,
- CSRSS_MAX_READ_CONSOLE / CharSize) * CharSize));
- if (Request == NULL)
+ CSR_API_MESSAGE Request;
+ PCSR_CAPTURE_BUFFER CaptureBuffer;
+ ULONG CsrRequest = MAKE_CSR_API(READ_CONSOLE, CSR_CONSOLE);
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+
+ CaptureBuffer = CsrAllocateCaptureBuffer(1, nNumberOfCharsToRead * CharSize);
+ if (CaptureBuffer == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
- Request->Status = STATUS_SUCCESS;
- Request->Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
- Request->Data.ReadConsoleRequest.Unicode = bUnicode;
- Request->Data.ReadConsoleRequest.FullReadSize = (WORD)nNumberOfCharsToRead;
- CsrRequest = MAKE_CSR_API(READ_CONSOLE, CSR_CONSOLE);
+ CsrAllocateMessagePointer(CaptureBuffer,
+ nNumberOfCharsToRead * CharSize,
+ &Request.Data.ReadConsoleRequest.Buffer);
+
+ Request.Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
+ Request.Data.ReadConsoleRequest.Unicode = bUnicode;
+ Request.Data.ReadConsoleRequest.NrCharactersToRead = (WORD)nNumberOfCharsToRead;
+ Request.Data.ReadConsoleRequest.NrCharactersRead = 0;
+ Request.Data.ReadConsoleRequest.CtrlWakeupMask = 0;
+ if (pInputControl && pInputControl->nLength ==
sizeof(CONSOLE_READCONSOLE_CONTROL))
+ {
+ Request.Data.ReadConsoleRequest.NrCharactersRead =
pInputControl->nInitialChars;
+ memcpy(Request.Data.ReadConsoleRequest.Buffer,
+ lpBuffer,
+ pInputControl->nInitialChars * sizeof(WCHAR));
+ Request.Data.ReadConsoleRequest.CtrlWakeupMask =
pInputControl->dwCtrlWakeupMask;
+ }
do
{
- if (Request->Status == STATUS_PENDING)
+ if (Status == STATUS_PENDING)
{
- Status =
NtWaitForSingleObject(Request->Data.ReadConsoleRequest.EventHandle,
+ Status = NtWaitForSingleObject(Request.Data.ReadConsoleRequest.EventHandle,
FALSE,
0);
if (!NT_SUCCESS(Status))
@@ -1738,37 +1746,28 @@
}
}
- Request->Data.ReadConsoleRequest.NrCharactersToRead =
(WORD)min(nNumberOfCharsToRead, CSRSS_MAX_READ_CONSOLE / CharSize);
-
- Status = CsrClientCallServer(Request,
- NULL,
- CsrRequest,
- max(sizeof(CSR_API_MESSAGE),
- CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE)
- +
Request->Data.ReadConsoleRequest.NrCharactersToRead * CharSize));
-
- if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
+ Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest,
sizeof(CSR_API_MESSAGE));
+ if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
{
DPRINT1("CSR returned error in ReadConsole\n");
- RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
+ CsrFreeCaptureBuffer(CaptureBuffer);
SetLastErrorByStatus(Status);
return FALSE;
}
-
- nNumberOfCharsToRead -= Request->Data.ReadConsoleRequest.NrCharactersRead;
- memcpy((PVOID)((ULONG_PTR)lpBuffer + (ULONG_PTR)(CharsRead * CharSize)),
- Request->Data.ReadConsoleRequest.Buffer,
- Request->Data.ReadConsoleRequest.NrCharactersRead * CharSize);
- CharsRead += Request->Data.ReadConsoleRequest.NrCharactersRead;
- }
- while (Request->Status == STATUS_PENDING && nNumberOfCharsToRead > 0);
+ }
+ while (Status == STATUS_PENDING);
+
+ memcpy(lpBuffer,
+ Request.Data.ReadConsoleRequest.Buffer,
+ Request.Data.ReadConsoleRequest.NrCharactersRead * CharSize);
if (lpNumberOfCharsRead != NULL)
- {
- *lpNumberOfCharsRead = CharsRead;
- }
-
- RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
+ *lpNumberOfCharsRead = Request.Data.ReadConsoleRequest.NrCharactersRead;
+
+ if (pInputControl && pInputControl->nLength ==
sizeof(CONSOLE_READCONSOLE_CONTROL))
+ pInputControl->dwControlKeyState =
Request.Data.ReadConsoleRequest.ControlKeyState;
+
+ CsrFreeCaptureBuffer(CaptureBuffer);
return TRUE;
}
@@ -1791,7 +1790,7 @@
lpBuffer,
nNumberOfCharsToRead,
lpNumberOfCharsRead,
- pInputControl,
+ NULL,
FALSE);
}
Modified: trunk/reactos/include/reactos/subsys/csrss/csrss.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/subsys/csr…
==============================================================================
--- trunk/reactos/include/reactos/subsys/csrss/csrss.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/subsys/csrss/csrss.h [iso-8859-1] Tue Jun 8 08:38:14
2010
@@ -70,11 +70,13 @@
{
HANDLE ConsoleHandle;
BOOL Unicode;
- WORD FullReadSize;
WORD NrCharactersToRead;
+ WORD NrCharactersRead;
HANDLE EventHandle;
- ULONG NrCharactersRead;
- BYTE Buffer[0];
+ PVOID Buffer;
+ UNICODE_STRING ExeName;
+ DWORD CtrlWakeupMask;
+ DWORD ControlKeyState;
} CSRSS_READ_CONSOLE, *PCSRSS_READ_CONSOLE;
typedef struct
@@ -515,7 +517,6 @@
#define CSRSS_MAX_WRITE_CONSOLE (LPC_MAX_DATA_LENGTH -
CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE))
#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR (LPC_MAX_DATA_LENGTH -
CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR))
#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB (LPC_MAX_DATA_LENGTH -
CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB))
-#define CSRSS_MAX_READ_CONSOLE (LPC_MAX_DATA_LENGTH -
CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE))
#define CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR (LPC_MAX_DATA_LENGTH -
CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR))
#define CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB (LPC_MAX_DATA_LENGTH -
CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB))
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/coninput.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/coninput.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/coninput.c [iso-8859-1] Tue Jun 8
08:38:14 2010
@@ -37,13 +37,18 @@
CharSize = (Request->Data.ReadConsoleRequest.Unicode ? sizeof(WCHAR) :
sizeof(CHAR));
- /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
- nNumberOfCharsToRead = min(Request->Data.ReadConsoleRequest.NrCharactersToRead,
CSRSS_MAX_READ_CONSOLE / CharSize);
+ nNumberOfCharsToRead = Request->Data.ReadConsoleRequest.NrCharactersToRead;
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) -
sizeof(PORT_MESSAGE);
Buffer = (PCHAR)Request->Data.ReadConsoleRequest.Buffer;
UnicodeBuffer = (PWCHAR)Buffer;
+ if (!Win32CsrValidateBuffer(ProcessData, Buffer, nNumberOfCharsToRead, CharSize))
+ return STATUS_ACCESS_VIOLATION;
+
+ if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) >
nNumberOfCharsToRead * CharSize)
+ return STATUS_INVALID_PARAMETER;
+
Status = ConioLockConsole(ProcessData,
Request->Data.ReadConsoleRequest.ConsoleHandle,
&Console, GENERIC_READ);
if (! NT_SUCCESS(Status))
@@ -58,7 +63,7 @@
if (Console->LineBuffer == NULL)
{
/* Starting a new line */
- Console->LineMaxSize = max(256,
Request->Data.ReadConsoleRequest.FullReadSize);
+ Console->LineMaxSize = max(256, nNumberOfCharsToRead);
Console->LineBuffer = HeapAlloc(Win32CsrApiHeap, 0,
Console->LineMaxSize * sizeof(WCHAR));
if (Console->LineBuffer == NULL)
{
@@ -66,9 +71,19 @@
goto done;
}
Console->LineComplete = FALSE;
- Console->LineSize = 0;
- Console->LinePos = 0;
Console->LineUpPressed = FALSE;
+ Console->LineInsertToggle = 0;
+ Console->LineWakeupMask =
Request->Data.ReadConsoleRequest.CtrlWakeupMask;
+ Console->LineSize = Request->Data.ReadConsoleRequest.NrCharactersRead;
+ Console->LinePos = Console->LineSize;
+ /* pre-filling the buffer is only allowed in the Unicode API,
+ * so we don't need to worry about conversion */
+ memcpy(Console->LineBuffer, Buffer, Console->LineSize *
sizeof(WCHAR));
+ if (Console->LineSize == Console->LineMaxSize)
+ {
+ Console->LineComplete = TRUE;
+ Console->LinePos = 0;
+ }
}
/* If we don't have a complete line yet, process the pending input */
@@ -87,6 +102,7 @@
&& Input->InputEvent.Event.KeyEvent.bKeyDown)
{
LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
+ Request->Data.ReadConsoleRequest.ControlKeyState =
Input->InputEvent.Event.KeyEvent.dwControlKeyState;
}
HeapFree(Win32CsrApiHeap, 0, Input);
}
@@ -104,10 +120,11 @@
}
if (Console->LinePos == Console->LineSize)
{
+ /* Entire line has been read */
HeapFree(Win32CsrApiHeap, 0, Console->LineBuffer);
Console->LineBuffer = NULL;
- Status = STATUS_SUCCESS; /* Entire line has been read */
- }
+ }
+ Status = STATUS_SUCCESS;
}
}
else
@@ -141,12 +158,6 @@
done:
Request->Data.ReadConsoleRequest.NrCharactersRead = i;
ConioUnlockConsole(Console);
-
- if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize >
sizeof(CSR_API_MESSAGE))
- {
- Request->Header.u1.s1.TotalLength =
CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize;
- Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength -
sizeof(PORT_MESSAGE);
- }
return Status;
}
@@ -355,6 +366,12 @@
current_entry = current_entry->Flink;
ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
}
+ if (Console->LineBuffer && !Console->LineComplete)
+ {
+ /* Line input is in progress; end it */
+ Console->LinePos = Console->LineSize = 0;
+ Console->LineComplete = TRUE;
+ }
return;
}
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/conio.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/conio.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/conio.h [iso-8859-1] Tue Jun 8 08:38:14
2010
@@ -81,6 +81,8 @@
WORD LinePos; /* current position within line */
BOOLEAN LineComplete; /* user pressed enter, ready to send back to
client */
BOOLEAN LineUpPressed;
+ BOOLEAN LineInsertToggle; /* replace character over cursor instead of
inserting */
+ ULONG LineWakeupMask; /* bitmap of which control characters will end
line input */
LIST_ENTRY HistoryBuffers;
WORD HistoryBufferSize; /* size for newly created history buffers */
WORD NumberOfHistoryBuffers; /* maximum number of history buffers allowed */
@@ -192,6 +194,7 @@
CHAR *Buffer, DWORD Length, BOOL Attrib);
NTSTATUS FASTCALL CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER
Buffer);
VOID WINAPI ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer);
+DWORD FASTCALL ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale);
CSR_API(CsrWriteConsole);
CSR_API(CsrGetScreenBufferInfo);
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/conoutput.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/conoutput.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/conoutput.c [iso-8859-1] Tue Jun 8
08:38:14 2010
@@ -865,6 +865,16 @@
return STATUS_SUCCESS;
}
+DWORD FASTCALL
+ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale)
+{
+ DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100;
+ /* If line input in progress, perhaps adjust for insert toggle */
+ if (Console->LineBuffer && !Console->LineComplete &&
Console->LineInsertToggle)
+ return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2);
+ return Size;
+}
+
CSR_API(CsrGetCursorInfo)
{
PCSRSS_SCREEN_BUFFER Buff;
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/guiconsole.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/guiconsole.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/guiconsole.c [iso-8859-1] Tue Jun 8
08:38:14 2010
@@ -946,11 +946,7 @@
if (LeftChar <= CursorX && CursorX <= RightChar &&
TopLine <= CursorY && CursorY <= BottomLine)
{
- CursorHeight = (GuiData->CharHeight * Buff->CursorInfo.dwSize) / 100;
- if (CursorHeight < 1)
- {
- CursorHeight = 1;
- }
+ CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
From = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY) + 1;
if (*From != DEFAULT_ATTRIB)
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/lineinput.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/lineinput.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/lineinput.c [iso-8859-1] Tue Jun 8
08:38:14 2010
@@ -459,6 +459,11 @@
LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]);
}
return;
+ case VK_INSERT:
+ /* Toggle between insert and overstrike */
+ Console->LineInsertToggle = !Console->LineInsertToggle;
+ ConioSetCursorInfo(Console, Console->ActiveBuffer);
+ return;
case VK_DELETE:
/* Remove character to right of cursor */
if (Pos != Console->LineSize)
@@ -555,7 +560,12 @@
Console->LineBuffer[Console->LineSize++] = L'\r';
if (Console->Mode & ENABLE_ECHO_INPUT)
ConioWriteConsole(Console, Console->ActiveBuffer, "\r", 1,
TRUE);
- if (Console->Mode & ENABLE_PROCESSED_INPUT)
+
+ /* Add \n if processed input. There should usually be room for it,
+ * but an exception to the rule exists: the buffer could have been
+ * pre-filled with LineMaxSize - 1 characters. */
+ if (Console->Mode & ENABLE_PROCESSED_INPUT &&
+ Console->LineSize < Console->LineMaxSize)
{
Console->LineBuffer[Console->LineSize++] = L'\n';
if (Console->Mode & ENABLE_ECHO_INPUT)
@@ -566,8 +576,21 @@
}
else if (KeyEvent->uChar.UnicodeChar != L'\0')
{
- /* Normal character */
- LineInputEdit(Console, 0, 1, &KeyEvent->uChar.UnicodeChar);
+ if (KeyEvent->uChar.UnicodeChar < 0x20 &&
+ Console->LineWakeupMask & (1 <<
KeyEvent->uChar.UnicodeChar))
+ {
+ /* Control key client wants to handle itself (e.g. for tab completion) */
+ Console->LineBuffer[Console->LineSize++] = L' ';
+ Console->LineBuffer[Console->LinePos] =
KeyEvent->uChar.UnicodeChar;
+ Console->LineComplete = TRUE;
+ Console->LinePos = 0;
+ }
+ else
+ {
+ /* Normal character */
+ BOOL Overstrike = Console->LineInsertToggle && Console->LinePos
!= Console->LineSize;
+ LineInputEdit(Console, Overstrike, 1, &KeyEvent->uChar.UnicodeChar);
+ }
}
}
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/tuiconsole.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/tuiconsole.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/tuiconsole.c [iso-8859-1] Tue Jun 8
08:38:14 2010
@@ -208,6 +208,7 @@
static BOOL WINAPI
TuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
{
+ CONSOLE_CURSOR_INFO Info;
DWORD BytesReturned;
if (ActiveConsole->ActiveBuffer != Buff)
@@ -215,9 +216,11 @@
return TRUE;
}
+ Info.dwSize = ConioEffectiveCursorSize(Console, 100);
+ Info.bVisible = Buff->CursorInfo.bVisible;
+
if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO,
- &Buff->CursorInfo, sizeof(Buff->CursorInfo), NULL,
0,
- &BytesReturned, NULL))
+ &Info, sizeof(Info), NULL, 0, &BytesReturned, NULL))
{
DPRINT1( "Failed to set cursor info\n" );
return FALSE;