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/con... ============================================================================== --- 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/csrs... ============================================================================== --- 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/win3... ============================================================================== --- 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/win3... ============================================================================== --- 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/win3... ============================================================================== --- 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/win3... ============================================================================== --- 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/win3... ============================================================================== --- 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/win3... ============================================================================== --- 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;