From 49c384301b458a1eb330fb7d8f263ed58df1c607 Mon Sep 17 00:00:00 2001 From: Marty Dill Date: Tue, 12 Nov 2002 00:48:26 +0000 Subject: [PATCH] Implemented ReadConsoleOutputA() and WriteConsoleInputA(). svn path=/trunk/; revision=3746 --- reactos/include/csrss/csrss.h | 32 +++++- reactos/lib/kernel32/misc/console.c | 113 ++++++++++++++++++-- reactos/subsys/csrss/api.h | 2 + reactos/subsys/csrss/api/conio.c | 157 +++++++++++++++++++++++++++- reactos/subsys/csrss/api/wapi.c | 4 +- 5 files changed, 299 insertions(+), 9 deletions(-) diff --git a/reactos/include/csrss/csrss.h b/reactos/include/csrss/csrss.h index 4b1115a10eb..d13ece70ccf 100644 --- a/reactos/include/csrss/csrss.h +++ b/reactos/include/csrss/csrss.h @@ -311,6 +311,31 @@ typedef struct DWORD Length; } CSRSS_PEEK_CONSOLE_INPUT_REPLY, *PCSRSS_PEEK_CONSOLE_INPUT_REPLY; +typedef struct +{ + HANDLE ConsoleHandle; + COORD BufferSize; + COORD BufferCoord; + SMALL_RECT ReadRegion; + CHAR_INFO* CharInfo; +} CSRSS_READ_CONSOLE_OUTPUT_REQUEST, *PCSRSS_READ_CONSOLE_OUTPUT_REQUEST; + +typedef struct +{ + SMALL_RECT ReadRegion; +} CSRSS_READ_CONSOLE_OUTPUT_REPLY, *PCSRSS_READ_CONSOLE_OUTPUT_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + DWORD Length; + INPUT_RECORD* InputRecord; +} CSRSS_WRITE_CONSOLE_INPUT_REQUEST, *PCSRSS_WRITE_CONSOLE_INPUT_REQUEST; + +typedef struct +{ + DWORD Length; +} CSRSS_WRITE_CONSOLE_INPUT_REPLY, *PCSRSS_WRITE_CONSOLE_INPUT_REPLY; #define CSRSS_MAX_WRITE_CONSOLE_REQUEST \ (MAX_MESSAGE_DATA - sizeof(ULONG) - sizeof(CSRSS_WRITE_CONSOLE_REQUEST)) @@ -364,7 +389,8 @@ typedef struct #define CSRSS_GET_SHUTDOWN_PARAMETERS (0x1F) #define CSRSS_SET_SHUTDOWN_PARAMETERS (0x20) #define CSRSS_PEEK_CONSOLE_INPUT (0x21) - +#define CSRSS_READ_CONSOLE_OUTPUT (0x22) +#define CSRSS_WRITE_CONSOLE_INPUT (0x23) /* Keep in sync with definition below. */ #define CSRSS_REQUEST_HEADER_SIZE (sizeof(LPC_MESSAGE) + sizeof(ULONG)) @@ -406,6 +432,8 @@ typedef struct CSRSS_EXIT_REACTOS_REQUEST ExitReactosRequest; CSRSS_SHUTDOWN_PARAMETERS SetShutdownParametersRequest; CSRSS_PEEK_CONSOLE_INPUT_REQUEST PeekConsoleInputRequest; + CSRSS_READ_CONSOLE_OUTPUT_REQUEST ReadConsoleOutputRequest; + CSRSS_WRITE_CONSOLE_INPUT_REQUEST WriteConsoleInputRequest; } Data; } CSRSS_API_REQUEST, *PCSRSS_API_REQUEST; @@ -434,6 +462,8 @@ typedef struct CSRSS_GET_NUM_INPUT_EVENTS_REPLY GetNumInputEventsReply; CSRSS_SHUTDOWN_PARAMETERS GetShutdownParametersReply; CSRSS_PEEK_CONSOLE_INPUT_REPLY PeekConsoleInputReply; + CSRSS_READ_CONSOLE_OUTPUT_REPLY ReadConsoleOutputReply; + CSRSS_WRITE_CONSOLE_INPUT_REPLY WriteConsoleInputReply; } Data; } CSRSS_API_REPLY, *PCSRSS_API_REPLY; diff --git a/reactos/lib/kernel32/misc/console.c b/reactos/lib/kernel32/misc/console.c index c75707f742e..dc6e226ebfe 100644 --- a/reactos/lib/kernel32/misc/console.c +++ b/reactos/lib/kernel32/misc/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.47 2002/11/03 20:01:05 chorns Exp $ +/* $Id: console.c,v 1.48 2002/11/12 00:48:25 mdill Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -937,7 +937,7 @@ PeekConsoleInputA( LPDWORD lpNumberOfEventsRead ) { - PCSRSS_API_REQUEST Request; + PCSRSS_API_REQUEST Request; CSRSS_API_REPLY Reply; NTSTATUS Status; PVOID BufferBase; @@ -1118,8 +1118,55 @@ WriteConsoleInputA( LPDWORD lpNumberOfEventsWritten ) { -/* TO DO */ - return FALSE; + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + PVOID BufferBase, BufferTargetBase; + NTSTATUS Status; + DWORD Size; + + if(lpBuffer == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Size = nLength * sizeof(INPUT_RECORD); + + Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST)); + if(Request == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + CsrReleaseParameterBuffer(BufferBase); + return FALSE; + } + + Request->Type = CSRSS_WRITE_CONSOLE_INPUT; + Request->Data.WriteConsoleInputRequest.ConsoleHandle = hConsoleInput; + Request->Data.WriteConsoleInputRequest.Length = nLength; + Request->Data.WriteConsoleInputRequest.InputRecord = (PINPUT_RECORD)BufferTargetBase; + + Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY)); + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrReleaseParameterBuffer(BufferBase); + return FALSE; + } + + if(lpNumberOfEventsWritten != NULL) + lpNumberOfEventsWritten = Reply.Data.WriteConsoleInputReply.Length; + + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrReleaseParameterBuffer(BufferBase); + + return TRUE; } @@ -1155,8 +1202,62 @@ ReadConsoleOutputA( PSMALL_RECT lpReadRegion ) { -/* TO DO */ - return FALSE; + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + PVOID BufferBase; + PVOID BufferTargetBase; + NTSTATUS Status; + DWORD Size, SizeX, SizeY; + + if(lpBuffer == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO); + + Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST)); + if(Request == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + CsrReleaseParameterBuffer(BufferBase); + return FALSE; + } + + Request->Type = CSRSS_READ_CONSOLE_OUTPUT; + Request->Data.ReadConsoleOutputRequest.ConsoleHandle = hConsoleOutput; + Request->Data.ReadConsoleOutputRequest.BufferSize = dwBufferSize; + Request->Data.ReadConsoleOutputRequest.BufferCoord = dwBufferCoord; + Request->Data.ReadConsoleOutputRequest.ReadRegion = *lpReadRegion; + Request->Data.ReadConsoleOutputRequest.CharInfo = (PCHAR_INFO)BufferTargetBase; + + Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY)); + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + SetLastErrorByStatus(Status); + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrReleaseParameterBuffer(BufferBase); + return FALSE; + } + + SizeX = Reply.Data.ReadConsoleOutputReply.ReadRegion.Right - Reply.Data.ReadConsoleOutputReply.ReadRegion.Left + 1; + SizeY = Reply.Data.ReadConsoleOutputReply.ReadRegion.Bottom - Reply.Data.ReadConsoleOutputReply.ReadRegion.Top + 1; + + memcpy(lpBuffer, BufferBase, sizeof(CHAR_INFO) * SizeX * SizeY); + *lpReadRegion = Reply.Data.ReadConsoleOutputReply.ReadRegion; + + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrReleaseParameterBuffer(BufferBase); + + return TRUE; } diff --git a/reactos/subsys/csrss/api.h b/reactos/subsys/csrss/api.h index e70bc96eb2b..b4c45fc6aa8 100644 --- a/reactos/subsys/csrss/api.h +++ b/reactos/subsys/csrss/api.h @@ -129,6 +129,8 @@ CSR_API(CsrExitReactos); CSR_API(CsrGetShutdownParameters); CSR_API(CsrSetShutdownParameters); CSR_API(CsrPeekConsoleInput); +CSR_API(CsrReadConsoleOutput); +CSR_API(CsrWriteConsoleInput); /* print.c */ VOID STDCALL DisplayString(LPCWSTR lpwString); diff --git a/reactos/subsys/csrss/api/conio.c b/reactos/subsys/csrss/api/conio.c index 7e73b565a4f..421cb631084 100644 --- a/reactos/subsys/csrss/api/conio.c +++ b/reactos/subsys/csrss/api/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.37 2002/11/03 20:01:07 chorns Exp $ +/* $Id: conio.c,v 1.38 2002/11/12 00:48:26 mdill Exp $ * * reactos/subsys/csrss/api/conio.c * @@ -1764,6 +1764,8 @@ CSR_API(CsrWriteConsoleOutput) UNLOCK; Reply->Data.WriteConsoleOutputReply.WriteRegion.Right = WriteRegion.Left + SizeX - 1; Reply->Data.WriteConsoleOutputReply.WriteRegion.Bottom = WriteRegion.Top + SizeY - 1; + Reply->Data.WriteConsoleOutputReply.WriteRegion.Left = WriteRegion.Left; + Reply->Data.WriteConsoleOutputReply.WriteRegion.Top = WriteRegion.Top; return (Reply->Status = STATUS_SUCCESS); } @@ -2147,4 +2149,157 @@ CSR_API(CsrPeekConsoleInput) return Reply->Status; } + +CSR_API(CsrReadConsoleOutput) +{ + PCHAR_INFO CharInfo; + PCHAR_INFO CurCharInfo; + PCSRSS_SCREEN_BUFFER ScreenBuffer; + DWORD Size; + DWORD Length; + DWORD SizeX, SizeY; + NTSTATUS Status; + COORD BufferSize; + COORD BufferCoord; + SMALL_RECT ReadRegion; + SMALL_RECT ScreenRect; + DWORD i, Y, X, Offset; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + + LOCK; + + Status = CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, (Object_t**)&ScreenBuffer); + if(!NT_SUCCESS(Status)) + { + Reply->Status = Status; + UNLOCK; + return Reply->Status; + } + + if(ScreenBuffer->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC) + { + Reply->Status = STATUS_INVALID_HANDLE; + UNLOCK; + return Reply->Status; + } + + CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo; + ReadRegion = Request->Data.ReadConsoleOutputRequest.ReadRegion; + BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize; + BufferCoord = Request->Data.ReadConsoleOutputRequest.BufferCoord; + Length = BufferSize.X * BufferSize.Y; + Size = Length * sizeof(INPUT_RECORD); + + if(((PVOID)CharInfo < ProcessData->CsrSectionViewBase) + || (((PVOID)CharInfo + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) + { + UNLOCK; + Reply->Status = STATUS_ACCESS_VIOLATION; + return Reply->Status ; + } + + SizeY = RtlMin(BufferSize.Y - BufferCoord.Y, CsrpRectHeight(ReadRegion)); + SizeX = RtlMin(BufferSize.X - BufferCoord.X, CsrpRectWidth(ReadRegion)); + ReadRegion.Bottom = ReadRegion.Top + SizeY; + ReadRegion.Right = ReadRegion.Left + SizeX; + + CsrpInitRect(ScreenRect, 0, 0, ScreenBuffer->MaxY - 1, ScreenBuffer->MaxX - 1); + if (!CsrpGetIntersection(&ReadRegion, ScreenRect, ReadRegion)) + { + UNLOCK; + Reply->Status = STATUS_SUCCESS; + return Reply->Status; + } + + for(i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y) + { + CurCharInfo = CharInfo + (i * BufferSize.Y); + + Offset = (Y * ScreenBuffer->MaxX + ReadRegion.Left) * 2; + for(X = ReadRegion.Left; X < ReadRegion.Right; ++X) + { + CurCharInfo->Char.AsciiChar = GET_CELL_BUFFER(ScreenBuffer, Offset); + CurCharInfo->Attributes = GET_CELL_BUFFER(ScreenBuffer, Offset); + ++CurCharInfo; + } + } + + UNLOCK; + + Reply->Status = STATUS_SUCCESS; + Reply->Data.ReadConsoleOutputReply.ReadRegion.Right = ReadRegion.Left + SizeX - 1; + Reply->Data.ReadConsoleOutputReply.ReadRegion.Bottom = ReadRegion.Top + SizeY - 1; + Reply->Data.ReadConsoleOutputReply.ReadRegion.Left = ReadRegion.Left; + Reply->Data.ReadConsoleOutputReply.ReadRegion.Top = ReadRegion.Top; + + return Reply->Status; +} + + +CSR_API(CsrWriteConsoleInput) +{ + PINPUT_RECORD InputRecord; + PCSRSS_CONSOLE Console; + NTSTATUS Status; + DWORD Length; + DWORD Size; + DWORD i; + PLIST_ENTRY NextItem; + ConsoleInput* Record; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + + LOCK; + + Status = CsrGetObject(ProcessData, Request->Data.WriteConsoleInputRequest.ConsoleHandle, (Object_t**)&Console); + if(!NT_SUCCESS(Status)) + { + Reply->Status = Status; + UNLOCK; + return Reply->Status; + } + + if(Console->Header.Type != CSRSS_CONSOLE_MAGIC) + { + Reply->Status = STATUS_INVALID_HANDLE; + UNLOCK; + return Reply->Status; + } + + InputRecord = Request->Data.WriteConsoleInputRequest.InputRecord; + Length = Request->Data.WriteConsoleInputRequest.Length; + Size = Length * sizeof(INPUT_RECORD); + + if(((PVOID)InputRecord < ProcessData->CsrSectionViewBase) + || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) + { + UNLOCK; + Reply->Status = STATUS_ACCESS_VIOLATION; + return Reply->Status ; + } + + for(i = 0; i < Length; ++i) + { + Record = RtlAllocateHeap(CsrssApiHeap, 0, sizeof(ConsoleInput)); + if(Record == NULL) + { + UNLOCK; + Reply->Status = STATUS_INSUFFICIENT_RESOURCES; + return Reply->Status; + } + + Record->InputEvent = *InputRecord++; + InsertTailList(&Console->InputEvents, &Record->ListEntry); + } + + UNLOCK; + + Reply->Status = STATUS_SUCCESS; + Reply->Data.WriteConsoleInputReply.Length = i; + return Reply->Status; +} + /* EOF */ diff --git a/reactos/subsys/csrss/api/wapi.c b/reactos/subsys/csrss/api/wapi.c index 24845d49306..f32dae9ec0f 100644 --- a/reactos/subsys/csrss/api/wapi.c +++ b/reactos/subsys/csrss/api/wapi.c @@ -1,4 +1,4 @@ -/* $Id: wapi.c,v 1.24 2002/10/31 01:50:00 ekohl Exp $ +/* $Id: wapi.c,v 1.25 2002/11/12 00:48:26 mdill Exp $ * * reactos/subsys/csrss/api/wapi.c * @@ -61,6 +61,8 @@ static const CsrFunc CsrFuncs[] = { CsrGetShutdownParameters, CsrSetShutdownParameters, CsrPeekConsoleInput, + CsrReadConsoleOutput, + CsrWriteConsoleInput, 0 }; static void Thread_Api2(HANDLE ServerPort)