From: Hermès Bélusca-Maïto Date: Sat, 17 Nov 2012 21:39:41 +0000 (+0000) Subject: [KERNEL32/CONSRV] X-Git-Tag: backups/ros-csrss@60644~140 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=2006c3bf86d4120299f5d930b2287daecdfbbc25 [KERNEL32/CONSRV] - Move the waiting loop of IntReadConsole into SrvReadConsole instead. - Merge IntPeekConsoleInput and IntReadConsoleInput helpers into a single IntGetConsoleInput helper function and make PeekConsoleInputW/A and ReadConsoleInputW/A use it. Indeed, the "only" difference between these two functions, is that the first one keeps the data read inside the console input buffer, but on the contrary the second removes the data and does not return until at least one input record has been read. In server-side, CsrReadInputEvent and CsrPeekConsoleInput are merged into SrvGetConsoleInput. Merge the corresponding structures. - Use shorter variable names in IntReadConsoleOutput and use CONSOLE_PROCESS_DATA structure in SrvReadConsoleOutput. - Merge IntReadConsoleOutputCharacter and ReadConsoleOutputAttribute functions into a single IntReadConsoleOutputCode helper function, and make ReadConsoleOutputAttribute and ReadConsoleOutputCharacterW/A use it. In server-side, CsrReadConsoleOutputChar and CsrReadConsoleOutputAttrib are merged into SrvReadConsoleOutputString. (Remark: the SrvReadConsoleOutputString name comes from http://j00ru.vexillium.org/csrss_list/api_list.html and I checked that it was indeed the server function that was called by both ReadConsoleOutputAttribute and ReadConsoleOutputCharacter). The idea behind merging these two functions is, that an attribute or a character are instances of the same entity, namely a "code" (what would be called an (ANSI) escape sequence). Therefore I encode them inside the same CSRSS_READ_CONSOLE_OUTPUT_CODE structure and I use it with the previous functions. [CONSRV] - Make use of the CONSOLE_PROCESS_DATA structure (introduced in r57685). - Use CsrValidateMessageBuffer instead of Win32CsrValidateBuffer. - Reorganize conmsg.h a little bit. svn path=/branches/ros-csrss/; revision=57721 --- diff --git a/dll/win32/kernel32/client/console/readwrite.c b/dll/win32/kernel32/client/console/readwrite.c index 9112769c65e..33340bad873 100644 --- a/dll/win32/kernel32/client/console/readwrite.c +++ b/dll/win32/kernel32/client/console/readwrite.c @@ -33,13 +33,18 @@ IntReadConsole(HANDLE hConsoleInput, PCONSOLE_READCONSOLE_CONTROL pInputControl, BOOL bUnicode) { - CSR_API_MESSAGE Request; - ULONG CsrRequest; + NTSTATUS Status; + CONSOLE_API_MESSAGE ApiMessage; + PCSRSS_READ_CONSOLE ReadConsoleRequest = &ApiMessage.Data.ReadConsoleRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - NTSTATUS Status = STATUS_SUCCESS; - ULONG CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + ULONG CharSize; - CaptureBuffer = CsrAllocateCaptureBuffer(1, nNumberOfCharsToRead * CharSize); + /* Determine the needed size */ + CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + ReadConsoleRequest->BufferSize = nNumberOfCharsToRead * CharSize; + + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, ReadConsoleRequest->BufferSize); if (CaptureBuffer == NULL) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); @@ -47,63 +52,46 @@ IntReadConsole(HANDLE hConsoleInput, return FALSE; } + /* Allocate space in the Buffer */ 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; + ReadConsoleRequest->BufferSize, + (PVOID*)&ReadConsoleRequest->Buffer); + + ReadConsoleRequest->ConsoleHandle = hConsoleInput; + ReadConsoleRequest->Unicode = bUnicode; + ReadConsoleRequest->NrCharactersToRead = (WORD)nNumberOfCharsToRead; + ReadConsoleRequest->NrCharactersRead = 0; + ReadConsoleRequest->CtrlWakeupMask = 0; if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) { - Request.Data.ReadConsoleRequest.NrCharactersRead = pInputControl->nInitialChars; - memcpy(Request.Data.ReadConsoleRequest.Buffer, + ReadConsoleRequest->NrCharactersRead = pInputControl->nInitialChars; + memcpy(ReadConsoleRequest->Buffer, lpBuffer, pInputControl->nInitialChars * sizeof(WCHAR)); - Request.Data.ReadConsoleRequest.CtrlWakeupMask = pInputControl->dwCtrlWakeupMask; + ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask; } - CsrRequest = CSR_CREATE_API_NUMBER(CSR_CONSOLE, READ_CONSOLE); - - do + Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsole), + sizeof(CSRSS_READ_CONSOLE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status)) { - if (Status == STATUS_PENDING) - { - Status = NtWaitForSingleObject(Request.Data.ReadConsoleRequest.EventHandle, - FALSE, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Wait for console input failed!\n"); - break; - } - } - - 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"); - CsrFreeCaptureBuffer(CaptureBuffer); - BaseSetLastNTError(Status); - return FALSE; - } + DPRINT1("CSR returned error in ReadConsole\n"); + CsrFreeCaptureBuffer(CaptureBuffer); + BaseSetLastNTError(Status); + return FALSE; } - while (Status == STATUS_PENDING); memcpy(lpBuffer, - Request.Data.ReadConsoleRequest.Buffer, - Request.Data.ReadConsoleRequest.NrCharactersRead * CharSize); + ReadConsoleRequest->Buffer, + ReadConsoleRequest->NrCharactersRead * CharSize); if (lpNumberOfCharsRead != NULL) - *lpNumberOfCharsRead = Request.Data.ReadConsoleRequest.NrCharactersRead; + *lpNumberOfCharsRead = ReadConsoleRequest->NrCharactersRead; if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) - pInputControl->dwControlKeyState = Request.Data.ReadConsoleRequest.ControlKeyState; + pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState; CsrFreeCaptureBuffer(CaptureBuffer); @@ -113,13 +101,16 @@ IntReadConsole(HANDLE hConsoleInput, static BOOL -IntPeekConsoleInput(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead, - BOOL bUnicode) +IntGetConsoleInput(HANDLE hConsoleInput, + BOOL bRead, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead, + BOOL bUnicode) { - CSR_API_MESSAGE Request; + NTSTATUS Status; + CONSOLE_API_MESSAGE ApiMessage; + PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &ApiMessage.Data.GetConsoleInputRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; ULONG Size; @@ -131,8 +122,9 @@ IntPeekConsoleInput(HANDLE hConsoleInput, Size = nLength * sizeof(INPUT_RECORD); + DPRINT("IntGetConsoleInput: %lx %p\n", Size, lpNumberOfEventsRead); + /* Allocate a Capture Buffer */ - DPRINT("IntPeekConsoleInput: %lx %p\n", Size, lpNumberOfEventsRead); CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); if (CaptureBuffer == NULL) { @@ -142,126 +134,111 @@ IntPeekConsoleInput(HANDLE hConsoleInput, } /* Allocate space in the Buffer */ - CsrCaptureMessageBuffer(CaptureBuffer, - NULL, - Size, - (PVOID*)&Request.Data.PeekConsoleInputRequest.InputRecord); + CsrAllocateMessagePointer(CaptureBuffer, + Size, + (PVOID*)&GetConsoleInputRequest->InputRecord); /* Set up the data to send to the Console Server */ - Request.Data.PeekConsoleInputRequest.ConsoleHandle = hConsoleInput; - Request.Data.PeekConsoleInputRequest.Unicode = bUnicode; - Request.Data.PeekConsoleInputRequest.Length = nLength; - - /* Call the server */ - CsrClientCallServer(&Request, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CSR_CONSOLE, PEEK_CONSOLE_INPUT), - sizeof(CSR_API_MESSAGE)); - DPRINT("Server returned: %x\n", Request.Status); - - /* Check for success*/ - if (NT_SUCCESS(Request.Status)) + GetConsoleInputRequest->ConsoleHandle = hConsoleInput; + GetConsoleInputRequest->Unicode = bUnicode; + GetConsoleInputRequest->bRead = bRead; + if (bRead == TRUE) { - /* Return the number of events read */ - DPRINT("Events read: %lx\n", Request.Data.PeekConsoleInputRequest.Length); - *lpNumberOfEventsRead = Request.Data.PeekConsoleInputRequest.Length; - - /* Copy into the buffer */ - DPRINT("Copying to buffer\n"); - RtlCopyMemory(lpBuffer, - Request.Data.PeekConsoleInputRequest.InputRecord, - sizeof(INPUT_RECORD) * *lpNumberOfEventsRead); + GetConsoleInputRequest->InputsRead = 0; } - else + GetConsoleInputRequest->Length = nLength; + + /* Call the server */ + Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleInput), + sizeof(CSRSS_GET_CONSOLE_INPUT)); + DPRINT("Server returned: %x\n", ApiMessage.Status); + +/** For Read only ** + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status)) { - /* Error out */ - *lpNumberOfEventsRead = 0; - BaseSetLastNTError(Request.Status); + // BaseSetLastNTError(Status); ???? + if (GetConsoleInputRequest->InputsRead == 0) + { + /\* we couldn't read a single record, fail *\/ + BaseSetLastNTError(Status); + return FALSE; + } + else + { + /\* FIXME - fail gracefully in case we already read at least one record? *\/ + // break; + } } +**/ - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); + /** + ** TODO: !! Simplify the function !! + **/ + if (bRead == TRUE) // ReadConsoleInput call. + { + /* Check for success */ + if (NT_SUCCESS(Status) || NT_SUCCESS(Status = ApiMessage.Status)) + { + /* Return the number of events read */ + DPRINT("Events read: %lx\n", GetConsoleInputRequest->InputsRead/*Length*/); - /* Return TRUE or FALSE */ - return NT_SUCCESS(Request.Status); -} + if (lpNumberOfEventsRead != NULL) + *lpNumberOfEventsRead = GetConsoleInputRequest->InputsRead/*Length*/; + /* Copy into the buffer */ + DPRINT("Copying to buffer\n"); + RtlCopyMemory(lpBuffer, + GetConsoleInputRequest->InputRecord, + sizeof(INPUT_RECORD) * GetConsoleInputRequest->InputsRead/*Length*/); + } + else + { + if (lpNumberOfEventsRead != NULL) + *lpNumberOfEventsRead = 0; -static -BOOL -IntReadConsoleInput(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead, - BOOL bUnicode) -{ - CSR_API_MESSAGE Request; - ULONG CsrRequest; - ULONG Read; - NTSTATUS Status; + /* Error out */ + BaseSetLastNTError(ApiMessage.Status); + } - CsrRequest = CSR_CREATE_API_NUMBER(CSR_CONSOLE, READ_INPUT); - Read = 0; + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); - while (nLength > 0) + return (GetConsoleInputRequest->InputsRead > 0); + } + else // PeekConsoleInput call. { - Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput; - Request.Data.ReadInputRequest.Unicode = bUnicode; - - Status = CsrClientCallServer(&Request, - NULL, - CsrRequest, - sizeof(CSR_API_MESSAGE)); - if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) - { - if (Read == 0) - { - /* we couldn't read a single record, fail */ - BaseSetLastNTError(Status); - return FALSE; - } - else - { - /* FIXME - fail gracefully in case we already read at least one record? */ - break; - } - } - else if (Status == STATUS_PENDING) + /* Check for success */ + if (NT_SUCCESS(Status) || NT_SUCCESS(ApiMessage.Status)) { - if (Read == 0) - { - Status = NtWaitForSingleObject(Request.Data.ReadInputRequest.Event, FALSE, 0); - if (!NT_SUCCESS(Status)) - { - BaseSetLastNTError(Status); - break; - } - } - else - { - /* nothing more to read (waiting for more input??), let's just bail */ - break; - } + /* Return the number of events read */ + DPRINT("Events read: %lx\n", GetConsoleInputRequest->Length); + + if (lpNumberOfEventsRead != NULL) + *lpNumberOfEventsRead = GetConsoleInputRequest->Length; + + /* Copy into the buffer */ + DPRINT("Copying to buffer\n"); + RtlCopyMemory(lpBuffer, + GetConsoleInputRequest->InputRecord, + sizeof(INPUT_RECORD) * GetConsoleInputRequest->Length); } else { - lpBuffer[Read++] = Request.Data.ReadInputRequest.Input; - nLength--; - - if (!Request.Data.ReadInputRequest.MoreEvents) - { - /* nothing more to read, bail */ - break; - } + if (lpNumberOfEventsRead != NULL) + *lpNumberOfEventsRead = 0; + + /* Error out */ + BaseSetLastNTError(ApiMessage.Status); } - } - if (lpNumberOfEventsRead != NULL) - { - *lpNumberOfEventsRead = Read; - } + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); - return (Read > 0); + /* Return TRUE or FALSE */ + return NT_SUCCESS(ApiMessage.Status); + } } @@ -274,7 +251,8 @@ IntReadConsoleOutput(HANDLE hConsoleOutput, PSMALL_RECT lpReadRegion, BOOL bUnicode) { - CSR_API_MESSAGE Request; + CONSOLE_API_MESSAGE ApiMessage; + PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest = &ApiMessage.Data.ReadConsoleOutputRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; DWORD Size, SizeX, SizeY; @@ -286,8 +264,9 @@ IntReadConsoleOutput(HANDLE hConsoleOutput, Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO); - /* Allocate a Capture Buffer */ DPRINT("IntReadConsoleOutput: %lx %p\n", Size, lpReadRegion); + + /* Allocate a Capture Buffer */ CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); if (CaptureBuffer == NULL) { @@ -297,124 +276,140 @@ IntReadConsoleOutput(HANDLE hConsoleOutput, } /* Allocate space in the Buffer */ - CsrCaptureMessageBuffer(CaptureBuffer, - NULL, - Size, - (PVOID*)&Request.Data.ReadConsoleOutputRequest.CharInfo); + CsrAllocateMessagePointer(CaptureBuffer, + Size, + (PVOID*)&ReadConsoleOutputRequest->CharInfo); /* Set up the data to send to the Console Server */ - Request.Data.ReadConsoleOutputRequest.ConsoleHandle = hConsoleOutput; - Request.Data.ReadConsoleOutputRequest.Unicode = bUnicode; - Request.Data.ReadConsoleOutputRequest.BufferSize = dwBufferSize; - Request.Data.ReadConsoleOutputRequest.BufferCoord = dwBufferCoord; - Request.Data.ReadConsoleOutputRequest.ReadRegion = *lpReadRegion; + ReadConsoleOutputRequest->ConsoleHandle = hConsoleOutput; + ReadConsoleOutputRequest->Unicode = bUnicode; + ReadConsoleOutputRequest->BufferSize = dwBufferSize; + ReadConsoleOutputRequest->BufferCoord = dwBufferCoord; + ReadConsoleOutputRequest->ReadRegion = *lpReadRegion; /* Call the server */ - CsrClientCallServer(&Request, + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, - CSR_CREATE_API_NUMBER(CSR_CONSOLE, READ_CONSOLE_OUTPUT), - sizeof(CSR_API_MESSAGE)); - DPRINT("Server returned: %x\n", Request.Status); + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutput), + sizeof(CSRSS_READ_CONSOLE_OUTPUT)); + DPRINT("Server returned: %x\n", ApiMessage.Status); /* Check for success*/ - if (NT_SUCCESS(Request.Status)) + if (NT_SUCCESS(ApiMessage.Status)) { /* Copy into the buffer */ DPRINT("Copying to buffer\n"); - SizeX = Request.Data.ReadConsoleOutputRequest.ReadRegion.Right - - Request.Data.ReadConsoleOutputRequest.ReadRegion.Left + 1; - SizeY = Request.Data.ReadConsoleOutputRequest.ReadRegion.Bottom - - Request.Data.ReadConsoleOutputRequest.ReadRegion.Top + 1; + SizeX = ReadConsoleOutputRequest->ReadRegion.Right - + ReadConsoleOutputRequest->ReadRegion.Left + 1; + SizeY = ReadConsoleOutputRequest->ReadRegion.Bottom - + ReadConsoleOutputRequest->ReadRegion.Top + 1; RtlCopyMemory(lpBuffer, - Request.Data.ReadConsoleOutputRequest.CharInfo, + ReadConsoleOutputRequest->CharInfo, sizeof(CHAR_INFO) * SizeX * SizeY); } else { /* Error out */ - BaseSetLastNTError(Request.Status); + BaseSetLastNTError(ApiMessage.Status); } /* Return the read region */ - DPRINT("read region: %lx\n", Request.Data.ReadConsoleOutputRequest.ReadRegion); - *lpReadRegion = Request.Data.ReadConsoleOutputRequest.ReadRegion; + DPRINT("read region: %lx\n", ReadConsoleOutputRequest->ReadRegion); + *lpReadRegion = ReadConsoleOutputRequest->ReadRegion; /* Release the capture buffer */ CsrFreeCaptureBuffer(CaptureBuffer); /* Return TRUE or FALSE */ - return NT_SUCCESS(Request.Status); + return NT_SUCCESS(ApiMessage.Status); } static BOOL -IntReadConsoleOutputCharacter(HANDLE hConsoleOutput, - PVOID lpCharacter, - DWORD nLength, - COORD dwReadCoord, - LPDWORD lpNumberOfCharsRead, - BOOL bUnicode) +IntReadConsoleOutputCode(HANDLE hConsoleOutput, + USHORT CodeType, + PVOID pCode, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfCodesRead) { - PCSR_API_MESSAGE Request; - ULONG CsrRequest; NTSTATUS Status; - ULONG SizeBytes, CharSize; - DWORD CharsRead = 0; + CONSOLE_API_MESSAGE ApiMessage; + PCSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest = &ApiMessage.Data.ReadConsoleOutputCodeRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG SizeBytes, CodeSize; + DWORD /*CodesRead = 0,*/ BytesRead; - CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + /* Determine the needed size */ + switch (CodeType) + { + case CODE_ASCII: + CodeSize = sizeof(CHAR); + break; - nLength = min(nLength, CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR / CharSize); - SizeBytes = nLength * CharSize; + case CODE_UNICODE: + CodeSize = sizeof(WCHAR); + break; - Request = RtlAllocateHeap(RtlGetProcessHeap(), 0, - max(sizeof(CSR_API_MESSAGE), - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) + SizeBytes)); - if (Request == NULL) + case CODE_ATTRIBUTE: + CodeSize = sizeof(WORD); + break; + + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + SizeBytes = nLength * CodeSize; + + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); + if (CaptureBuffer == NULL) { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } - CsrRequest = CSR_CREATE_API_NUMBER(CSR_CONSOLE, READ_CONSOLE_OUTPUT_CHAR); - Request->Data.ReadConsoleOutputCharRequest.ReadCoord = dwReadCoord; + /* Allocate space in the Buffer */ + CsrAllocateMessagePointer(CaptureBuffer, + SizeBytes, + (PVOID*)&ReadConsoleOutputCodeRequest->pCode.pCode); - while (nLength > 0) - { - DWORD BytesRead; + /* Start reading */ + ReadConsoleOutputCodeRequest->ConsoleHandle = hConsoleOutput; + ReadConsoleOutputCodeRequest->CodeType = CodeType; + ReadConsoleOutputCodeRequest->ReadCoord = dwReadCoord; - Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput; - Request->Data.ReadConsoleOutputCharRequest.Unicode = bUnicode; - Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead = nLength; - SizeBytes = Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead * CharSize; + // while (nLength > 0) + { + ReadConsoleOutputCodeRequest->NumCodesToRead = nLength; + // SizeBytes = ReadConsoleOutputCodeRequest->NumCodesToRead * CodeSize; - Status = CsrClientCallServer(Request, - NULL, - CsrRequest, - max(sizeof(CSR_API_MESSAGE), - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) + SizeBytes)); - if (!NT_SUCCESS(Status) || !NT_SUCCESS(Request->Status)) + Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutputString), + sizeof(CSRSS_READ_CONSOLE_OUTPUT_CODE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status)) { - RtlFreeHeap(RtlGetProcessHeap(), 0, Request); BaseSetLastNTError(Status); - break; + CsrFreeCaptureBuffer(CaptureBuffer); + return FALSE; } - BytesRead = Request->Data.ReadConsoleOutputCharRequest.CharsRead * CharSize; - memcpy(lpCharacter, Request->Data.ReadConsoleOutputCharRequest.String, BytesRead); - lpCharacter = (PVOID)((ULONG_PTR)lpCharacter + (ULONG_PTR)BytesRead); - CharsRead += Request->Data.ReadConsoleOutputCharRequest.CharsRead; - nLength -= Request->Data.ReadConsoleOutputCharRequest.CharsRead; + BytesRead = ReadConsoleOutputCodeRequest->CodesRead * CodeSize; + memcpy(pCode, ReadConsoleOutputCodeRequest->pCode.pCode, BytesRead); + // pCode = (PVOID)((ULONG_PTR)pCode + /*(ULONG_PTR)*/BytesRead); + // nLength -= ReadConsoleOutputCodeRequest->CodesRead; + // CodesRead += ReadConsoleOutputCodeRequest->CodesRead; - Request->Data.ReadConsoleOutputCharRequest.ReadCoord = Request->Data.ReadConsoleOutputCharRequest.EndCoord; + ReadConsoleOutputCodeRequest->ReadCoord = ReadConsoleOutputCodeRequest->EndCoord; } - if (lpNumberOfCharsRead != NULL) - { - *lpNumberOfCharsRead = CharsRead; - } + if (lpNumberOfCodesRead != NULL) + *lpNumberOfCodesRead = /*CodesRead;*/ ReadConsoleOutputCodeRequest->CodesRead; - RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + CsrFreeCaptureBuffer(CaptureBuffer); return TRUE; } @@ -818,10 +813,12 @@ PeekConsoleInputW(HANDLE hConsoleInput, DWORD nLength, LPDWORD lpNumberOfEventsRead) { - return IntPeekConsoleInput(hConsoleInput, - lpBuffer, nLength, - lpNumberOfEventsRead, - TRUE); + return IntGetConsoleInput(hConsoleInput, + FALSE, + lpBuffer, + nLength, + lpNumberOfEventsRead, + TRUE); } @@ -837,11 +834,12 @@ PeekConsoleInputA(HANDLE hConsoleInput, DWORD nLength, LPDWORD lpNumberOfEventsRead) { - return IntPeekConsoleInput(hConsoleInput, - lpBuffer, - nLength, - lpNumberOfEventsRead, - FALSE); + return IntGetConsoleInput(hConsoleInput, + FALSE, + lpBuffer, + nLength, + lpNumberOfEventsRead, + FALSE); } @@ -857,11 +855,12 @@ ReadConsoleInputW(HANDLE hConsoleInput, DWORD nLength, LPDWORD lpNumberOfEventsRead) { - return IntReadConsoleInput(hConsoleInput, - lpBuffer, - nLength, - lpNumberOfEventsRead, - TRUE); + return IntGetConsoleInput(hConsoleInput, + TRUE, + lpBuffer, + nLength, + lpNumberOfEventsRead, + TRUE); } @@ -877,11 +876,12 @@ ReadConsoleInputA(HANDLE hConsoleInput, DWORD nLength, LPDWORD lpNumberOfEventsRead) { - return IntReadConsoleInput(hConsoleInput, - lpBuffer, - nLength, - lpNumberOfEventsRead, - FALSE); + return IntGetConsoleInput(hConsoleInput, + TRUE, + lpBuffer, + nLength, + lpNumberOfEventsRead, + FALSE); } @@ -960,12 +960,12 @@ ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead) { - return IntReadConsoleOutputCharacter(hConsoleOutput, - (PVOID)lpCharacter, - nLength, - dwReadCoord, - lpNumberOfCharsRead, - TRUE); + return IntReadConsoleOutputCode(hConsoleOutput, + CODE_UNICODE, + lpCharacter, + nLength, + dwReadCoord, + lpNumberOfCharsRead); } @@ -982,12 +982,12 @@ ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead) { - return IntReadConsoleOutputCharacter(hConsoleOutput, - (PVOID)lpCharacter, - nLength, - dwReadCoord, - lpNumberOfCharsRead, - FALSE); + return IntReadConsoleOutputCode(hConsoleOutput, + CODE_ASCII, + lpCharacter, + nLength, + dwReadCoord, + lpNumberOfCharsRead); } @@ -1004,60 +1004,12 @@ ReadConsoleOutputAttribute(HANDLE hConsoleOutput, COORD dwReadCoord, LPDWORD lpNumberOfAttrsRead) { - PCSR_API_MESSAGE Request; - ULONG CsrRequest; - NTSTATUS Status; - DWORD Size; - - if (lpNumberOfAttrsRead != NULL) - *lpNumberOfAttrsRead = nLength; - - Request = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - max(sizeof(CSR_API_MESSAGE), - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB) - + min (nLength, CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB / sizeof(WORD)) * sizeof(WORD))); - if (Request == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - CsrRequest = CSR_CREATE_API_NUMBER(CSR_CONSOLE, READ_CONSOLE_OUTPUT_ATTRIB); - - while (nLength != 0) - { - Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput; - Request->Data.ReadConsoleOutputAttribRequest.ReadCoord = dwReadCoord; - - if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB / sizeof(WORD)) - Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB / sizeof(WCHAR); - else - Size = nLength; - - Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead = Size; - - Status = CsrClientCallServer(Request, - NULL, - CsrRequest, - max(sizeof(CSR_API_MESSAGE), - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB) + Size * sizeof(WORD))); - if (!NT_SUCCESS(Status) || !NT_SUCCESS(Request->Status)) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, Request); - BaseSetLastNTError(Status); - return FALSE; - } - - memcpy(lpAttribute, Request->Data.ReadConsoleOutputAttribRequest.Attribute, Size * sizeof(WORD)); - lpAttribute += Size; - nLength -= Size; - Request->Data.ReadConsoleOutputAttribRequest.ReadCoord = Request->Data.ReadConsoleOutputAttribRequest.EndCoord; - } - - RtlFreeHeap(RtlGetProcessHeap(), 0, Request); - - return TRUE; + return IntReadConsoleOutputCode(hConsoleOutput, + CODE_ATTRIBUTE, + lpAttribute, + nLength, + dwReadCoord, + lpNumberOfAttrsRead); } diff --git a/include/reactos/subsys/win/conmsg.h b/include/reactos/subsys/win/conmsg.h index 6c03b3a0948..5b5a8ce33f7 100644 --- a/include/reactos/subsys/win/conmsg.h +++ b/include/reactos/subsys/win/conmsg.h @@ -25,7 +25,7 @@ typedef enum _CONSRV_API_NUMBER ConsolepWriteConsoleInput, ConsolepReadConsoleOutput, ConsolepWriteConsoleOutput, - // ConsolepReadConsoleOutputString, + ConsolepReadConsoleOutputString, // ConsolepWriteConsoleOutputString, // ConsolepFillConsoleOutput, ConsolepGetMode, @@ -147,7 +147,10 @@ typedef struct WORD NrCharactersToRead; WORD NrCharactersRead; HANDLE EventHandle; + PVOID Buffer; + ULONG BufferSize; + UNICODE_STRING ExeName; DWORD CtrlWakeupMask; DWORD ControlKeyState; @@ -202,15 +205,6 @@ typedef struct WORD Length; } CSRSS_FILL_OUTPUT_ATTRIB, *PCSRSS_FILL_OUTPUT_ATTRIB; -typedef struct -{ - HANDLE ConsoleHandle; - BOOL Unicode; - INPUT_RECORD Input; - BOOL MoreEvents; - HANDLE Event; -} CSRSS_READ_INPUT, *PCSRSS_READ_INPUT; - typedef struct { HANDLE ConsoleHandle; @@ -312,34 +306,55 @@ typedef struct CHAR_INFO Fill; } CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER, *PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER; -typedef struct + +/* + * An attribute or a character are instances of the same entity, namely + * a "code" (what would be called an (ANSI) escape sequence). Therefore + * encode them inside the same structure. + */ +typedef enum _CODE_TYPE { - HANDLE ConsoleHandle; - BOOL Unicode; - DWORD NumCharsToRead; - COORD ReadCoord; - COORD EndCoord; - DWORD CharsRead; - CHAR String[0]; -} CSRSS_READ_CONSOLE_OUTPUT_CHAR, *PCSRSS_READ_CONSOLE_OUTPUT_CHAR; + CODE_ASCII = 0x01, + CODE_UNICODE = 0x02, + CODE_ATTRIBUTE = 0x03 +} CODE_TYPE; typedef struct { - HANDLE ConsoleHandle; - DWORD NumAttrsToRead; + HANDLE ConsoleHandle; + CODE_TYPE CodeType; + + DWORD NumCodesToRead; COORD ReadCoord; COORD EndCoord; - WORD Attribute[0]; -} CSRSS_READ_CONSOLE_OUTPUT_ATTRIB, *PCSRSS_READ_CONSOLE_OUTPUT_ATTRIB; + + DWORD CodesRead; + + union + { + PVOID pCode; + PCHAR AsciiChar; + PWCHAR UnicodeChar; + PWORD Attribute; + } pCode; // Either a pointer to a character or to an attribute. +} CSRSS_READ_CONSOLE_OUTPUT_CODE, *PCSRSS_READ_CONSOLE_OUTPUT_CODE; typedef struct { HANDLE ConsoleHandle; BOOL Unicode; + BOOL bRead; // TRUE --> Read ; FALSE --> Peek + DWORD Length; INPUT_RECORD* InputRecord; -} CSRSS_PEEK_CONSOLE_INPUT, *PCSRSS_PEEK_CONSOLE_INPUT; + + /** For Read **/ + ULONG InputsRead; + // INPUT_RECORD Input; + BOOL MoreEvents; + HANDLE Event; +} CSRSS_GET_CONSOLE_INPUT, *PCSRSS_GET_CONSOLE_INPUT; typedef struct { @@ -557,14 +572,12 @@ typedef struct _CONSOLE_API_MESSAGE union { CSRSS_WRITE_CONSOLE WriteConsoleRequest; - CSRSS_READ_CONSOLE ReadConsoleRequest; CSRSS_ALLOC_CONSOLE AllocConsoleRequest; CSRSS_FREE_CONSOLE FreeConsoleRequest; CSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest; CSRSS_SET_CURSOR SetCursorRequest; CSRSS_FILL_OUTPUT FillOutputRequest; CSRSS_FILL_OUTPUT_ATTRIB FillOutputAttribRequest; - CSRSS_READ_INPUT ReadInputRequest; CSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest; CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB WriteConsoleOutputAttribRequest; CSRSS_GET_CURSOR_INFO GetCursorInfoRequest; @@ -579,10 +592,6 @@ typedef struct _CONSOLE_API_MESSAGE CSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest; CSRSS_FLUSH_INPUT_BUFFER FlushInputBufferRequest; CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER ScrollConsoleScreenBufferRequest; - CSRSS_READ_CONSOLE_OUTPUT_CHAR ReadConsoleOutputCharRequest; - CSRSS_READ_CONSOLE_OUTPUT_ATTRIB ReadConsoleOutputAttribRequest; - CSRSS_PEEK_CONSOLE_INPUT PeekConsoleInputRequest; - CSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest; CSRSS_WRITE_CONSOLE_INPUT WriteConsoleInputRequest; CSRSS_GET_INPUT_HANDLE GetInputHandleRequest; CSRSS_GET_OUTPUT_HANDLE GetOutputHandleRequest; @@ -594,12 +603,20 @@ typedef struct _CONSOLE_API_MESSAGE CSRSS_GET_CONSOLE_WINDOW GetConsoleWindowRequest; CSRSS_SET_CONSOLE_ICON SetConsoleIconRequest; + /* Read */ + CSRSS_READ_CONSOLE ReadConsoleRequest; // SrvReadConsole / ReadConsole + CSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest; // SrvGetConsoleInput / PeekConsoleInput & ReadConsoleInput + CSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest; // SrvReadConsoleOutput / ReadConsoleOutput + CSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest; // SrvReadConsoleOutputString / ReadConsoleOutputAttribute & ReadConsoleOutputCharacter + + /* Aliases */ CSRSS_CONSOLE_ALIAS ConsoleAlias; CSRSS_GET_ALL_CONSOLE_ALIASES GetAllConsoleAliases; CSRSS_GET_ALL_CONSOLE_ALIASES_LENGTH GetAllConsoleAliasesLength; CSRSS_GET_CONSOLE_ALIASES_EXES GetConsoleAliasesExes; CSRSS_GET_CONSOLE_ALIASES_EXES_LENGTH GetConsoleAliasesExesLength; + /* History */ CSRSS_GET_COMMAND_HISTORY GetCommandHistory; CSRSS_GET_COMMAND_HISTORY_LENGTH GetCommandHistoryLength; CSRSS_EXPUNGE_COMMAND_HISTORY ExpungeCommandHistory; diff --git a/win32ss/user/consrv/coninput.c b/win32ss/user/consrv/coninput.c index 4c4d5776a93..45fe2f3e9f1 100644 --- a/win32ss/user/consrv/coninput.c +++ b/win32ss/user/consrv/coninput.c @@ -211,16 +211,16 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode) if (NotChar) LastVirtualKey = msg->wParam; - DPRINT ("csrss: %s %s %s %s %02x %02x '%lc' %04x\n", - Down ? "down" : "up ", - (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ? - "char" : "key ", - Fake ? "fake" : "real", - NotChar ? "notc" : "char", - VirtualScanCode, - VirtualKeyCode, - (UnicodeChar >= L' ') ? UnicodeChar : L'.', - ShiftState); + DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n", + Down ? "down" : "up ", + (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ? + "char" : "key ", + Fake ? "fake" : "real", + NotChar ? "notc" : "char", + VirtualScanCode, + VirtualKeyCode, + (UnicodeChar >= L' ') ? UnicodeChar : L'.', + ShiftState); if (Fake) return; @@ -232,13 +232,15 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode) (er.Event.KeyEvent.wVirtualKeyCode == 'C')) && (er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80)) { - PCSR_PROCESS current; + PCONSOLE_PROCESS_DATA current; PLIST_ENTRY current_entry; + DPRINT1("Console_Api Ctrl-C\n"); + current_entry = Console->ProcessList.Flink; while (current_entry != &Console->ProcessList) { - current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink); + current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink); current_entry = current_entry->Flink; ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current); } @@ -293,69 +295,163 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode) CSR_API(SrvGetConsoleInput) { NTSTATUS Status; - PCSRSS_PEEK_CONSOLE_INPUT PeekConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.PeekConsoleInputRequest; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputRequest; + PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCSRSS_CONSOLE Console; + PLIST_ENTRY CurrentInput; + ConsoleInput* Input; + DWORD Length; - PLIST_ENTRY CurrentItem; PINPUT_RECORD InputRecord; - ConsoleInput* Item; - UINT NumItems; DPRINT("SrvGetConsoleInput\n"); - Status = ConioLockConsole(ProcessData, PeekConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ); - if(! NT_SUCCESS(Status)) + Status = ConioLockConsole(ProcessData, GetConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ); + if(!NT_SUCCESS(Status)) return Status; + + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetConsoleInputRequest->InputRecord, + GetConsoleInputRequest->Length, + sizeof(INPUT_RECORD))) { - return Status; + return STATUS_INVALID_PARAMETER; } - InputRecord = PeekConsoleInputRequest->InputRecord; - Length = PeekConsoleInputRequest->Length; + InputRecord = GetConsoleInputRequest->InputRecord; + Length = GetConsoleInputRequest->Length; - if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD))) +/* + if (!Win32CsrValidateBuffer(ProcessData->Process, InputRecord, Length, sizeof(INPUT_RECORD))) { ConioUnlockConsole(Console); return STATUS_ACCESS_VIOLATION; } +*/ - NumItems = 0; - - if (! IsListEmpty(&Console->InputEvents)) + if (GetConsoleInputRequest->bRead) // Read input. { - CurrentItem = Console->InputEvents.Flink; + GetConsoleInputRequest->Event = ProcessData->ConsoleEvent; - while (CurrentItem != &Console->InputEvents && NumItems < Length) + while (Length > 0) { - Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry); + BOOLEAN Done = FALSE; + + // GetConsoleInputRequest->Event = ProcessData->ConsoleEvent; + + /* only get input if there is any */ + CurrentInput = Console->InputEvents.Flink; + while (CurrentInput != &Console->InputEvents) + { + Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry); + CurrentInput = CurrentInput->Flink; + + if (Done) + { + GetConsoleInputRequest->MoreEvents = TRUE; + break; + } + + RemoveEntryList(&Input->ListEntry); - ++NumItems; - *InputRecord = Item->InputEvent; + if (!Done) + { + GetConsoleInputRequest->InputsRead++; + *InputRecord = Input->InputEvent; + /* HACK */ Length--; + + // GetConsoleInputRequest->Input = Input->InputEvent; + if (GetConsoleInputRequest->Unicode == FALSE) + { + // ConioInputEventToAnsi(Console, &GetConsoleInputRequest->Input); + ConioInputEventToAnsi(Console, InputRecord); + } + + InputRecord++; + Done = TRUE; + } + + HeapFree(ConSrvHeap, 0, Input); + } + + if (Done) + Status = STATUS_SUCCESS; + else + Status = STATUS_PENDING; + + if (IsListEmpty(&Console->InputEvents)) + { + ResetEvent(Console->ActiveEvent); + } - if (PeekConsoleInputRequest->Unicode == FALSE) + if (Status == STATUS_PENDING) + { + if (GetConsoleInputRequest->InputsRead == 0) + { + Status = NtWaitForSingleObject(GetConsoleInputRequest->Event, FALSE, 0); + if (!NT_SUCCESS(Status)) + { + // BaseSetLastNTError(Status); + break; + } + } + else + { + /* nothing more to read (waiting for more input??), let's just bail */ + break; + } + } + else // Status != STATUS_PENDING ; == STATUS_SUCCESS { - ConioInputEventToAnsi(Console, InputRecord); + if (!GetConsoleInputRequest->MoreEvents) + { + /* nothing more to read, bail */ + break; + } } + } + } + else // Peek input. + { + UINT NumInputs = 0; + + if (!IsListEmpty(&Console->InputEvents)) + { + CurrentInput = Console->InputEvents.Flink; + + while (CurrentInput != &Console->InputEvents && NumInputs < Length) + { + Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry); + + ++NumInputs; + *InputRecord = Input->InputEvent; - InputRecord++; - CurrentItem = CurrentItem->Flink; + if (GetConsoleInputRequest->Unicode == FALSE) + { + ConioInputEventToAnsi(Console, InputRecord); + } + + InputRecord++; + CurrentInput = CurrentInput->Flink; + } } + + GetConsoleInputRequest->Length = NumInputs; + + Status = STATUS_SUCCESS; } ConioUnlockConsole(Console); - PeekConsoleInputRequest->Length = NumItems; - - return STATUS_SUCCESS; + return Status; } CSR_API(SrvWriteConsoleInput) { + NTSTATUS Status; PCSRSS_WRITE_CONSOLE_INPUT WriteConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleInputRequest; PINPUT_RECORD InputRecord; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCSRSS_CONSOLE Console; - NTSTATUS Status; DWORD Length; DWORD i; @@ -370,7 +466,7 @@ CSR_API(SrvWriteConsoleInput) InputRecord = WriteConsoleInputRequest->InputRecord; Length = WriteConsoleInputRequest->Length; - if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD))) + if (!Win32CsrValidateBuffer(ProcessData->Process, InputRecord, Length, sizeof(INPUT_RECORD))) { ConioUnlockConsole(Console); return STATUS_ACCESS_VIOLATION; @@ -398,6 +494,7 @@ CSR_API(SrvWriteConsoleInput) CSR_API(SrvReadConsole) { + NTSTATUS Status; PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest; PLIST_ENTRY CurrentEntry; ConsoleInput *Input; @@ -405,9 +502,8 @@ CSR_API(SrvReadConsole) PWCHAR UnicodeBuffer; ULONG i = 0; ULONG nNumberOfCharsToRead, CharSize; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCSRSS_CONSOLE Console; - NTSTATUS Status; DPRINT("SrvReadConsole\n"); @@ -415,21 +511,54 @@ CSR_API(SrvReadConsole) nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead; + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&ReadConsoleRequest->Buffer, + ReadConsoleRequest->BufferSize, + sizeof(BYTE))) + { + return STATUS_INVALID_PARAMETER; + } + Buffer = (PCHAR)ReadConsoleRequest->Buffer; UnicodeBuffer = (PWCHAR)Buffer; - if (!Win32CsrValidateBuffer(ProcessData, Buffer, nNumberOfCharsToRead, CharSize)) - return STATUS_ACCESS_VIOLATION; - if (ReadConsoleRequest->NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize) - return STATUS_INVALID_PARAMETER; +/* + if (!Win32CsrValidateBuffer(ProcessData->Process, Buffer, nNumberOfCharsToRead, CharSize)) + return STATUS_ACCESS_VIOLATION; +*/ Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle, &Console, GENERIC_READ); - if (! NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) return Status; + + Status = STATUS_SUCCESS; + ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent; + +/*** HACK: Enclosing do { ... } while (...) loop coming from kernel32 ***/ +do +{ + if (Status == STATUS_PENDING) { - return Status; + Status = NtWaitForSingleObject(ReadConsoleRequest->EventHandle, + FALSE, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Wait for console input failed!\n"); + break; + } } - ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent; +/******/ + + if (ReadConsoleRequest->NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize) + { + // return STATUS_INVALID_PARAMETER; + Status = STATUS_INVALID_PARAMETER; + break; + // goto done; + } + + // ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent; Status = STATUS_PENDING; /* we haven't read anything (yet) */ if (Console->Mode & ENABLE_LINE_INPUT) @@ -531,68 +660,11 @@ CSR_API(SrvReadConsole) } done: ReadConsoleRequest->NrCharactersRead = i; - ConioUnlockConsole(Console); - return Status; +/******/ } - -CSR_API(CsrReadInputEvent) -{ - PCSRSS_READ_INPUT ReadInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadInputRequest; - PLIST_ENTRY CurrentEntry; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; - PCSRSS_CONSOLE Console; - NTSTATUS Status; - BOOLEAN Done = FALSE; - ConsoleInput *Input; - - DPRINT("CsrReadInputEvent\n"); - - ReadInputRequest->Event = ProcessData->ConsoleEvent; - - Status = ConioLockConsole(ProcessData, ReadInputRequest->ConsoleHandle, &Console, GENERIC_READ); - if (! NT_SUCCESS(Status)) - { - return Status; - } - - /* only get input if there is any */ - CurrentEntry = Console->InputEvents.Flink; - while (CurrentEntry != &Console->InputEvents) - { - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - CurrentEntry = CurrentEntry->Flink; - - if (Done) - { - ReadInputRequest->MoreEvents = TRUE; - break; - } - - RemoveEntryList(&Input->ListEntry); - - if (!Done) - { - ReadInputRequest->Input = Input->InputEvent; - if (ReadInputRequest->Unicode == FALSE) - { - ConioInputEventToAnsi(Console, &ReadInputRequest->Input); - } - Done = TRUE; - } - - HeapFree(ConSrvHeap, 0, Input); - } - - if (Done) - Status = STATUS_SUCCESS; - else - Status = STATUS_PENDING; - - if (IsListEmpty(&Console->InputEvents)) - { - ResetEvent(Console->ActiveEvent); - } +while (Status == STATUS_PENDING); +/*** HACK: Enclosing do { ... } while (...) loop coming from kernel32 ***/ ConioUnlockConsole(Console); @@ -601,22 +673,19 @@ CSR_API(CsrReadInputEvent) CSR_API(SrvFlushConsoleInputBuffer) { + NTSTATUS Status; PCSRSS_FLUSH_INPUT_BUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest; PLIST_ENTRY CurrentEntry; PCSRSS_CONSOLE Console; ConsoleInput* Input; - NTSTATUS Status; DPRINT("SrvFlushConsoleInputBuffer\n"); - Status = ConioLockConsole(CsrGetClientThread()->Process, + Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), FlushInputBufferRequest->ConsoleInput, &Console, GENERIC_WRITE); - if(! NT_SUCCESS(Status)) - { - return Status; - } + if(!NT_SUCCESS(Status)) return Status; /* Discard all entries in the input event queue */ while (!IsListEmpty(&Console->InputEvents)) @@ -638,24 +707,21 @@ CSR_API(SrvGetConsoleNumberOfInputEvents) NTSTATUS Status; PCSRSS_GET_NUM_INPUT_EVENTS GetNumInputEventsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumInputEventsRequest; PCSRSS_CONSOLE Console; - PLIST_ENTRY CurrentItem; + PLIST_ENTRY CurrentInput; DWORD NumEvents; DPRINT("SrvGetConsoleNumberOfInputEvents\n"); - Status = ConioLockConsole(CsrGetClientThread()->Process, GetNumInputEventsRequest->ConsoleHandle, &Console, GENERIC_READ); - if (! NT_SUCCESS(Status)) - { - return Status; - } + Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), GetNumInputEventsRequest->ConsoleHandle, &Console, GENERIC_READ); + if (!NT_SUCCESS(Status)) return Status; - CurrentItem = Console->InputEvents.Flink; + CurrentInput = Console->InputEvents.Flink; NumEvents = 0; /* If there are any events ... */ - while (CurrentItem != &Console->InputEvents) + while (CurrentInput != &Console->InputEvents) { - CurrentItem = CurrentItem->Flink; + CurrentInput = CurrentInput->Flink; NumEvents++; } diff --git a/win32ss/user/consrv/conoutput.c b/win32ss/user/consrv/conoutput.c index 2bcee0e0959..ae37fac8563 100644 --- a/win32ss/user/consrv/conoutput.c +++ b/win32ss/user/consrv/conoutput.c @@ -436,7 +436,7 @@ ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale) CSR_API(SrvReadConsoleOutput) { PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputRequest; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCHAR_INFO CharInfo; PCHAR_INFO CurCharInfo; PCSRSS_SCREEN_BUFFER Buff; @@ -453,26 +453,32 @@ CSR_API(SrvReadConsoleOutput) DPRINT("SrvReadConsoleOutput\n"); - Status = ConioLockScreenBuffer(ProcessData, ReadConsoleOutputRequest->ConsoleHandle, &Buff, GENERIC_READ); - if (! NT_SUCCESS(Status)) - { - return Status; - } - CharInfo = ReadConsoleOutputRequest->CharInfo; ReadRegion = ReadConsoleOutputRequest->ReadRegion; BufferSize = ReadConsoleOutputRequest->BufferSize; BufferCoord = ReadConsoleOutputRequest->BufferCoord; - /* FIXME: Is this correct? */ - CodePage = ProcessData->Console->OutputCodePage; - - if (!Win32CsrValidateBuffer(ProcessData, CharInfo, + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&ReadConsoleOutputRequest->CharInfo, + BufferSize.X * BufferSize.Y, + sizeof(CHAR_INFO))) + { + return STATUS_INVALID_PARAMETER; + } +/* + if (!Win32CsrValidateBuffer(ProcessData->Process, CharInfo, BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO))) { ConioUnlockScreenBuffer(Buff); return STATUS_ACCESS_VIOLATION; } +*/ + + Status = ConioLockScreenBuffer(ProcessData, ReadConsoleOutputRequest->ConsoleHandle, &Buff, GENERIC_READ); + if (!NT_SUCCESS(Status)) return Status; + + /* FIXME: Is this correct? */ + CodePage = ProcessData->Console->OutputCodePage; SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion)); SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion)); @@ -480,7 +486,7 @@ CSR_API(SrvReadConsoleOutput) ReadRegion.Right = ReadRegion.Left + SizeX; ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX); - if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion)) + if (!ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion)) { ConioUnlockScreenBuffer(Buff); return STATUS_SUCCESS; @@ -495,6 +501,7 @@ CSR_API(SrvReadConsoleOutput) { if (ReadConsoleOutputRequest->Unicode) { + // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar); MultiByteToWideChar(CodePage, 0, (PCHAR)Ptr++, 1, &CurCharInfo->Char.UnicodeChar, 1); @@ -691,45 +698,82 @@ CSR_API(SrvWriteConsoleOutput) return STATUS_SUCCESS; } -CSR_API(CsrReadConsoleOutputChar) +CSR_API(SrvReadConsoleOutputString) { NTSTATUS Status; - PCSRSS_READ_CONSOLE_OUTPUT_CHAR ReadConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputCharRequest; + PCSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputCodeRequest; PCSRSS_CONSOLE Console; PCSRSS_SCREEN_BUFFER Buff; + USHORT CodeType; DWORD Xpos, Ypos; - PCHAR ReadBuffer; + PVOID ReadBuffer; DWORD i; - ULONG CharSize; - CHAR Char; + ULONG CodeSize; + BYTE Code; - DPRINT("CsrReadConsoleOutputChar\n"); + DPRINT("SrvReadConsoleOutputString\n"); - ReadBuffer = ReadConsoleOutputCharRequest->String; + ReadBuffer = ReadConsoleOutputCodeRequest->pCode.pCode; - CharSize = (ReadConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR)); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ReadConsoleOutputCharRequest->ConsoleHandle, &Buff, GENERIC_READ); - if (! NT_SUCCESS(Status)) + CodeType = ReadConsoleOutputCodeRequest->CodeType; + switch (CodeType) { - return Status; + case CODE_ASCII: + CodeSize = sizeof(CHAR); + break; + + case CODE_UNICODE: + CodeSize = sizeof(WCHAR); + break; + + case CODE_ATTRIBUTE: + CodeSize = sizeof(WORD); + break; + + default: + return STATUS_INVALID_PARAMETER; } - Console = Buff->Header.Console; - Xpos = ReadConsoleOutputCharRequest->ReadCoord.X; - Ypos = (ReadConsoleOutputCharRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; + Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadConsoleOutputCodeRequest->ConsoleHandle, &Buff, GENERIC_READ); + if (!NT_SUCCESS(Status)) return Status; - for (i = 0; i < ReadConsoleOutputCharRequest->NumCharsToRead; ++i) - { - Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)]; + Console = Buff->Header.Console; - if(ReadConsoleOutputCharRequest->Unicode) + Xpos = ReadConsoleOutputCodeRequest->ReadCoord.X; + Ypos = (ReadConsoleOutputCodeRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; + + /* + * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) : + * + * If the number of attributes (resp. characters) to be read from extends + * beyond the end of the specified screen buffer row, attributes (resp. + * characters) are read from the next row. If the number of attributes + * (resp. characters) to be read from extends beyond the end of the console + * screen buffer, attributes (resp. characters) up to the end of the console + * screen buffer are read. + * + * TODO: Do NOT loop up to NumCodesToRead, but stop before + * if we are going to overflow... + */ + for (i = 0; i < ReadConsoleOutputCodeRequest->NumCodesToRead; ++i) + { + Code = Buff->Buffer[2 * (Xpos + Ypos * Buff->MaxX) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)]; + + switch (CodeType) { - ConsoleAnsiCharToUnicodeChar(Console, (WCHAR*)ReadBuffer, &Char); - ReadBuffer += sizeof(WCHAR); + case CODE_UNICODE: + ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)ReadBuffer, (PCHAR)&Code); + break; + + case CODE_ASCII: + *(PCHAR)ReadBuffer = (CHAR)Code; + break; + + case CODE_ATTRIBUTE: + *(PWORD)ReadBuffer = (WORD)Code; + break; } - else - *(ReadBuffer++) = Char; + ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize); Xpos++; @@ -745,78 +789,28 @@ CSR_API(CsrReadConsoleOutputChar) } } - *ReadBuffer = 0; - ReadConsoleOutputCharRequest->EndCoord.X = Xpos; - ReadConsoleOutputCharRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY; - - ConioUnlockScreenBuffer(Buff); - - ReadConsoleOutputCharRequest->CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadConsoleOutputCharRequest->String) / CharSize; - if (ReadConsoleOutputCharRequest->CharsRead * CharSize + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) > sizeof(CSR_API_MESSAGE)) - { - DPRINT1("Length won't fit in message\n"); - return STATUS_BUFFER_TOO_SMALL; - } - - return STATUS_SUCCESS; -} - -CSR_API(CsrReadConsoleOutputAttrib) -{ - NTSTATUS Status; - PCSRSS_READ_CONSOLE_OUTPUT_ATTRIB ReadConsoleOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputAttribRequest; - PCSRSS_SCREEN_BUFFER Buff; - DWORD Xpos, Ypos; - PWORD ReadBuffer; - DWORD i; - DWORD CurrentLength; - - DPRINT("CsrReadConsoleOutputAttrib\n"); - - ReadBuffer = ReadConsoleOutputAttribRequest->Attribute; - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ReadConsoleOutputAttribRequest->ConsoleHandle, &Buff, GENERIC_READ); - if (! NT_SUCCESS(Status)) + switch (CodeType) { - return Status; - } + case CODE_UNICODE: + *(PWCHAR)ReadBuffer = 0; + break; - Xpos = ReadConsoleOutputAttribRequest->ReadCoord.X; - Ypos = (ReadConsoleOutputAttribRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; + case CODE_ASCII: + *(PCHAR)ReadBuffer = 0; + break; - for (i = 0; i < ReadConsoleOutputAttribRequest->NumAttrsToRead; ++i) - { - *ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX) + 1]; - - ReadBuffer++; - Xpos++; - - if (Xpos == Buff->MaxX) - { - Xpos = 0; - Ypos++; - - if (Ypos == Buff->MaxY) - { - Ypos = 0; - } - } + case CODE_ATTRIBUTE: + *(PWORD)ReadBuffer = 0; + break; } - *ReadBuffer = 0; - - ReadConsoleOutputAttribRequest->EndCoord.X = Xpos; - ReadConsoleOutputAttribRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY; + ReadConsoleOutputCodeRequest->EndCoord.X = Xpos; + ReadConsoleOutputCodeRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY; ConioUnlockScreenBuffer(Buff); - CurrentLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB) - + ReadConsoleOutputAttribRequest->NumAttrsToRead * sizeof(WORD); - if (CurrentLength > sizeof(CSR_API_MESSAGE)) - { - DPRINT1("Length won't fit in message\n"); - return STATUS_BUFFER_TOO_SMALL; - } + ReadConsoleOutputCodeRequest->CodesRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadConsoleOutputCodeRequest->pCode.pCode) / CodeSize; + // <= ReadConsoleOutputCodeRequest->NumCodesToRead return STATUS_SUCCESS; }