From ecb660bb7d228224acde4003c03604d98a41ce8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 17 Nov 2012 15:41:31 +0000 Subject: [PATCH] [CONSRV] Code reorganization only, no code changes. svn path=/branches/ros-csrss/; revision=57717 --- win32ss/user/consrv/coninput.c | 501 +++++----- win32ss/user/consrv/conoutput.c | 1575 ++++++++++++++++--------------- 2 files changed, 1045 insertions(+), 1031 deletions(-) diff --git a/win32ss/user/consrv/coninput.c b/win32ss/user/consrv/coninput.c index cf55ff02b21..4c4d5776a93 100644 --- a/win32ss/user/consrv/coninput.c +++ b/win32ss/user/consrv/coninput.c @@ -6,7 +6,7 @@ * PROGRAMMERS: */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/ #include "consrv.h" #include "conio.h" @@ -15,7 +15,8 @@ #define NDEBUG #include -/* GLOBALS *******************************************************************/ + +/* GLOBALS ********************************************************************/ #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \ WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) @@ -23,147 +24,8 @@ #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \ MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1) -/* FUNCTIONS *****************************************************************/ -CSR_API(SrvReadConsole) -{ - PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest; - PLIST_ENTRY CurrentEntry; - ConsoleInput *Input; - PCHAR Buffer; - PWCHAR UnicodeBuffer; - ULONG i = 0; - ULONG nNumberOfCharsToRead, CharSize; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; - PCSRSS_CONSOLE Console; - NTSTATUS Status; - - DPRINT("SrvReadConsole\n"); - - CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR)); - - nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead; - - 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; - - Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle, - &Console, GENERIC_READ); - if (! NT_SUCCESS(Status)) - { - return Status; - } - ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent; - - Status = STATUS_PENDING; /* we haven't read anything (yet) */ - if (Console->Mode & ENABLE_LINE_INPUT) - { - if (Console->LineBuffer == NULL) - { - /* Starting a new line */ - Console->LineMaxSize = max(256, nNumberOfCharsToRead); - Console->LineBuffer = HeapAlloc(ConSrvHeap, 0, Console->LineMaxSize * sizeof(WCHAR)); - if (Console->LineBuffer == NULL) - { - Status = STATUS_NO_MEMORY; - goto done; - } - Console->LineComplete = FALSE; - Console->LineUpPressed = FALSE; - Console->LineInsertToggle = 0; - Console->LineWakeupMask = ReadConsoleRequest->CtrlWakeupMask; - Console->LineSize = ReadConsoleRequest->NrCharactersRead; - Console->LinePos = Console->LineSize; - /* pre-filling the buffer is only allowed in the Unicode API, - * so we don't need to worry about conversion */ - memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR)); - if (Console->LineSize == Console->LineMaxSize) - { - Console->LineComplete = TRUE; - Console->LinePos = 0; - } - } - - /* If we don't have a complete line yet, process the pending input */ - while (!Console->LineComplete && !IsListEmpty(&Console->InputEvents)) - { - /* remove input event from queue */ - CurrentEntry = RemoveHeadList(&Console->InputEvents); - if (IsListEmpty(&Console->InputEvents)) - { - ResetEvent(Console->ActiveEvent); - } - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - - /* only pay attention to key down */ - if (KEY_EVENT == Input->InputEvent.EventType - && Input->InputEvent.Event.KeyEvent.bKeyDown) - { - LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent); - ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; - } - HeapFree(ConSrvHeap, 0, Input); - } - - /* Check if we have a complete line to read from */ - if (Console->LineComplete) - { - while (i < nNumberOfCharsToRead && Console->LinePos != Console->LineSize) - { - WCHAR Char = Console->LineBuffer[Console->LinePos++]; - if (ReadConsoleRequest->Unicode) - UnicodeBuffer[i++] = Char; - else - ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char); - } - if (Console->LinePos == Console->LineSize) - { - /* Entire line has been read */ - HeapFree(ConSrvHeap, 0, Console->LineBuffer); - Console->LineBuffer = NULL; - } - Status = STATUS_SUCCESS; - } - } - else - { - /* Character input */ - while (i < nNumberOfCharsToRead && !IsListEmpty(&Console->InputEvents)) - { - /* remove input event from queue */ - CurrentEntry = RemoveHeadList(&Console->InputEvents); - if (IsListEmpty(&Console->InputEvents)) - { - ResetEvent(Console->ActiveEvent); - } - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - - /* only pay attention to valid ascii chars, on key down */ - if (KEY_EVENT == Input->InputEvent.EventType - && Input->InputEvent.Event.KeyEvent.bKeyDown - && Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0') - { - WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar; - if (ReadConsoleRequest->Unicode) - UnicodeBuffer[i++] = Char; - else - ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char); - Status = STATUS_SUCCESS; /* did read something */ - } - HeapFree(ConSrvHeap, 0, Input); - } - } -done: - ReadConsoleRequest->NrCharactersRead = i; - ConioUnlockConsole(Console); - - return Status; -} +/* PRIVATE FUNCTIONS **********************************************************/ static VOID FASTCALL ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent) @@ -425,6 +287,255 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode) ConioProcessChar(Console, &er); } + +/* PUBLIC APIS ****************************************************************/ + +CSR_API(SrvGetConsoleInput) +{ + NTSTATUS Status; + PCSRSS_PEEK_CONSOLE_INPUT PeekConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.PeekConsoleInputRequest; + PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCSRSS_CONSOLE Console; + 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)) + { + return Status; + } + + InputRecord = PeekConsoleInputRequest->InputRecord; + Length = PeekConsoleInputRequest->Length; + + if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD))) + { + ConioUnlockConsole(Console); + return STATUS_ACCESS_VIOLATION; + } + + NumItems = 0; + + if (! IsListEmpty(&Console->InputEvents)) + { + CurrentItem = Console->InputEvents.Flink; + + while (CurrentItem != &Console->InputEvents && NumItems < Length) + { + Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry); + + ++NumItems; + *InputRecord = Item->InputEvent; + + if (PeekConsoleInputRequest->Unicode == FALSE) + { + ConioInputEventToAnsi(Console, InputRecord); + } + + InputRecord++; + CurrentItem = CurrentItem->Flink; + } + } + + ConioUnlockConsole(Console); + + PeekConsoleInputRequest->Length = NumItems; + + return STATUS_SUCCESS; +} + +CSR_API(SrvWriteConsoleInput) +{ + PCSRSS_WRITE_CONSOLE_INPUT WriteConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleInputRequest; + PINPUT_RECORD InputRecord; + PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCSRSS_CONSOLE Console; + NTSTATUS Status; + DWORD Length; + DWORD i; + + DPRINT("SrvWriteConsoleInput\n"); + + Status = ConioLockConsole(ProcessData, WriteConsoleInputRequest->ConsoleHandle, &Console, GENERIC_WRITE); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + InputRecord = WriteConsoleInputRequest->InputRecord; + Length = WriteConsoleInputRequest->Length; + + if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD))) + { + ConioUnlockConsole(Console); + return STATUS_ACCESS_VIOLATION; + } + + for (i = 0; i < Length && NT_SUCCESS(Status); i++) + { + if (!WriteConsoleInputRequest->Unicode && + InputRecord->EventType == KEY_EVENT) + { + CHAR AsciiChar = InputRecord->Event.KeyEvent.uChar.AsciiChar; + ConsoleInputAnsiCharToUnicodeChar(Console, + &InputRecord->Event.KeyEvent.uChar.UnicodeChar, + &AsciiChar); + } + Status = ConioProcessChar(Console, InputRecord++); + } + + ConioUnlockConsole(Console); + + WriteConsoleInputRequest->Length = i; + + return Status; +} + +CSR_API(SrvReadConsole) +{ + PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest; + PLIST_ENTRY CurrentEntry; + ConsoleInput *Input; + PCHAR Buffer; + PWCHAR UnicodeBuffer; + ULONG i = 0; + ULONG nNumberOfCharsToRead, CharSize; + PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCSRSS_CONSOLE Console; + NTSTATUS Status; + + DPRINT("SrvReadConsole\n"); + + CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR)); + + nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead; + + 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; + + Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle, + &Console, GENERIC_READ); + if (! NT_SUCCESS(Status)) + { + return Status; + } + ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent; + + Status = STATUS_PENDING; /* we haven't read anything (yet) */ + if (Console->Mode & ENABLE_LINE_INPUT) + { + if (Console->LineBuffer == NULL) + { + /* Starting a new line */ + Console->LineMaxSize = max(256, nNumberOfCharsToRead); + Console->LineBuffer = HeapAlloc(ConSrvHeap, 0, Console->LineMaxSize * sizeof(WCHAR)); + if (Console->LineBuffer == NULL) + { + Status = STATUS_NO_MEMORY; + goto done; + } + Console->LineComplete = FALSE; + Console->LineUpPressed = FALSE; + Console->LineInsertToggle = 0; + Console->LineWakeupMask = ReadConsoleRequest->CtrlWakeupMask; + Console->LineSize = ReadConsoleRequest->NrCharactersRead; + Console->LinePos = Console->LineSize; + /* pre-filling the buffer is only allowed in the Unicode API, + * so we don't need to worry about conversion */ + memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR)); + if (Console->LineSize == Console->LineMaxSize) + { + Console->LineComplete = TRUE; + Console->LinePos = 0; + } + } + + /* If we don't have a complete line yet, process the pending input */ + while (!Console->LineComplete && !IsListEmpty(&Console->InputEvents)) + { + /* remove input event from queue */ + CurrentEntry = RemoveHeadList(&Console->InputEvents); + if (IsListEmpty(&Console->InputEvents)) + { + ResetEvent(Console->ActiveEvent); + } + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + + /* only pay attention to key down */ + if (KEY_EVENT == Input->InputEvent.EventType + && Input->InputEvent.Event.KeyEvent.bKeyDown) + { + LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent); + ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; + } + HeapFree(ConSrvHeap, 0, Input); + } + + /* Check if we have a complete line to read from */ + if (Console->LineComplete) + { + while (i < nNumberOfCharsToRead && Console->LinePos != Console->LineSize) + { + WCHAR Char = Console->LineBuffer[Console->LinePos++]; + if (ReadConsoleRequest->Unicode) + UnicodeBuffer[i++] = Char; + else + ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char); + } + if (Console->LinePos == Console->LineSize) + { + /* Entire line has been read */ + HeapFree(ConSrvHeap, 0, Console->LineBuffer); + Console->LineBuffer = NULL; + } + Status = STATUS_SUCCESS; + } + } + else + { + /* Character input */ + while (i < nNumberOfCharsToRead && !IsListEmpty(&Console->InputEvents)) + { + /* remove input event from queue */ + CurrentEntry = RemoveHeadList(&Console->InputEvents); + if (IsListEmpty(&Console->InputEvents)) + { + ResetEvent(Console->ActiveEvent); + } + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + + /* only pay attention to valid ascii chars, on key down */ + if (KEY_EVENT == Input->InputEvent.EventType + && Input->InputEvent.Event.KeyEvent.bKeyDown + && Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0') + { + WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar; + if (ReadConsoleRequest->Unicode) + UnicodeBuffer[i++] = Char; + else + ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char); + Status = STATUS_SUCCESS; /* did read something */ + } + HeapFree(ConSrvHeap, 0, Input); + } + } +done: + ReadConsoleRequest->NrCharactersRead = i; + ConioUnlockConsole(Console); + + return Status; +} + CSR_API(CsrReadInputEvent) { PCSRSS_READ_INPUT ReadInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadInputRequest; @@ -555,110 +666,4 @@ CSR_API(SrvGetConsoleNumberOfInputEvents) return STATUS_SUCCESS; } -CSR_API(SrvGetConsoleInput) -{ - NTSTATUS Status; - PCSRSS_PEEK_CONSOLE_INPUT PeekConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.PeekConsoleInputRequest; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; - PCSRSS_CONSOLE Console; - 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)) - { - return Status; - } - - InputRecord = PeekConsoleInputRequest->InputRecord; - Length = PeekConsoleInputRequest->Length; - - if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD))) - { - ConioUnlockConsole(Console); - return STATUS_ACCESS_VIOLATION; - } - - NumItems = 0; - - if (! IsListEmpty(&Console->InputEvents)) - { - CurrentItem = Console->InputEvents.Flink; - - while (CurrentItem != &Console->InputEvents && NumItems < Length) - { - Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry); - - ++NumItems; - *InputRecord = Item->InputEvent; - - if (PeekConsoleInputRequest->Unicode == FALSE) - { - ConioInputEventToAnsi(Console, InputRecord); - } - - InputRecord++; - CurrentItem = CurrentItem->Flink; - } - } - - ConioUnlockConsole(Console); - - PeekConsoleInputRequest->Length = NumItems; - - return STATUS_SUCCESS; -} - -CSR_API(SrvWriteConsoleInput) -{ - PCSRSS_WRITE_CONSOLE_INPUT WriteConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleInputRequest; - PINPUT_RECORD InputRecord; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; - PCSRSS_CONSOLE Console; - NTSTATUS Status; - DWORD Length; - DWORD i; - - DPRINT("SrvWriteConsoleInput\n"); - - Status = ConioLockConsole(ProcessData, WriteConsoleInputRequest->ConsoleHandle, &Console, GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - - InputRecord = WriteConsoleInputRequest->InputRecord; - Length = WriteConsoleInputRequest->Length; - - if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD))) - { - ConioUnlockConsole(Console); - return STATUS_ACCESS_VIOLATION; - } - - for (i = 0; i < Length && NT_SUCCESS(Status); i++) - { - if (!WriteConsoleInputRequest->Unicode && - InputRecord->EventType == KEY_EVENT) - { - CHAR AsciiChar = InputRecord->Event.KeyEvent.uChar.AsciiChar; - ConsoleInputAnsiCharToUnicodeChar(Console, - &InputRecord->Event.KeyEvent.uChar.UnicodeChar, - &AsciiChar); - } - Status = ConioProcessChar(Console, InputRecord++); - } - - ConioUnlockConsole(Console); - - WriteConsoleInputRequest->Length = i; - - return Status; -} - /* EOF */ diff --git a/win32ss/user/consrv/conoutput.c b/win32ss/user/consrv/conoutput.c index 9f860e45907..2bcee0e0959 100644 --- a/win32ss/user/consrv/conoutput.c +++ b/win32ss/user/consrv/conoutput.c @@ -6,7 +6,7 @@ * PROGRAMMERS: */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/ #include "consrv.h" #include "conio.h" @@ -14,13 +14,16 @@ #define NDEBUG #include -/* GLOBALS *******************************************************************/ + +/* GLOBALS ********************************************************************/ #define ConioInitRect(Rect, top, left, bottom, right) \ - ((Rect)->Top) = top; \ - ((Rect)->Left) = left; \ - ((Rect)->Bottom) = bottom; \ - ((Rect)->Right) = right +do { \ + ((Rect)->Top) = top; \ + ((Rect)->Left) = left; \ + ((Rect)->Bottom) = bottom; \ + ((Rect)->Right) = right; \ +} while(0) #define ConioIsRectEmpty(Rect) \ (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom)) @@ -31,7 +34,8 @@ #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \ MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1) -/* FUNCTIONS *****************************************************************/ + +/* PRIVATE FUNCTIONS **********************************************************/ PBYTE FASTCALL ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff, ULONG X, ULONG Y) @@ -294,8 +298,10 @@ __inline BOOLEAN ConioGetUnion( return TRUE; } -/* Move from one rectangle to another. We must be careful about the order that - * this is done, to avoid overwriting parts of the source before they are moved. */ +/* + * Move from one rectangle to another. We must be careful about the order that + * this is done, to avoid overwriting parts of the source before they are moved. + */ static VOID FASTCALL ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer, SMALL_RECT *SrcRegion, @@ -356,6 +362,162 @@ ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer, } } +VOID WINAPI +ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer) +{ + PCSRSS_CONSOLE Console = Buffer->Header.Console; + + RemoveEntryList(&Buffer->ListEntry); + if (Buffer == Console->ActiveBuffer) + { + /* Deleted active buffer; switch to most recently created */ + Console->ActiveBuffer = NULL; + if (!IsListEmpty(&Console->BufferList)) + { + Console->ActiveBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CSRSS_SCREEN_BUFFER, ListEntry); + ConioDrawConsole(Console); + } + } + + HeapFree(ConSrvHeap, 0, Buffer->Buffer); + HeapFree(ConSrvHeap, 0, Buffer); +} + +VOID FASTCALL +ConioDrawConsole(PCSRSS_CONSOLE Console) +{ + SMALL_RECT Region; + + ConioInitRect(&Region, 0, 0, Console->Size.Y - 1, Console->Size.X - 1); + + ConioDrawRegion(Console, &Region); +} + +static VOID FASTCALL +ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, COORD *Start, UINT Length) +{ + if (Buff->MaxX <= Start->X + Length) + { + UpdateRect->Left = 0; + } + else + { + UpdateRect->Left = Start->X; + } + if (Buff->MaxX <= Start->X + Length) + { + UpdateRect->Right = Buff->MaxX - 1; + } + else + { + UpdateRect->Right = Start->X + Length - 1; + } + UpdateRect->Top = Start->Y; + UpdateRect->Bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX; + if (Buff->MaxY <= UpdateRect->Bottom) + { + UpdateRect->Bottom = Buff->MaxY - 1; + } +} + +DWORD FASTCALL +ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale) +{ + DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100; + /* If line input in progress, perhaps adjust for insert toggle */ + if (Console->LineBuffer && !Console->LineComplete && Console->LineInsertToggle) + return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2); + return Size; +} + + +/* PUBLIC APIS ****************************************************************/ + +CSR_API(SrvReadConsoleOutput) +{ + PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputRequest; + PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCHAR_INFO CharInfo; + PCHAR_INFO CurCharInfo; + PCSRSS_SCREEN_BUFFER Buff; + DWORD SizeX, SizeY; + NTSTATUS Status; + COORD BufferSize; + COORD BufferCoord; + SMALL_RECT ReadRegion; + SMALL_RECT ScreenRect; + DWORD i; + PBYTE Ptr; + LONG X, Y; + UINT CodePage; + + 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, + BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO))) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_ACCESS_VIOLATION; + } + + SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion)); + SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion)); + ReadRegion.Bottom = ReadRegion.Top + SizeY; + ReadRegion.Right = ReadRegion.Left + SizeX; + + ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX); + if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion)) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_SUCCESS; + } + + for (i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y) + { + CurCharInfo = CharInfo + (i * BufferSize.X); + + Ptr = ConioCoordToPointer(Buff, ReadRegion.Left, Y); + for (X = ReadRegion.Left; X < ReadRegion.Right; ++X) + { + if (ReadConsoleOutputRequest->Unicode) + { + MultiByteToWideChar(CodePage, 0, + (PCHAR)Ptr++, 1, + &CurCharInfo->Char.UnicodeChar, 1); + } + else + { + CurCharInfo->Char.AsciiChar = *Ptr++; + } + CurCharInfo->Attributes = *Ptr++; + ++CurCharInfo; + } + } + + ConioUnlockScreenBuffer(Buff); + + ReadConsoleOutputRequest->ReadRegion.Right = ReadRegion.Left + SizeX - 1; + ReadConsoleOutputRequest->ReadRegion.Bottom = ReadRegion.Top + SizeY - 1; + ReadConsoleOutputRequest->ReadRegion.Left = ReadRegion.Left; + ReadConsoleOutputRequest->ReadRegion.Top = ReadRegion.Top; + + return STATUS_SUCCESS; +} + CSR_API(SrvWriteConsole) { NTSTATUS Status; @@ -441,625 +603,6 @@ CSR_API(SrvWriteConsole) return Status; } -VOID WINAPI -ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer) -{ - PCSRSS_CONSOLE Console = Buffer->Header.Console; - - RemoveEntryList(&Buffer->ListEntry); - if (Buffer == Console->ActiveBuffer) - { - /* Deleted active buffer; switch to most recently created */ - Console->ActiveBuffer = NULL; - if (!IsListEmpty(&Console->BufferList)) - { - Console->ActiveBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CSRSS_SCREEN_BUFFER, ListEntry); - ConioDrawConsole(Console); - } - } - - HeapFree(ConSrvHeap, 0, Buffer->Buffer); - HeapFree(ConSrvHeap, 0, Buffer); -} - -VOID FASTCALL -ConioDrawConsole(PCSRSS_CONSOLE Console) -{ - SMALL_RECT Region; - - ConioInitRect(&Region, 0, 0, Console->Size.Y - 1, Console->Size.X - 1); - - ConioDrawRegion(Console, &Region); -} - -CSR_API(SrvGetConsoleScreenBufferInfo) // CsrGetScreenBufferInfo -{ - NTSTATUS Status; - PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - PCONSOLE_SCREEN_BUFFER_INFO pInfo; - - DPRINT("SrvGetConsoleScreenBufferInfo\n"); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ScreenBufferInfoRequest->ConsoleHandle, &Buff, GENERIC_READ); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - pInfo = &ScreenBufferInfoRequest->Info; - pInfo->dwSize.X = Buff->MaxX; - pInfo->dwSize.Y = Buff->MaxY; - pInfo->dwCursorPosition.X = Buff->CurrentX; - pInfo->dwCursorPosition.Y = Buff->CurrentY; - pInfo->wAttributes = Buff->DefaultAttrib; - pInfo->srWindow.Left = Buff->ShowX; - pInfo->srWindow.Right = Buff->ShowX + Console->Size.X - 1; - pInfo->srWindow.Top = Buff->ShowY; - pInfo->srWindow.Bottom = Buff->ShowY + Console->Size.Y - 1; - pInfo->dwMaximumWindowSize.X = Buff->MaxX; - pInfo->dwMaximumWindowSize.Y = Buff->MaxY; - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - -CSR_API(SrvSetConsoleCursor) -{ - NTSTATUS Status; - PCSRSS_SET_CURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - LONG OldCursorX, OldCursorY; - LONG NewCursorX, NewCursorY; - - DPRINT("SrvSetConsoleCursor\n"); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetCursorRequest->ConsoleHandle, &Buff, GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - - NewCursorX = SetCursorRequest->Position.X; - NewCursorY = SetCursorRequest->Position.Y; - if (NewCursorX < 0 || NewCursorX >= Buff->MaxX || - NewCursorY < 0 || NewCursorY >= Buff->MaxY) - { - ConioUnlockScreenBuffer(Buff); - return STATUS_INVALID_PARAMETER; - } - OldCursorX = Buff->CurrentX; - OldCursorY = Buff->CurrentY; - Buff->CurrentX = NewCursorX; - Buff->CurrentY = NewCursorY; - if (Buff == Console->ActiveBuffer) - { - if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY)) - { - ConioUnlockScreenBuffer(Buff); - return STATUS_UNSUCCESSFUL; - } - } - - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - -static VOID FASTCALL -ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, COORD *Start, UINT Length) -{ - if (Buff->MaxX <= Start->X + Length) - { - UpdateRect->Left = 0; - } - else - { - UpdateRect->Left = Start->X; - } - if (Buff->MaxX <= Start->X + Length) - { - UpdateRect->Right = Buff->MaxX - 1; - } - else - { - UpdateRect->Right = Start->X + Length - 1; - } - UpdateRect->Top = Start->Y; - UpdateRect->Bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX; - if (Buff->MaxY <= UpdateRect->Bottom) - { - UpdateRect->Bottom = Buff->MaxY - 1; - } -} - -CSR_API(CsrWriteConsoleOutputChar) -{ - NTSTATUS Status; - PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputCharRequest; - PCHAR String, tmpString = NULL; - PBYTE Buffer; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - DWORD X, Y, Length, CharSize, Written = 0; - SMALL_RECT UpdateRect; - - DPRINT("CsrWriteConsoleOutputChar\n"); - - CharSize = (WriteConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR)); - - if (ApiMessage->Header.u1.s1.TotalLength - < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR) - + (WriteConsoleOutputCharRequest->Length * CharSize)) - { - DPRINT1("Invalid ApiMessage size\n"); - return STATUS_INVALID_PARAMETER; - } - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, - WriteConsoleOutputCharRequest->ConsoleHandle, - &Buff, - GENERIC_WRITE); - if (NT_SUCCESS(Status)) - { - Console = Buff->Header.Console; - if(WriteConsoleOutputCharRequest->Unicode) - { - Length = WideCharToMultiByte(Console->OutputCodePage, 0, - (PWCHAR)WriteConsoleOutputCharRequest->String, - WriteConsoleOutputCharRequest->Length, - NULL, 0, NULL, NULL); - tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length); - if (String) - { - WideCharToMultiByte(Console->OutputCodePage, 0, - (PWCHAR)WriteConsoleOutputCharRequest->String, - WriteConsoleOutputCharRequest->Length, - String, Length, NULL, NULL); - } - else - { - Status = STATUS_NO_MEMORY; - } - } - else - { - String = (PCHAR)WriteConsoleOutputCharRequest->String; - } - - if (String) - { - if (NT_SUCCESS(Status)) - { - X = WriteConsoleOutputCharRequest->Coord.X; - Y = (WriteConsoleOutputCharRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY; - Length = WriteConsoleOutputCharRequest->Length; - Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; - while (Length--) - { - *Buffer = *String++; - Written++; - Buffer += 2; - if (++X == Buff->MaxX) - { - if (++Y == Buff->MaxY) - { - Y = 0; - Buffer = Buff->Buffer; - } - X = 0; - } - } - if (Buff == Console->ActiveBuffer) - { - ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputCharRequest->Coord, - WriteConsoleOutputCharRequest->Length); - ConioDrawRegion(Console, &UpdateRect); - } - - WriteConsoleOutputCharRequest->EndCoord.X = X; - WriteConsoleOutputCharRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY; - - } - if (WriteConsoleOutputCharRequest->Unicode) - { - RtlFreeHeap(GetProcessHeap(), 0, tmpString); - } - } - ConioUnlockScreenBuffer(Buff); - } - WriteConsoleOutputCharRequest->NrCharactersWritten = Written; - return Status; -} - -CSR_API(CsrFillOutputChar) -{ - NTSTATUS Status; - PCSRSS_FILL_OUTPUT FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - DWORD X, Y, Length, Written = 0; - CHAR Char; - PBYTE Buffer; - SMALL_RECT UpdateRect; - - DPRINT("CsrFillOutputChar\n"); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, FillOutputRequest->ConsoleHandle, &Buff, GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - - X = FillOutputRequest->Position.X; - Y = (FillOutputRequest->Position.Y + Buff->VirtualY) % Buff->MaxY; - Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; - if(FillOutputRequest->Unicode) - ConsoleUnicodeCharToAnsiChar(Console, &Char, &FillOutputRequest->Char.UnicodeChar); - else - Char = FillOutputRequest->Char.AsciiChar; - Length = FillOutputRequest->Length; - while (Length--) - { - *Buffer = Char; - Buffer += 2; - Written++; - if (++X == Buff->MaxX) - { - if (++Y == Buff->MaxY) - { - Y = 0; - Buffer = Buff->Buffer; - } - X = 0; - } - } - - if (Buff == Console->ActiveBuffer) - { - ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputRequest->Position, - FillOutputRequest->Length); - ConioDrawRegion(Console, &UpdateRect); - } - - ConioUnlockScreenBuffer(Buff); - Length = FillOutputRequest->Length; - FillOutputRequest->NrCharactersWritten = Length; - return STATUS_SUCCESS; -} - -CSR_API(CsrWriteConsoleOutputAttrib) -{ - PCSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB WriteConsoleOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputAttribRequest; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - PUCHAR Buffer; - PWORD Attribute; - int X, Y, Length; - NTSTATUS Status; - SMALL_RECT UpdateRect; - - DPRINT("CsrWriteConsoleOutputAttrib\n"); - - if (ApiMessage->Header.u1.s1.TotalLength - < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB) - + WriteConsoleOutputAttribRequest->Length * sizeof(WORD)) - { - DPRINT1("Invalid ApiMessage size\n"); - return STATUS_INVALID_PARAMETER; - } - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, - WriteConsoleOutputAttribRequest->ConsoleHandle, - &Buff, - GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - - X = WriteConsoleOutputAttribRequest->Coord.X; - Y = (WriteConsoleOutputAttribRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY; - Length = WriteConsoleOutputAttribRequest->Length; - Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1]; - Attribute = WriteConsoleOutputAttribRequest->Attribute; - while (Length--) - { - *Buffer = (UCHAR)(*Attribute++); - Buffer += 2; - if (++X == Buff->MaxX) - { - if (++Y == Buff->MaxY) - { - Y = 0; - Buffer = Buff->Buffer + 1; - } - X = 0; - } - } - - if (Buff == Console->ActiveBuffer) - { - ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputAttribRequest->Coord, - WriteConsoleOutputAttribRequest->Length); - ConioDrawRegion(Console, &UpdateRect); - } - - WriteConsoleOutputAttribRequest->EndCoord.X = X; - WriteConsoleOutputAttribRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY; - - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - -CSR_API(CsrFillOutputAttrib) -{ - PCSRSS_FILL_OUTPUT_ATTRIB FillOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputAttribRequest; - PCSRSS_SCREEN_BUFFER Buff; - PUCHAR Buffer; - NTSTATUS Status; - int X, Y, Length; - UCHAR Attr; - SMALL_RECT UpdateRect; - PCSRSS_CONSOLE Console; - - DPRINT("CsrFillOutputAttrib\n"); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, FillOutputAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - - X = FillOutputAttribRequest->Coord.X; - Y = (FillOutputAttribRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY; - Length = FillOutputAttribRequest->Length; - Attr = FillOutputAttribRequest->Attribute; - Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1]; - while (Length--) - { - *Buffer = Attr; - Buffer += 2; - if (++X == Buff->MaxX) - { - if (++Y == Buff->MaxY) - { - Y = 0; - Buffer = Buff->Buffer + 1; - } - X = 0; - } - } - - if (Buff == Console->ActiveBuffer) - { - ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputAttribRequest->Coord, - FillOutputAttribRequest->Length); - ConioDrawRegion(Console, &UpdateRect); - } - - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - -DWORD FASTCALL -ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale) -{ - DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100; - /* If line input in progress, perhaps adjust for insert toggle */ - if (Console->LineBuffer && !Console->LineComplete && Console->LineInsertToggle) - return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2); - return Size; -} - -CSR_API(SrvGetConsoleCursorInfo) -{ - NTSTATUS Status; - PCSRSS_GET_CURSOR_INFO GetCursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCursorInfoRequest; - PCSRSS_SCREEN_BUFFER Buff; - - DPRINT("SrvGetConsoleCursorInfo\n"); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, GetCursorInfoRequest->ConsoleHandle, &Buff, GENERIC_READ); - if (! NT_SUCCESS(Status)) - { - return Status; - } - GetCursorInfoRequest->Info.bVisible = Buff->CursorInfo.bVisible; - GetCursorInfoRequest->Info.dwSize = Buff->CursorInfo.dwSize; - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - -CSR_API(SrvSetConsoleCursorInfo) -{ - PCSRSS_SET_CURSOR_INFO SetCursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorInfoRequest; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - DWORD Size; - BOOL Visible; - NTSTATUS Status; - - DPRINT("SrvSetConsoleCursorInfo\n"); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetCursorInfoRequest->ConsoleHandle, &Buff, GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - - Size = SetCursorInfoRequest->Info.dwSize; - Visible = SetCursorInfoRequest->Info.bVisible; - if (Size < 1) - { - Size = 1; - } - if (100 < Size) - { - Size = 100; - } - - if (Size != Buff->CursorInfo.dwSize - || (Visible && ! Buff->CursorInfo.bVisible) || (! Visible && Buff->CursorInfo.bVisible)) - { - Buff->CursorInfo.dwSize = Size; - Buff->CursorInfo.bVisible = Visible; - - if (! ConioSetCursorInfo(Console, Buff)) - { - ConioUnlockScreenBuffer(Buff); - return STATUS_UNSUCCESSFUL; - } - } - - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - -CSR_API(CsrSetTextAttrib) -{ - NTSTATUS Status; - PCSRSS_SET_ATTRIB SetAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetAttribRequest; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - - DPRINT("CsrSetTextAttrib\n"); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - - Buff->DefaultAttrib = SetAttribRequest->Attrib; - if (Buff == Console->ActiveBuffer) - { - if (! ConioUpdateScreenInfo(Console, Buff)) - { - ConioUnlockScreenBuffer(Buff); - return STATUS_UNSUCCESSFUL; - } - } - - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - -CSR_API(SrvCreateConsoleScreenBuffer) -{ - PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - NTSTATUS Status; - - DPRINT("SrvCreateConsoleScreenBuffer\n"); - - RtlEnterCriticalSection(&ProcessData->HandleTableLock); - Status = ConioConsoleFromProcessData(ProcessData, &Console); - if (! NT_SUCCESS(Status)) - { - return Status; - } - - Buff = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER)); - - if (Buff != NULL) - { - if (Console->ActiveBuffer) - { - Buff->MaxX = Console->ActiveBuffer->MaxX; - Buff->MaxY = Console->ActiveBuffer->MaxY; - Buff->CursorInfo.bVisible = Console->ActiveBuffer->CursorInfo.bVisible; - Buff->CursorInfo.dwSize = Console->ActiveBuffer->CursorInfo.dwSize; - } - else - { - Buff->CursorInfo.bVisible = TRUE; - Buff->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE; - } - - if (Buff->MaxX == 0) - { - Buff->MaxX = 80; - } - - if (Buff->MaxY == 0) - { - Buff->MaxY = 25; - } - - Status = CsrInitConsoleScreenBuffer(Console, Buff); - if (NT_SUCCESS(Status)) - { - Status = Win32CsrInsertObject(ProcessData, - &CreateScreenBufferRequest->OutputHandle, - &Buff->Header, - CreateScreenBufferRequest->Access, - CreateScreenBufferRequest->Inheritable, - CreateScreenBufferRequest->ShareMode); - } - } - else - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - - ConioUnlockConsole(Console); - RtlLeaveCriticalSection(&ProcessData->HandleTableLock); - return Status; -} - -CSR_API(SrvSetConsoleActiveScreenBuffer) -{ - NTSTATUS Status; - PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - - DPRINT("SrvSetConsoleActiveScreenBuffer\n"); - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetScreenBufferRequest->OutputHandle, &Buff, GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - - if (Buff == Console->ActiveBuffer) - { - ConioUnlockScreenBuffer(Buff); - return STATUS_SUCCESS; - } - - /* If old buffer has no handles, it's now unreferenced */ - if (Console->ActiveBuffer->Header.HandleCount == 0) - { - ConioDeleteScreenBuffer(Console->ActiveBuffer); - } - /* tie console to new buffer */ - Console->ActiveBuffer = Buff; - /* Redraw the console */ - ConioDrawConsole(Console); - - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - CSR_API(SrvWriteConsoleOutput) { PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputRequest; @@ -1148,100 +691,6 @@ CSR_API(SrvWriteConsoleOutput) return STATUS_SUCCESS; } -CSR_API(SrvScrollConsoleScreenBuffer) -{ - PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER ScrollConsoleScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScrollConsoleScreenBufferRequest; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; - SMALL_RECT ScreenBuffer; - SMALL_RECT SrcRegion; - SMALL_RECT DstRegion; - SMALL_RECT UpdateRegion; - SMALL_RECT ScrollRectangle; - SMALL_RECT ClipRectangle; - NTSTATUS Status; - HANDLE ConsoleHandle; - BOOLEAN UseClipRectangle; - COORD DestinationOrigin; - CHAR_INFO Fill; - CHAR FillChar; - - DPRINT("SrvScrollConsoleScreenBuffer\n"); - - ConsoleHandle = ScrollConsoleScreenBufferRequest->ConsoleHandle; - UseClipRectangle = ScrollConsoleScreenBufferRequest->UseClipRectangle; - DestinationOrigin = ScrollConsoleScreenBufferRequest->DestinationOrigin; - Fill = ScrollConsoleScreenBufferRequest->Fill; - - Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ConsoleHandle, &Buff, GENERIC_WRITE); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Console = Buff->Header.Console; - - ScrollRectangle = ScrollConsoleScreenBufferRequest->ScrollRectangle; - - /* Make sure source rectangle is inside the screen buffer */ - ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); - if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle)) - { - ConioUnlockScreenBuffer(Buff); - return STATUS_SUCCESS; - } - - /* If the source was clipped on the left or top, adjust the destination accordingly */ - if (ScrollRectangle.Left < 0) - { - DestinationOrigin.X -= ScrollRectangle.Left; - } - if (ScrollRectangle.Top < 0) - { - DestinationOrigin.Y -= ScrollRectangle.Top; - } - - if (UseClipRectangle) - { - ClipRectangle = ScrollConsoleScreenBufferRequest->ClipRectangle; - if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer)) - { - ConioUnlockScreenBuffer(Buff); - return STATUS_SUCCESS; - } - } - else - { - ClipRectangle = ScreenBuffer; - } - - ConioInitRect(&DstRegion, - DestinationOrigin.Y, - DestinationOrigin.X, - DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1, - DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1); - - if (ScrollConsoleScreenBufferRequest->Unicode) - ConsoleUnicodeCharToAnsiChar(Console, &FillChar, &Fill.Char.UnicodeChar); - else - FillChar = Fill.Char.AsciiChar; - - ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, Fill.Attributes << 8 | (BYTE)FillChar); - - if (Buff == Console->ActiveBuffer) - { - ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion); - if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &ClipRectangle)) - { - /* Draw update region */ - ConioDrawRegion(Console, &UpdateRegion); - } - } - - ConioUnlockScreenBuffer(Buff); - - return STATUS_SUCCESS; -} - CSR_API(CsrReadConsoleOutputChar) { NTSTATUS Status; @@ -1372,87 +821,647 @@ CSR_API(CsrReadConsoleOutputAttrib) return STATUS_SUCCESS; } -CSR_API(SrvReadConsoleOutput) +CSR_API(CsrWriteConsoleOutputChar) { - PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputRequest; - PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; - PCHAR_INFO CharInfo; - PCHAR_INFO CurCharInfo; - PCSRSS_SCREEN_BUFFER Buff; - DWORD SizeX, SizeY; NTSTATUS Status; - COORD BufferSize; - COORD BufferCoord; - SMALL_RECT ReadRegion; - SMALL_RECT ScreenRect; - DWORD i; - PBYTE Ptr; - LONG X, Y; - UINT CodePage; + PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputCharRequest; + PCHAR String, tmpString = NULL; + PBYTE Buffer; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + DWORD X, Y, Length, CharSize, Written = 0; + SMALL_RECT UpdateRect; - DPRINT("SrvReadConsoleOutput\n"); + DPRINT("CsrWriteConsoleOutputChar\n"); - Status = ConioLockScreenBuffer(ProcessData, ReadConsoleOutputRequest->ConsoleHandle, &Buff, GENERIC_READ); + CharSize = (WriteConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR)); + + if (ApiMessage->Header.u1.s1.TotalLength + < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR) + + (WriteConsoleOutputCharRequest->Length * CharSize)) + { + DPRINT1("Invalid ApiMessage size\n"); + return STATUS_INVALID_PARAMETER; + } + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, + WriteConsoleOutputCharRequest->ConsoleHandle, + &Buff, + GENERIC_WRITE); + if (NT_SUCCESS(Status)) + { + Console = Buff->Header.Console; + if(WriteConsoleOutputCharRequest->Unicode) + { + Length = WideCharToMultiByte(Console->OutputCodePage, 0, + (PWCHAR)WriteConsoleOutputCharRequest->String, + WriteConsoleOutputCharRequest->Length, + NULL, 0, NULL, NULL); + tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length); + if (String) + { + WideCharToMultiByte(Console->OutputCodePage, 0, + (PWCHAR)WriteConsoleOutputCharRequest->String, + WriteConsoleOutputCharRequest->Length, + String, Length, NULL, NULL); + } + else + { + Status = STATUS_NO_MEMORY; + } + } + else + { + String = (PCHAR)WriteConsoleOutputCharRequest->String; + } + + if (String) + { + if (NT_SUCCESS(Status)) + { + X = WriteConsoleOutputCharRequest->Coord.X; + Y = (WriteConsoleOutputCharRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY; + Length = WriteConsoleOutputCharRequest->Length; + Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; + while (Length--) + { + *Buffer = *String++; + Written++; + Buffer += 2; + if (++X == Buff->MaxX) + { + if (++Y == Buff->MaxY) + { + Y = 0; + Buffer = Buff->Buffer; + } + X = 0; + } + } + if (Buff == Console->ActiveBuffer) + { + ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputCharRequest->Coord, + WriteConsoleOutputCharRequest->Length); + ConioDrawRegion(Console, &UpdateRect); + } + + WriteConsoleOutputCharRequest->EndCoord.X = X; + WriteConsoleOutputCharRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY; + + } + if (WriteConsoleOutputCharRequest->Unicode) + { + RtlFreeHeap(GetProcessHeap(), 0, tmpString); + } + } + ConioUnlockScreenBuffer(Buff); + } + WriteConsoleOutputCharRequest->NrCharactersWritten = Written; + return Status; +} + +CSR_API(CsrWriteConsoleOutputAttrib) +{ + PCSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB WriteConsoleOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputAttribRequest; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + PUCHAR Buffer; + PWORD Attribute; + int X, Y, Length; + NTSTATUS Status; + SMALL_RECT UpdateRect; + + DPRINT("CsrWriteConsoleOutputAttrib\n"); + + if (ApiMessage->Header.u1.s1.TotalLength + < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB) + + WriteConsoleOutputAttribRequest->Length * sizeof(WORD)) + { + DPRINT1("Invalid ApiMessage size\n"); + return STATUS_INVALID_PARAMETER; + } + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, + WriteConsoleOutputAttribRequest->ConsoleHandle, + &Buff, + GENERIC_WRITE); if (! NT_SUCCESS(Status)) { return Status; } + Console = Buff->Header.Console; - CharInfo = ReadConsoleOutputRequest->CharInfo; - ReadRegion = ReadConsoleOutputRequest->ReadRegion; - BufferSize = ReadConsoleOutputRequest->BufferSize; - BufferCoord = ReadConsoleOutputRequest->BufferCoord; - - /* FIXME: Is this correct? */ - CodePage = ProcessData->Console->OutputCodePage; - - if (!Win32CsrValidateBuffer(ProcessData, CharInfo, - BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO))) + X = WriteConsoleOutputAttribRequest->Coord.X; + Y = (WriteConsoleOutputAttribRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY; + Length = WriteConsoleOutputAttribRequest->Length; + Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1]; + Attribute = WriteConsoleOutputAttribRequest->Attribute; + while (Length--) { - ConioUnlockScreenBuffer(Buff); - return STATUS_ACCESS_VIOLATION; - } - - SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion)); - SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion)); - ReadRegion.Bottom = ReadRegion.Top + SizeY; - ReadRegion.Right = ReadRegion.Left + SizeX; - - ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX); - if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion)) - { - ConioUnlockScreenBuffer(Buff); - return STATUS_SUCCESS; - } - - for (i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y) - { - CurCharInfo = CharInfo + (i * BufferSize.X); - - Ptr = ConioCoordToPointer(Buff, ReadRegion.Left, Y); - for (X = ReadRegion.Left; X < ReadRegion.Right; ++X) + *Buffer = (UCHAR)(*Attribute++); + Buffer += 2; + if (++X == Buff->MaxX) { - if (ReadConsoleOutputRequest->Unicode) + if (++Y == Buff->MaxY) { - MultiByteToWideChar(CodePage, 0, - (PCHAR)Ptr++, 1, - &CurCharInfo->Char.UnicodeChar, 1); + Y = 0; + Buffer = Buff->Buffer + 1; } - else + X = 0; + } + } + + if (Buff == Console->ActiveBuffer) + { + ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputAttribRequest->Coord, + WriteConsoleOutputAttribRequest->Length); + ConioDrawRegion(Console, &UpdateRect); + } + + WriteConsoleOutputAttribRequest->EndCoord.X = X; + WriteConsoleOutputAttribRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY; + + ConioUnlockScreenBuffer(Buff); + + return STATUS_SUCCESS; +} + +CSR_API(CsrFillOutputChar) +{ + NTSTATUS Status; + PCSRSS_FILL_OUTPUT FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + DWORD X, Y, Length, Written = 0; + CHAR Char; + PBYTE Buffer; + SMALL_RECT UpdateRect; + + DPRINT("CsrFillOutputChar\n"); + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, FillOutputRequest->ConsoleHandle, &Buff, GENERIC_WRITE); + if (! NT_SUCCESS(Status)) + { + return Status; + } + Console = Buff->Header.Console; + + X = FillOutputRequest->Position.X; + Y = (FillOutputRequest->Position.Y + Buff->VirtualY) % Buff->MaxY; + Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; + if(FillOutputRequest->Unicode) + ConsoleUnicodeCharToAnsiChar(Console, &Char, &FillOutputRequest->Char.UnicodeChar); + else + Char = FillOutputRequest->Char.AsciiChar; + Length = FillOutputRequest->Length; + while (Length--) + { + *Buffer = Char; + Buffer += 2; + Written++; + if (++X == Buff->MaxX) + { + if (++Y == Buff->MaxY) { - CurCharInfo->Char.AsciiChar = *Ptr++; + Y = 0; + Buffer = Buff->Buffer; } - CurCharInfo->Attributes = *Ptr++; - ++CurCharInfo; + X = 0; + } + } + + if (Buff == Console->ActiveBuffer) + { + ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputRequest->Position, + FillOutputRequest->Length); + ConioDrawRegion(Console, &UpdateRect); + } + + ConioUnlockScreenBuffer(Buff); + Length = FillOutputRequest->Length; + FillOutputRequest->NrCharactersWritten = Length; + return STATUS_SUCCESS; +} + +CSR_API(CsrFillOutputAttrib) +{ + PCSRSS_FILL_OUTPUT_ATTRIB FillOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputAttribRequest; + PCSRSS_SCREEN_BUFFER Buff; + PUCHAR Buffer; + NTSTATUS Status; + int X, Y, Length; + UCHAR Attr; + SMALL_RECT UpdateRect; + PCSRSS_CONSOLE Console; + + DPRINT("CsrFillOutputAttrib\n"); + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, FillOutputAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE); + if (! NT_SUCCESS(Status)) + { + return Status; + } + Console = Buff->Header.Console; + + X = FillOutputAttribRequest->Coord.X; + Y = (FillOutputAttribRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY; + Length = FillOutputAttribRequest->Length; + Attr = FillOutputAttribRequest->Attribute; + Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1]; + while (Length--) + { + *Buffer = Attr; + Buffer += 2; + if (++X == Buff->MaxX) + { + if (++Y == Buff->MaxY) + { + Y = 0; + Buffer = Buff->Buffer + 1; + } + X = 0; + } + } + + if (Buff == Console->ActiveBuffer) + { + ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputAttribRequest->Coord, + FillOutputAttribRequest->Length); + ConioDrawRegion(Console, &UpdateRect); + } + + ConioUnlockScreenBuffer(Buff); + + return STATUS_SUCCESS; +} + +CSR_API(SrvGetConsoleCursorInfo) +{ + NTSTATUS Status; + PCSRSS_GET_CURSOR_INFO GetCursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCursorInfoRequest; + PCSRSS_SCREEN_BUFFER Buff; + + DPRINT("SrvGetConsoleCursorInfo\n"); + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, GetCursorInfoRequest->ConsoleHandle, &Buff, GENERIC_READ); + if (! NT_SUCCESS(Status)) + { + return Status; + } + GetCursorInfoRequest->Info.bVisible = Buff->CursorInfo.bVisible; + GetCursorInfoRequest->Info.dwSize = Buff->CursorInfo.dwSize; + ConioUnlockScreenBuffer(Buff); + + return STATUS_SUCCESS; +} + +CSR_API(SrvSetConsoleCursorInfo) +{ + PCSRSS_SET_CURSOR_INFO SetCursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorInfoRequest; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + DWORD Size; + BOOL Visible; + NTSTATUS Status; + + DPRINT("SrvSetConsoleCursorInfo\n"); + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetCursorInfoRequest->ConsoleHandle, &Buff, GENERIC_WRITE); + if (! NT_SUCCESS(Status)) + { + return Status; + } + Console = Buff->Header.Console; + + Size = SetCursorInfoRequest->Info.dwSize; + Visible = SetCursorInfoRequest->Info.bVisible; + if (Size < 1) + { + Size = 1; + } + if (100 < Size) + { + Size = 100; + } + + if (Size != Buff->CursorInfo.dwSize + || (Visible && ! Buff->CursorInfo.bVisible) || (! Visible && Buff->CursorInfo.bVisible)) + { + Buff->CursorInfo.dwSize = Size; + Buff->CursorInfo.bVisible = Visible; + + if (! ConioSetCursorInfo(Console, Buff)) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_UNSUCCESSFUL; } } ConioUnlockScreenBuffer(Buff); - ReadConsoleOutputRequest->ReadRegion.Right = ReadRegion.Left + SizeX - 1; - ReadConsoleOutputRequest->ReadRegion.Bottom = ReadRegion.Top + SizeY - 1; - ReadConsoleOutputRequest->ReadRegion.Left = ReadRegion.Left; - ReadConsoleOutputRequest->ReadRegion.Top = ReadRegion.Top; + return STATUS_SUCCESS; +} + +CSR_API(SrvSetConsoleCursorPosition) +{ + NTSTATUS Status; + PCSRSS_SET_CURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + LONG OldCursorX, OldCursorY; + LONG NewCursorX, NewCursorY; + + DPRINT("SrvSetConsoleCursorPosition\n"); + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetCursorRequest->ConsoleHandle, &Buff, GENERIC_WRITE); + if (! NT_SUCCESS(Status)) + { + return Status; + } + Console = Buff->Header.Console; + + NewCursorX = SetCursorRequest->Position.X; + NewCursorY = SetCursorRequest->Position.Y; + if (NewCursorX < 0 || NewCursorX >= Buff->MaxX || + NewCursorY < 0 || NewCursorY >= Buff->MaxY) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_INVALID_PARAMETER; + } + OldCursorX = Buff->CurrentX; + OldCursorY = Buff->CurrentY; + Buff->CurrentX = NewCursorX; + Buff->CurrentY = NewCursorY; + if (Buff == Console->ActiveBuffer) + { + if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY)) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_UNSUCCESSFUL; + } + } + + ConioUnlockScreenBuffer(Buff); + + return STATUS_SUCCESS; +} + +CSR_API(CsrSetTextAttrib) +{ + NTSTATUS Status; + PCSRSS_SET_ATTRIB SetAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetAttribRequest; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + + DPRINT("CsrSetTextAttrib\n"); + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE); + if (! NT_SUCCESS(Status)) + { + return Status; + } + Console = Buff->Header.Console; + + Buff->DefaultAttrib = SetAttribRequest->Attrib; + if (Buff == Console->ActiveBuffer) + { + if (! ConioUpdateScreenInfo(Console, Buff)) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_UNSUCCESSFUL; + } + } + + ConioUnlockScreenBuffer(Buff); + + return STATUS_SUCCESS; +} + +CSR_API(SrvCreateConsoleScreenBuffer) +{ + PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest; + PCSR_PROCESS ProcessData = CsrGetClientThread()->Process; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; + + DPRINT("SrvCreateConsoleScreenBuffer\n"); + + RtlEnterCriticalSection(&ProcessData->HandleTableLock); + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + Buff = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER)); + + if (Buff != NULL) + { + if (Console->ActiveBuffer) + { + Buff->MaxX = Console->ActiveBuffer->MaxX; + Buff->MaxY = Console->ActiveBuffer->MaxY; + Buff->CursorInfo.bVisible = Console->ActiveBuffer->CursorInfo.bVisible; + Buff->CursorInfo.dwSize = Console->ActiveBuffer->CursorInfo.dwSize; + } + else + { + Buff->CursorInfo.bVisible = TRUE; + Buff->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE; + } + + if (Buff->MaxX == 0) + { + Buff->MaxX = 80; + } + + if (Buff->MaxY == 0) + { + Buff->MaxY = 25; + } + + Status = CsrInitConsoleScreenBuffer(Console, Buff); + if (NT_SUCCESS(Status)) + { + Status = Win32CsrInsertObject(ProcessData, + &CreateScreenBufferRequest->OutputHandle, + &Buff->Header, + CreateScreenBufferRequest->Access, + CreateScreenBufferRequest->Inheritable, + CreateScreenBufferRequest->ShareMode); + } + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + ConioUnlockConsole(Console); + RtlLeaveCriticalSection(&ProcessData->HandleTableLock); + return Status; +} + +CSR_API(SrvGetConsoleScreenBufferInfo) // CsrGetScreenBufferInfo +{ + NTSTATUS Status; + PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + PCONSOLE_SCREEN_BUFFER_INFO pInfo; + + DPRINT("SrvGetConsoleScreenBufferInfo\n"); + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ScreenBufferInfoRequest->ConsoleHandle, &Buff, GENERIC_READ); + if (! NT_SUCCESS(Status)) + { + return Status; + } + Console = Buff->Header.Console; + pInfo = &ScreenBufferInfoRequest->Info; + pInfo->dwSize.X = Buff->MaxX; + pInfo->dwSize.Y = Buff->MaxY; + pInfo->dwCursorPosition.X = Buff->CurrentX; + pInfo->dwCursorPosition.Y = Buff->CurrentY; + pInfo->wAttributes = Buff->DefaultAttrib; + pInfo->srWindow.Left = Buff->ShowX; + pInfo->srWindow.Right = Buff->ShowX + Console->Size.X - 1; + pInfo->srWindow.Top = Buff->ShowY; + pInfo->srWindow.Bottom = Buff->ShowY + Console->Size.Y - 1; + pInfo->dwMaximumWindowSize.X = Buff->MaxX; + pInfo->dwMaximumWindowSize.Y = Buff->MaxY; + ConioUnlockScreenBuffer(Buff); + + return STATUS_SUCCESS; +} + +CSR_API(SrvSetConsoleActiveScreenBuffer) +{ + NTSTATUS Status; + PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + + DPRINT("SrvSetConsoleActiveScreenBuffer\n"); + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetScreenBufferRequest->OutputHandle, &Buff, GENERIC_WRITE); + if (! NT_SUCCESS(Status)) + { + return Status; + } + Console = Buff->Header.Console; + + if (Buff == Console->ActiveBuffer) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_SUCCESS; + } + + /* If old buffer has no handles, it's now unreferenced */ + if (Console->ActiveBuffer->Header.HandleCount == 0) + { + ConioDeleteScreenBuffer(Console->ActiveBuffer); + } + /* tie console to new buffer */ + Console->ActiveBuffer = Buff; + /* Redraw the console */ + ConioDrawConsole(Console); + + ConioUnlockScreenBuffer(Buff); + + return STATUS_SUCCESS; +} + +CSR_API(SrvScrollConsoleScreenBuffer) +{ + PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER ScrollConsoleScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScrollConsoleScreenBufferRequest; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + SMALL_RECT ScreenBuffer; + SMALL_RECT SrcRegion; + SMALL_RECT DstRegion; + SMALL_RECT UpdateRegion; + SMALL_RECT ScrollRectangle; + SMALL_RECT ClipRectangle; + NTSTATUS Status; + HANDLE ConsoleHandle; + BOOLEAN UseClipRectangle; + COORD DestinationOrigin; + CHAR_INFO Fill; + CHAR FillChar; + + DPRINT("SrvScrollConsoleScreenBuffer\n"); + + ConsoleHandle = ScrollConsoleScreenBufferRequest->ConsoleHandle; + UseClipRectangle = ScrollConsoleScreenBufferRequest->UseClipRectangle; + DestinationOrigin = ScrollConsoleScreenBufferRequest->DestinationOrigin; + Fill = ScrollConsoleScreenBufferRequest->Fill; + + Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ConsoleHandle, &Buff, GENERIC_WRITE); + if (! NT_SUCCESS(Status)) + { + return Status; + } + Console = Buff->Header.Console; + + ScrollRectangle = ScrollConsoleScreenBufferRequest->ScrollRectangle; + + /* Make sure source rectangle is inside the screen buffer */ + ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); + if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle)) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_SUCCESS; + } + + /* If the source was clipped on the left or top, adjust the destination accordingly */ + if (ScrollRectangle.Left < 0) + { + DestinationOrigin.X -= ScrollRectangle.Left; + } + if (ScrollRectangle.Top < 0) + { + DestinationOrigin.Y -= ScrollRectangle.Top; + } + + if (UseClipRectangle) + { + ClipRectangle = ScrollConsoleScreenBufferRequest->ClipRectangle; + if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer)) + { + ConioUnlockScreenBuffer(Buff); + return STATUS_SUCCESS; + } + } + else + { + ClipRectangle = ScreenBuffer; + } + + ConioInitRect(&DstRegion, + DestinationOrigin.Y, + DestinationOrigin.X, + DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1, + DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1); + + if (ScrollConsoleScreenBufferRequest->Unicode) + ConsoleUnicodeCharToAnsiChar(Console, &FillChar, &Fill.Char.UnicodeChar); + else + FillChar = Fill.Char.AsciiChar; + + ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, Fill.Attributes << 8 | (BYTE)FillChar); + + if (Buff == Console->ActiveBuffer) + { + ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion); + if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &ClipRectangle)) + { + /* Draw update region */ + ConioDrawRegion(Console, &UpdateRegion); + } + } + + ConioUnlockScreenBuffer(Buff); return STATUS_SUCCESS; }