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); + ReadConsoleRequest->BufferSize, + (PVOID*)&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->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; + GetConsoleInputRequest->ConsoleHandle = hConsoleInput; + GetConsoleInputRequest->Unicode = bUnicode; + GetConsoleInputRequest->bRead = bRead; + if (bRead == TRUE) + { + GetConsoleInputRequest->InputsRead = 0; + } + GetConsoleInputRequest->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); + 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); - /* Check for success*/ - if (NT_SUCCESS(Request.Status)) +/** For Read only ** + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status)) { - /* 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); - } - else - { - /* Error out */ - *lpNumberOfEventsRead = 0; - BaseSetLastNTError(Request.Status); - } - - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); - - /* Return TRUE or FALSE */ - return NT_SUCCESS(Request.Status); -} - - -static -BOOL -IntReadConsoleInput(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead, - BOOL bUnicode) -{ - CSR_API_MESSAGE Request; - ULONG CsrRequest; - ULONG Read; - NTSTATUS Status; - - CsrRequest = CSR_CREATE_API_NUMBER(CSR_CONSOLE, READ_INPUT); - Read = 0; - - while (nLength > 0) - { - 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)) + // BaseSetLastNTError(Status); ???? + if (GetConsoleInputRequest->InputsRead == 0) { - 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) - { - 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; - } + /\* we couldn't read a single record, fail *\/ + BaseSetLastNTError(Status); + return FALSE; } else { - lpBuffer[Read++] = Request.Data.ReadInputRequest.Input; - nLength--; - - if (!Request.Data.ReadInputRequest.MoreEvents) - { - /* nothing more to read, bail */ - break; - } + /\* FIXME - fail gracefully in case we already read at least one record? *\/ + // break; } } +**/ - if (lpNumberOfEventsRead != NULL) + /** + ** TODO: !! Simplify the function !! + **/ + if (bRead == TRUE) // ReadConsoleInput call. { - *lpNumberOfEventsRead = Read; - } + /* 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 (Read > 0); + 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; + + /* Error out */ + BaseSetLastNTError(ApiMessage.Status); + } + + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + return (GetConsoleInputRequest->InputsRead > 0); + } + else // PeekConsoleInput call. + { + /* Check for success */ + if (NT_SUCCESS(Status) || NT_SUCCESS(ApiMessage.Status)) + { + /* 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 + { + if (lpNumberOfEventsRead != NULL) + *lpNumberOfEventsRead = 0; + + /* Error out */ + BaseSetLastNTError(ApiMessage.Status); + } + + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* 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)); - - nLength = min(nLength, CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR / CharSize); - SizeBytes = nLength * CharSize; - - Request = RtlAllocateHeap(RtlGetProcessHeap(), 0, - max(sizeof(CSR_API_MESSAGE), - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) + SizeBytes)); - if (Request == NULL) + /* Determine the needed size */ + switch (CodeType) { + case CODE_ASCII: + CodeSize = sizeof(CHAR); + break; + + case CODE_UNICODE: + CodeSize = sizeof(WCHAR); + break; + + 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) + /* Start reading */ + ReadConsoleOutputCodeRequest->ConsoleHandle = hConsoleOutput; + ReadConsoleOutputCodeRequest->CodeType = CodeType; + ReadConsoleOutputCodeRequest->ReadCoord = dwReadCoord; + + // while (nLength > 0) { - DWORD BytesRead; + ReadConsoleOutputCodeRequest->NumCodesToRead = nLength; + // SizeBytes = ReadConsoleOutputCodeRequest->NumCodesToRead * CodeSize; - Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput; - Request->Data.ReadConsoleOutputCharRequest.Unicode = bUnicode; - Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead = nLength; - SizeBytes = Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead * CharSize; - - 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; - ++NumItems; - *InputRecord = Item->InputEvent; + // GetConsoleInputRequest->Event = ProcessData->ConsoleEvent; - if (PeekConsoleInputRequest->Unicode == FALSE) + /* only get input if there is any */ + CurrentInput = Console->InputEvents.Flink; + while (CurrentInput != &Console->InputEvents) { - ConioInputEventToAnsi(Console, InputRecord); + Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry); + CurrentInput = CurrentInput->Flink; + + if (Done) + { + GetConsoleInputRequest->MoreEvents = TRUE; + break; + } + + RemoveEntryList(&Input->ListEntry); + + 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); } - InputRecord++; - CurrentItem = CurrentItem->Flink; + if (Done) + Status = STATUS_SUCCESS; + else + Status = STATUS_PENDING; + + if (IsListEmpty(&Console->InputEvents)) + { + ResetEvent(Console->ActiveEvent); + } + + 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 + { + 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; + + 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,22 +511,55 @@ 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)) - { - return 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) + { + Status = NtWaitForSingleObject(ReadConsoleRequest->EventHandle, + FALSE, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Wait for console input failed!\n"); + break; + } + } +/******/ + + 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; } + + Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadConsoleOutputCodeRequest->ConsoleHandle, &Buff, GENERIC_READ); + if (!NT_SUCCESS(Status)) return Status; + Console = Buff->Header.Console; - Xpos = ReadConsoleOutputCharRequest->ReadCoord.X; - Ypos = (ReadConsoleOutputCharRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; + Xpos = ReadConsoleOutputCodeRequest->ReadCoord.X; + Ypos = (ReadConsoleOutputCodeRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; - for (i = 0; i < ReadConsoleOutputCharRequest->NumCharsToRead; ++i) + /* + * 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) { - Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)]; + Code = Buff->Buffer[2 * (Xpos + Ypos * Buff->MaxX) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)]; - if(ReadConsoleOutputCharRequest->Unicode) + 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; + switch (CodeType) + { + case CODE_UNICODE: + *(PWCHAR)ReadBuffer = 0; + break; + + case CODE_ASCII: + *(PCHAR)ReadBuffer = 0; + break; + + case CODE_ATTRIBUTE: + *(PWORD)ReadBuffer = 0; + break; + } + + ReadConsoleOutputCodeRequest->EndCoord.X = Xpos; + ReadConsoleOutputCodeRequest->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)) - { - return Status; - } - - Xpos = ReadConsoleOutputAttribRequest->ReadCoord.X; - Ypos = (ReadConsoleOutputAttribRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; - - 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; - } - } - } - - *ReadBuffer = 0; - - ReadConsoleOutputAttribRequest->EndCoord.X = Xpos; - ReadConsoleOutputAttribRequest->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; }