+++ /dev/null
-/*
- * reactos/subsys/csrss/win32csr/conio.c
- *
- * Console I/O functions
- *
- * ReactOS Operating System
- */
-
-/* INCLUDES ******************************************************************/
-
-#define NDEBUG
-#include "w32csr.h"
-#include <debug.h>
-
-/* GLOBALS *******************************************************************/
-
-#define ConioInitRect(Rect, top, left, bottom, right) \
- ((Rect)->Top) = top; \
- ((Rect)->Left) = left; \
- ((Rect)->Bottom) = bottom; \
- ((Rect)->Right) = right
-
-#define ConioIsRectEmpty(Rect) \
- (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
-
-#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
- WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
-
-#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
- MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
-
-/* FUNCTIONS *****************************************************************/
-
-PBYTE FASTCALL
-ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff, ULONG X, ULONG Y)
-{
- return &Buff->Buffer[2 * (((Y + Buff->VirtualY) % Buff->MaxY) * Buff->MaxX + X)];
-}
-
-static VOID FASTCALL
-ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff)
-{
- PBYTE Ptr = ConioCoordToPointer(Buff, 0, Buff->CurrentY);
- UINT Pos;
-
- for (Pos = 0; Pos < Buff->MaxX; Pos++)
- {
- /* Fill the cell */
- *Ptr++ = ' ';
- *Ptr++ = Buff->DefaultAttrib;
- }
-}
-
-NTSTATUS FASTCALL
-CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
- PCSRSS_SCREEN_BUFFER Buffer)
-{
- DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer->MaxX, Buffer->MaxY);
-
- Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC;
- Buffer->Header.Console = Console;
- Buffer->Header.HandleCount = 0;
- Buffer->ShowX = 0;
- Buffer->ShowY = 0;
- Buffer->VirtualY = 0;
- Buffer->Buffer = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, Buffer->MaxX * Buffer->MaxY * 2);
- if (NULL == Buffer->Buffer)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- ConioInitScreenBuffer(Console, Buffer);
- /* initialize buffer to be empty with default attributes */
- for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++)
- {
- ClearLineBuffer(Buffer);
- }
- Buffer->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
- Buffer->CurrentX = 0;
- Buffer->CurrentY = 0;
-
- InsertHeadList(&Console->BufferList, &Buffer->ListEntry);
- return STATUS_SUCCESS;
-}
-
-static VOID FASTCALL
-ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, UINT *ScrolledLines)
-{
- /* If we hit bottom, slide the viewable screen */
- if (++Buff->CurrentY == Buff->MaxY)
- {
- Buff->CurrentY--;
- if (++Buff->VirtualY == Buff->MaxY)
- {
- Buff->VirtualY = 0;
- }
- (*ScrolledLines)++;
- ClearLineBuffer(Buff);
- if (UpdateRect->Top != 0)
- {
- UpdateRect->Top--;
- }
- }
- UpdateRect->Left = 0;
- UpdateRect->Right = Buff->MaxX - 1;
- UpdateRect->Bottom = Buff->CurrentY;
-}
-
-NTSTATUS FASTCALL
-ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
- CHAR *Buffer, DWORD Length, BOOL Attrib)
-{
- UINT i;
- PBYTE Ptr;
- SMALL_RECT UpdateRect;
- LONG CursorStartX, CursorStartY;
- UINT ScrolledLines;
-
- CursorStartX = Buff->CurrentX;
- CursorStartY = Buff->CurrentY;
- UpdateRect.Left = Buff->MaxX;
- UpdateRect.Top = Buff->CurrentY;
- UpdateRect.Right = -1;
- UpdateRect.Bottom = Buff->CurrentY;
- ScrolledLines = 0;
-
- for (i = 0; i < Length; i++)
- {
- if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
- {
- /* --- LF --- */
- if (Buffer[i] == '\n')
- {
- Buff->CurrentX = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- continue;
- }
- /* --- BS --- */
- else if (Buffer[i] == '\b')
- {
- /* Only handle BS if we're not on the first pos of the first line */
- if (0 != Buff->CurrentX || 0 != Buff->CurrentY)
- {
- if (0 == Buff->CurrentX)
- {
- /* slide virtual position up */
- Buff->CurrentX = Buff->MaxX - 1;
- Buff->CurrentY--;
- UpdateRect.Top = min(UpdateRect.Top, (LONG)Buff->CurrentY);
- }
- else
- {
- Buff->CurrentX--;
- }
- Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY);
- Ptr[0] = ' ';
- Ptr[1] = Buff->DefaultAttrib;
- UpdateRect.Left = min(UpdateRect.Left, (LONG) Buff->CurrentX);
- UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX);
- }
- continue;
- }
- /* --- CR --- */
- else if (Buffer[i] == '\r')
- {
- Buff->CurrentX = 0;
- UpdateRect.Left = min(UpdateRect.Left, (LONG) Buff->CurrentX);
- UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX);
- continue;
- }
- /* --- TAB --- */
- else if (Buffer[i] == '\t')
- {
- UINT EndX;
-
- UpdateRect.Left = min(UpdateRect.Left, (LONG)Buff->CurrentX);
- EndX = (Buff->CurrentX + 8) & ~7;
- if (EndX > Buff->MaxX)
- {
- EndX = Buff->MaxX;
- }
- Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY);
- while (Buff->CurrentX < EndX)
- {
- *Ptr++ = ' ';
- *Ptr++ = Buff->DefaultAttrib;
- Buff->CurrentX++;
- }
- UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX - 1);
- if (Buff->CurrentX == Buff->MaxX)
- {
- if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
- {
- Buff->CurrentX = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- }
- else
- {
- Buff->CurrentX--;
- }
- }
- continue;
- }
- }
- UpdateRect.Left = min(UpdateRect.Left, (LONG)Buff->CurrentX);
- UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX);
- Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY);
- Ptr[0] = Buffer[i];
- if (Attrib)
- {
- Ptr[1] = Buff->DefaultAttrib;
- }
- Buff->CurrentX++;
- if (Buff->CurrentX == Buff->MaxX)
- {
- if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
- {
- Buff->CurrentX = 0;
- ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
- }
- else
- {
- Buff->CurrentX = CursorStartX;
- }
- }
- }
-
- if (! ConioIsRectEmpty(&UpdateRect) && Buff == Console->ActiveBuffer)
- {
- ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines,
- Buffer, Length);
- }
-
- return STATUS_SUCCESS;
-}
-
-__inline BOOLEAN ConioGetIntersection(
- SMALL_RECT *Intersection,
- SMALL_RECT *Rect1,
- SMALL_RECT *Rect2)
-{
- if (ConioIsRectEmpty(Rect1) ||
- (ConioIsRectEmpty(Rect2)) ||
- (Rect1->Top > Rect2->Bottom) ||
- (Rect1->Left > Rect2->Right) ||
- (Rect1->Bottom < Rect2->Top) ||
- (Rect1->Right < Rect2->Left))
- {
- /* The rectangles do not intersect */
- ConioInitRect(Intersection, 0, -1, 0, -1);
- return FALSE;
- }
-
- ConioInitRect(Intersection,
- max(Rect1->Top, Rect2->Top),
- max(Rect1->Left, Rect2->Left),
- min(Rect1->Bottom, Rect2->Bottom),
- min(Rect1->Right, Rect2->Right));
-
- return TRUE;
-}
-
-__inline BOOLEAN ConioGetUnion(
- SMALL_RECT *Union,
- SMALL_RECT *Rect1,
- SMALL_RECT *Rect2)
-{
- if (ConioIsRectEmpty(Rect1))
- {
- if (ConioIsRectEmpty(Rect2))
- {
- ConioInitRect(Union, 0, -1, 0, -1);
- return FALSE;
- }
- else
- {
- *Union = *Rect2;
- }
- }
- else if (ConioIsRectEmpty(Rect2))
- {
- *Union = *Rect1;
- }
- else
- {
- ConioInitRect(Union,
- min(Rect1->Top, Rect2->Top),
- min(Rect1->Left, Rect2->Left),
- max(Rect1->Bottom, Rect2->Bottom),
- max(Rect1->Right, Rect2->Right));
- }
-
- 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. */
-static VOID FASTCALL
-ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
- SMALL_RECT *SrcRegion,
- SMALL_RECT *DstRegion,
- SMALL_RECT *ClipRegion,
- WORD Fill)
-{
- int Width = ConioRectWidth(SrcRegion);
- int Height = ConioRectHeight(SrcRegion);
- int SX, SY;
- int DX, DY;
- int XDelta, YDelta;
- int i, j;
-
- SY = SrcRegion->Top;
- DY = DstRegion->Top;
- YDelta = 1;
- if (SY < DY)
- {
- /* Moving down: work from bottom up */
- SY = SrcRegion->Bottom;
- DY = DstRegion->Bottom;
- YDelta = -1;
- }
- for (i = 0; i < Height; i++)
- {
- PWORD SRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, SY);
- PWORD DRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, DY);
-
- SX = SrcRegion->Left;
- DX = DstRegion->Left;
- XDelta = 1;
- if (SX < DX)
- {
- /* Moving right: work from right to left */
- SX = SrcRegion->Right;
- DX = DstRegion->Right;
- XDelta = -1;
- }
- for (j = 0; j < Width; j++)
- {
- WORD Cell = SRow[SX];
- if (SX >= ClipRegion->Left && SX <= ClipRegion->Right
- && SY >= ClipRegion->Top && SY <= ClipRegion->Bottom)
- {
- SRow[SX] = Fill;
- }
- if (DX >= ClipRegion->Left && DX <= ClipRegion->Right
- && DY >= ClipRegion->Top && DY <= ClipRegion->Bottom)
- {
- DRow[DX] = Cell;
- }
- SX += XDelta;
- DX += XDelta;
- }
- SY += YDelta;
- DY += YDelta;
- }
-}
-
-CSR_API(CsrWriteConsole)
-{
- NTSTATUS Status;
- PCHAR Buffer;
- PCSRSS_SCREEN_BUFFER Buff;
- PCSRSS_CONSOLE Console;
- DWORD Written = 0;
- ULONG Length;
- ULONG CharSize = (Request->Data.WriteConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
- DPRINT("CsrWriteConsole\n");
-
- if (Request->Header.u1.s1.TotalLength
- < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE)
- + (Request->Data.WriteConsoleRequest.NrCharactersToWrite * CharSize))
- {
- DPRINT1("Invalid request size\n");
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- if (Console->UnpauseEvent)
- {
- Status = NtDuplicateObject(GetCurrentProcess(), Console->UnpauseEvent,
- ProcessData->ProcessHandle, &Request->Data.WriteConsoleRequest.UnpauseEvent,
- SYNCHRONIZE, 0, 0);
- ConioUnlockScreenBuffer(Buff);
- return NT_SUCCESS(Status) ? STATUS_PENDING : Status;
- }
-
- if(Request->Data.WriteConsoleRequest.Unicode)
- {
- Length = WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)Request->Data.WriteConsoleRequest.Buffer,
- Request->Data.WriteConsoleRequest.NrCharactersToWrite,
- NULL, 0, NULL, NULL);
- Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
- if (Buffer)
- {
- WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)Request->Data.WriteConsoleRequest.Buffer,
- Request->Data.WriteConsoleRequest.NrCharactersToWrite,
- Buffer, Length, NULL, NULL);
- }
- else
- {
- Status = STATUS_NO_MEMORY;
- }
- }
- else
- {
- Buffer = (PCHAR)Request->Data.WriteConsoleRequest.Buffer;
- }
-
- if (Buffer)
- {
- if (NT_SUCCESS(Status))
- {
- Status = ConioWriteConsole(Console, Buff, Buffer,
- Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE);
- if (NT_SUCCESS(Status))
- {
- Written = Request->Data.WriteConsoleRequest.NrCharactersToWrite;
- }
- }
- if (Request->Data.WriteConsoleRequest.Unicode)
- {
- RtlFreeHeap(GetProcessHeap(), 0, Buffer);
- }
- }
- ConioUnlockScreenBuffer(Buff);
-
- Request->Data.WriteConsoleRequest.NrCharactersWritten = Written;
-
- 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(Win32CsrApiHeap, 0, Buffer->Buffer);
- HeapFree(Win32CsrApiHeap, 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(CsrGetScreenBufferInfo)
-{
- NTSTATUS Status;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
- PCONSOLE_SCREEN_BUFFER_INFO pInfo;
-
- DPRINT("CsrGetScreenBufferInfo\n");
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, &Buff, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
- pInfo = &Request->Data.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(CsrSetCursor)
-{
- NTSTATUS Status;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
- LONG OldCursorX, OldCursorY;
- LONG NewCursorX, NewCursorY;
-
- DPRINT("CsrSetCursor\n");
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- NewCursorX = Request->Data.SetCursorRequest.Position.X;
- NewCursorY = Request->Data.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;
- 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 = (Request->Data.WriteConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
- if (Request->Header.u1.s1.TotalLength
- < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR)
- + (Request->Data.WriteConsoleOutputCharRequest.Length * CharSize))
- {
- DPRINT1("Invalid request size\n");
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = ConioLockScreenBuffer(ProcessData,
- Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
- &Buff,
- GENERIC_WRITE);
- if (NT_SUCCESS(Status))
- {
- Console = Buff->Header.Console;
- if(Request->Data.WriteConsoleOutputCharRequest.Unicode)
- {
- Length = WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String,
- Request->Data.WriteConsoleOutputCharRequest.Length,
- NULL, 0, NULL, NULL);
- tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
- if (String)
- {
- WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String,
- Request->Data.WriteConsoleOutputCharRequest.Length,
- String, Length, NULL, NULL);
- }
- else
- {
- Status = STATUS_NO_MEMORY;
- }
- }
- else
- {
- String = (PCHAR)Request->Data.WriteConsoleOutputCharRequest.String;
- }
-
- if (String)
- {
- if (NT_SUCCESS(Status))
- {
- X = Request->Data.WriteConsoleOutputCharRequest.Coord.X;
- Y = (Request->Data.WriteConsoleOutputCharRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
- Length = Request->Data.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, &Request->Data.WriteConsoleOutputCharRequest.Coord,
- Request->Data.WriteConsoleOutputCharRequest.Length);
- ConioDrawRegion(Console, &UpdateRect);
- }
-
- Request->Data.WriteConsoleOutputCharRequest.EndCoord.X = X;
- Request->Data.WriteConsoleOutputCharRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
-
- }
- if (Request->Data.WriteConsoleRequest.Unicode)
- {
- RtlFreeHeap(GetProcessHeap(), 0, tmpString);
- }
- }
- ConioUnlockScreenBuffer(Buff);
- }
- Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten = Written;
- return Status;
-}
-
-CSR_API(CsrFillOutputChar)
-{
- NTSTATUS Status;
- 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(ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- X = Request->Data.FillOutputRequest.Position.X;
- Y = (Request->Data.FillOutputRequest.Position.Y + Buff->VirtualY) % Buff->MaxY;
- Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
- if(Request->Data.FillOutputRequest.Unicode)
- ConsoleUnicodeCharToAnsiChar(Console, &Char, &Request->Data.FillOutputRequest.Char.UnicodeChar);
- else
- Char = Request->Data.FillOutputRequest.Char.AsciiChar;
- Length = Request->Data.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, &Request->Data.FillOutputRequest.Position,
- Request->Data.FillOutputRequest.Length);
- ConioDrawRegion(Console, &UpdateRect);
- }
-
- ConioUnlockScreenBuffer(Buff);
- Length = Request->Data.FillOutputRequest.Length;
- Request->Data.FillOutputRequest.NrCharactersWritten = Length;
- return STATUS_SUCCESS;
-}
-
-CSR_API(CsrWriteConsoleOutputAttrib)
-{
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
- PUCHAR Buffer;
- PWORD Attribute;
- int X, Y, Length;
- NTSTATUS Status;
- SMALL_RECT UpdateRect;
-
- DPRINT("CsrWriteConsoleOutputAttrib\n");
-
- if (Request->Header.u1.s1.TotalLength
- < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB)
- + Request->Data.WriteConsoleOutputAttribRequest.Length * sizeof(WORD))
- {
- DPRINT1("Invalid request size\n");
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = ConioLockScreenBuffer(ProcessData,
- Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle,
- &Buff,
- GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X;
- Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
- Length = Request->Data.WriteConsoleOutputAttribRequest.Length;
- Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1];
- Attribute = Request->Data.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, &Request->Data.WriteConsoleOutputAttribRequest.Coord,
- Request->Data.WriteConsoleOutputAttribRequest.Length);
- ConioDrawRegion(Console, &UpdateRect);
- }
-
- Request->Data.WriteConsoleOutputAttribRequest.EndCoord.X = X;
- Request->Data.WriteConsoleOutputAttribRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
-
- ConioUnlockScreenBuffer(Buff);
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(CsrFillOutputAttrib)
-{
- 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(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- X = Request->Data.FillOutputAttribRequest.Coord.X;
- Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
- Length = Request->Data.FillOutputAttribRequest.Length;
- Attr = Request->Data.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, &Request->Data.FillOutputAttribRequest.Coord,
- Request->Data.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(CsrGetCursorInfo)
-{
- PCSRSS_SCREEN_BUFFER Buff;
- NTSTATUS Status;
-
- DPRINT("CsrGetCursorInfo\n");
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, &Buff, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Request->Data.GetCursorInfoRequest.Info.bVisible = Buff->CursorInfo.bVisible;
- Request->Data.GetCursorInfoRequest.Info.dwSize = Buff->CursorInfo.dwSize;
- ConioUnlockScreenBuffer(Buff);
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(CsrSetCursorInfo)
-{
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
- DWORD Size;
- BOOL Visible;
- NTSTATUS Status;
-
- DPRINT("CsrSetCursorInfo\n");
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- Size = Request->Data.SetCursorInfoRequest.Info.dwSize;
- Visible = Request->Data.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_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
-
- DPRINT("CsrSetTextAttrib\n");
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib;
- if (Buff == Console->ActiveBuffer)
- {
- if (! ConioUpdateScreenInfo(Console, Buff))
- {
- ConioUnlockScreenBuffer(Buff);
- return STATUS_UNSUCCESSFUL;
- }
- }
-
- ConioUnlockScreenBuffer(Buff);
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(CsrCreateScreenBuffer)
-{
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
- NTSTATUS Status;
-
- DPRINT("CsrCreateScreenBuffer\n");
-
- RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- Status = ConioConsoleFromProcessData(ProcessData, &Console);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Buff = HeapAlloc(Win32CsrApiHeap, 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,
- &Request->Data.CreateScreenBufferRequest.OutputHandle,
- &Buff->Header,
- Request->Data.CreateScreenBufferRequest.Access,
- Request->Data.CreateScreenBufferRequest.Inheritable,
- Request->Data.CreateScreenBufferRequest.ShareMode);
- }
- }
- else
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- ConioUnlockConsole(Console);
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
-}
-
-CSR_API(CsrSetScreenBuffer)
-{
- NTSTATUS Status;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
-
- DPRINT("CsrSetScreenBuffer\n");
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.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(CsrWriteConsoleOutput)
-{
- SHORT i, X, Y, SizeX, SizeY;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
- SMALL_RECT ScreenBuffer;
- CHAR_INFO* CurCharInfo;
- SMALL_RECT WriteRegion;
- CHAR_INFO* CharInfo;
- COORD BufferCoord;
- COORD BufferSize;
- NTSTATUS Status;
- PBYTE Ptr;
-
- DPRINT("CsrWriteConsoleOutput\n");
-
- Status = ConioLockScreenBuffer(ProcessData,
- Request->Data.WriteConsoleOutputRequest.ConsoleHandle,
- &Buff,
- GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize;
- BufferCoord = Request->Data.WriteConsoleOutputRequest.BufferCoord;
- CharInfo = Request->Data.WriteConsoleOutputRequest.CharInfo;
- if (!Win32CsrValidateBuffer(ProcessData, CharInfo,
- BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
- {
- ConioUnlockScreenBuffer(Buff);
- return STATUS_ACCESS_VIOLATION;
- }
- WriteRegion = Request->Data.WriteConsoleOutputRequest.WriteRegion;
-
- SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion));
- SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion));
- WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
- WriteRegion.Right = WriteRegion.Left + SizeX - 1;
-
- /* Make sure WriteRegion is inside the screen buffer */
- ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
- if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
- {
- ConioUnlockScreenBuffer(Buff);
-
- /* It is okay to have a WriteRegion completely outside the screen buffer.
- No data is written then. */
- return STATUS_SUCCESS;
- }
-
- for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++)
- {
- CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
- Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y);
- for (X = WriteRegion.Left; X <= WriteRegion.Right; X++)
- {
- CHAR AsciiChar;
- if (Request->Data.WriteConsoleOutputRequest.Unicode)
- {
- ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
- }
- else
- {
- AsciiChar = CurCharInfo->Char.AsciiChar;
- }
- *Ptr++ = AsciiChar;
- *Ptr++ = CurCharInfo->Attributes;
- CurCharInfo++;
- }
- }
-
- ConioDrawRegion(Console, &WriteRegion);
-
- ConioUnlockScreenBuffer(Buff);
-
- Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.Left + SizeX - 1;
- Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
- Request->Data.WriteConsoleOutputRequest.WriteRegion.Left = WriteRegion.Left;
- Request->Data.WriteConsoleOutputRequest.WriteRegion.Top = WriteRegion.Top;
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(CsrScrollConsoleScreenBuffer)
-{
- 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("CsrScrollConsoleScreenBuffer\n");
-
- ConsoleHandle = Request->Data.ScrollConsoleScreenBufferRequest.ConsoleHandle;
- UseClipRectangle = Request->Data.ScrollConsoleScreenBufferRequest.UseClipRectangle;
- DestinationOrigin = Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin;
- Fill = Request->Data.ScrollConsoleScreenBufferRequest.Fill;
-
- Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- ScrollRectangle = Request->Data.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 = Request->Data.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 (Request->Data.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;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
- DWORD Xpos, Ypos;
- PCHAR ReadBuffer;
- DWORD i;
- ULONG CharSize;
- CHAR Char;
-
- DPRINT("CsrReadConsoleOutputChar\n");
-
- ReadBuffer = Request->Data.ReadConsoleOutputCharRequest.String;
-
- CharSize = (Request->Data.ReadConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, &Buff, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X;
- Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
-
- for (i = 0; i < Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; ++i)
- {
- Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)];
-
- if(Request->Data.ReadConsoleOutputCharRequest.Unicode)
- {
- ConsoleAnsiCharToUnicodeChar(Console, (WCHAR*)ReadBuffer, &Char);
- ReadBuffer += sizeof(WCHAR);
- }
- else
- *(ReadBuffer++) = Char;
-
- Xpos++;
-
- if (Xpos == Buff->MaxX)
- {
- Xpos = 0;
- Ypos++;
-
- if (Ypos == Buff->MaxY)
- {
- Ypos = 0;
- }
- }
- }
-
- *ReadBuffer = 0;
- Request->Data.ReadConsoleOutputCharRequest.EndCoord.X = Xpos;
- Request->Data.ReadConsoleOutputCharRequest.EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
-
- ConioUnlockScreenBuffer(Buff);
-
- Request->Data.ReadConsoleOutputCharRequest.CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)Request->Data.ReadConsoleOutputCharRequest.String) / CharSize;
- if (Request->Data.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_SCREEN_BUFFER Buff;
- DWORD Xpos, Ypos;
- PWORD ReadBuffer;
- DWORD i;
- DWORD CurrentLength;
-
- DPRINT("CsrReadConsoleOutputAttrib\n");
-
- ReadBuffer = Request->Data.ReadConsoleOutputAttribRequest.Attribute;
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X;
- Ypos = (Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
-
- for (i = 0; i < Request->Data.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;
-
- Request->Data.ReadConsoleOutputAttribRequest.EndCoord.X = Xpos;
- Request->Data.ReadConsoleOutputAttribRequest.EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
-
- ConioUnlockScreenBuffer(Buff);
-
- CurrentLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB)
- + Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead * sizeof(WORD);
- if (CurrentLength > sizeof(CSR_API_MESSAGE))
- {
- DPRINT1("Length won't fit in message\n");
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(CsrReadConsoleOutput)
-{
- 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("CsrReadConsoleOutput\n");
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, &Buff, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
-
- CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo;
- ReadRegion = Request->Data.ReadConsoleOutputRequest.ReadRegion;
- BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize;
- BufferCoord = Request->Data.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 (Request->Data.ReadConsoleOutputRequest.Unicode)
- {
- MultiByteToWideChar(CodePage, 0,
- (PCHAR)Ptr++, 1,
- &CurCharInfo->Char.UnicodeChar, 1);
- }
- else
- {
- CurCharInfo->Char.AsciiChar = *Ptr++;
- }
- CurCharInfo->Attributes = *Ptr++;
- ++CurCharInfo;
- }
- }
-
- ConioUnlockScreenBuffer(Buff);
-
- Request->Data.ReadConsoleOutputRequest.ReadRegion.Right = ReadRegion.Left + SizeX - 1;
- Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom = ReadRegion.Top + SizeY - 1;
- Request->Data.ReadConsoleOutputRequest.ReadRegion.Left = ReadRegion.Left;
- Request->Data.ReadConsoleOutputRequest.ReadRegion.Top = ReadRegion.Top;
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(CsrSetScreenBufferSize)
-{
- NTSTATUS Status;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
-
- Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferSize.OutputHandle, &Buff, GENERIC_WRITE);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- Status = ConioResizeBuffer(Console, Buff, Request->Data.SetScreenBufferSize.Size);
- ConioUnlockScreenBuffer(Buff);
-
- return Status;
-}
-
-/* EOF */