* PROGRAMMERS:
*/
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
#include "consrv.h"
#include "conio.h"
#define NDEBUG
#include <debug.h>
-/* 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))
#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)
}
}
- if (! ConioIsRectEmpty(&UpdateRect) && Buff == Console->ActiveBuffer)
+ if (!ConioIsRectEmpty(&UpdateRect) && Buff == Console->ActiveBuffer)
{
ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines,
Buffer, Length);
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,
}
}
-CSR_API(SrvWriteConsole)
-{
- NTSTATUS Status;
- PCSRSS_WRITE_CONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
- PCHAR Buffer;
- PCSRSS_SCREEN_BUFFER Buff;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
- PCSRSS_CONSOLE Console;
- DWORD Written = 0;
- ULONG Length;
- ULONG CharSize = (WriteConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
- DPRINT("SrvWriteConsole\n");
-
- if (ApiMessage->Header.u1.s1.TotalLength
- < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE)
- + (WriteConsoleRequest->NrCharactersToWrite * CharSize))
- {
- DPRINT1("Invalid ApiMessage size\n");
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = ConioLockScreenBuffer(ProcessData, 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, &WriteConsoleRequest->UnpauseEvent,
- SYNCHRONIZE, 0, 0);
- ConioUnlockScreenBuffer(Buff);
- return NT_SUCCESS(Status) ? STATUS_PENDING : Status;
- }
-
- if(WriteConsoleRequest->Unicode)
- {
- Length = WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- NULL, 0, NULL, NULL);
- Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
- if (Buffer)
- {
- WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- Buffer, Length, NULL, NULL);
- }
- else
- {
- Status = STATUS_NO_MEMORY;
- }
- }
- else
- {
- Buffer = (PCHAR)WriteConsoleRequest->Buffer;
- }
-
- if (Buffer)
- {
- if (NT_SUCCESS(Status))
- {
- Status = ConioWriteConsole(Console, Buff, Buffer,
- WriteConsoleRequest->NrCharactersToWrite, TRUE);
- if (NT_SUCCESS(Status))
- {
- Written = WriteConsoleRequest->NrCharactersToWrite;
- }
- }
- if (WriteConsoleRequest->Unicode)
- {
- RtlFreeHeap(GetProcessHeap(), 0, Buffer);
- }
- }
- ConioUnlockScreenBuffer(Buff);
-
- WriteConsoleRequest->NrCharactersWritten = Written;
-
- return Status;
-}
-
VOID WINAPI
ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer)
{
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)
{
}
}
-CSR_API(CsrWriteConsoleOutputChar)
+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;
+}
+
+static NTSTATUS
+DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
+ IN PCSR_THREAD ClientThread,
+ IN BOOL CreateWaitBlock OPTIONAL);
+
+// Wait function CSR_WAIT_FUNCTION
+static BOOLEAN
+WriteConsoleThread(IN PLIST_ENTRY WaitList,
+ IN PCSR_THREAD WaitThread,
+ IN PCSR_API_MESSAGE WaitApiMessage,
+ IN PVOID WaitContext,
+ IN PVOID WaitArgument1,
+ IN PVOID WaitArgument2,
+ IN ULONG WaitFlags)
{
NTSTATUS Status;
- PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputCharRequest;
- PCHAR String, tmpString = NULL;
- PBYTE Buffer;
+
+ Status = DoWriteConsole(WaitApiMessage,
+ WaitThread,
+ FALSE);
+
+ if (Status != STATUS_PENDING)
+ {
+ WaitApiMessage->Status = Status;
+ }
+
+ return (Status == STATUS_PENDING ? FALSE : TRUE);
+}
+
+static NTSTATUS
+DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
+ IN PCSR_THREAD ClientThread,
+ IN BOOL CreateWaitBlock OPTIONAL)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCSRSS_WRITE_CONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
- DWORD X, Y, Length, CharSize, Written = 0;
- SMALL_RECT UpdateRect;
+ PCHAR Buffer;
+ DWORD Written = 0;
+ ULONG Length;
- DPRINT("CsrWriteConsoleOutputChar\n");
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
+ if (!NT_SUCCESS(Status)) return Status;
- CharSize = (WriteConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
+ Console = Buff->Header.Console;
- if (ApiMessage->Header.u1.s1.TotalLength
- < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR)
- + (WriteConsoleOutputCharRequest->Length * CharSize))
+ // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
+ if (Console->PauseFlags && Console->UnpauseEvent != NULL)
{
- DPRINT1("Invalid ApiMessage size\n");
- return STATUS_INVALID_PARAMETER;
- }
+ if (CreateWaitBlock)
+ {
+ if (!CsrCreateWait(&Console->WriteWaitQueue,
+ WriteConsoleThread,
+ ClientThread,
+ ApiMessage,
+ NULL,
+ NULL))
+ {
+ /* Fail */
+ ConioUnlockScreenBuffer(Buff);
+ return STATUS_NO_MEMORY;
+ }
+ }
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process,
- WriteConsoleOutputCharRequest->ConsoleHandle,
- &Buff,
- GENERIC_WRITE);
- if (NT_SUCCESS(Status))
+ /* Wait until we un-pause the console */
+ Status = STATUS_PENDING;
+ }
+ else
{
- Console = Buff->Header.Console;
- if(WriteConsoleOutputCharRequest->Unicode)
+ if(WriteConsoleRequest->Unicode)
{
Length = WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteConsoleOutputCharRequest->String,
- WriteConsoleOutputCharRequest->Length,
+ (PWCHAR)WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NrCharactersToWrite,
NULL, 0, NULL, NULL);
- tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
- if (String)
+ Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
+ if (Buffer)
{
WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteConsoleOutputCharRequest->String,
- WriteConsoleOutputCharRequest->Length,
- String, Length, NULL, NULL);
+ (PWCHAR)WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NrCharactersToWrite,
+ Buffer, Length, NULL, NULL);
}
else
{
}
else
{
- String = (PCHAR)WriteConsoleOutputCharRequest->String;
+ Buffer = (PCHAR)WriteConsoleRequest->Buffer;
}
- if (String)
+ if (Buffer)
{
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--)
+ Status = ConioWriteConsole(Console, Buff, Buffer,
+ WriteConsoleRequest->NrCharactersToWrite, TRUE);
+ if (NT_SUCCESS(Status))
{
- *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);
+ Written = WriteConsoleRequest->NrCharactersToWrite;
}
-
- WriteConsoleOutputCharRequest->EndCoord.X = X;
- WriteConsoleOutputCharRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
-
}
- if (WriteConsoleOutputCharRequest->Unicode)
+ if (WriteConsoleRequest->Unicode)
{
- RtlFreeHeap(GetProcessHeap(), 0, tmpString);
+ RtlFreeHeap(GetProcessHeap(), 0, Buffer);
}
}
- ConioUnlockScreenBuffer(Buff);
+
+ WriteConsoleRequest->NrCharactersWritten = Written;
}
- WriteConsoleOutputCharRequest->NrCharactersWritten = Written;
+
+ ConioUnlockScreenBuffer(Buff);
return Status;
}
-CSR_API(CsrFillOutputChar)
+
+/* PUBLIC APIS ****************************************************************/
+
+CSR_API(SrvReadConsoleOutput)
{
- NTSTATUS Status;
- PCSRSS_FILL_OUTPUT FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
- PCSRSS_CONSOLE Console;
+ PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputRequest;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ PCHAR_INFO CharInfo;
+ PCHAR_INFO CurCharInfo;
PCSRSS_SCREEN_BUFFER Buff;
- DWORD X, Y, Length, Written = 0;
- CHAR Char;
- PBYTE Buffer;
- SMALL_RECT UpdateRect;
+ 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");
- DPRINT("CsrFillOutputChar\n");
+ CharInfo = ReadConsoleOutputRequest->CharInfo;
+ ReadRegion = ReadConsoleOutputRequest->ReadRegion;
+ BufferSize = ReadConsoleOutputRequest->BufferSize;
+ BufferCoord = ReadConsoleOutputRequest->BufferCoord;
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, FillOutputRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&ReadConsoleOutputRequest->CharInfo,
+ BufferSize.X * BufferSize.Y,
+ sizeof(CHAR_INFO)))
{
- return Status;
+ return STATUS_INVALID_PARAMETER;
}
- 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--)
+ Status = ConioLockScreenBuffer(ProcessData, ReadConsoleOutputRequest->ConsoleHandle, &Buff, GENERIC_READ);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* FIXME: Is this correct? */
+ CodePage = ProcessData->Console->OutputCodePage;
+
+ SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
+ SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion));
+ ReadRegion.Bottom = ReadRegion.Top + SizeY;
+ ReadRegion.Right = ReadRegion.Left + SizeX;
+
+ ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX);
+ if (!ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
{
- *Buffer = Char;
- Buffer += 2;
- Written++;
- if (++X == Buff->MaxX)
+ 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 (++Y == Buff->MaxY)
+ if (ReadConsoleOutputRequest->Unicode)
{
- Y = 0;
- Buffer = Buff->Buffer;
+ // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
+ MultiByteToWideChar(CodePage, 0,
+ (PCHAR)Ptr++, 1,
+ &CurCharInfo->Char.UnicodeChar, 1);
}
- X = 0;
+ else
+ {
+ CurCharInfo->Char.AsciiChar = *Ptr++;
+ }
+ CurCharInfo->Attributes = *Ptr++;
+ ++CurCharInfo;
}
}
- if (Buff == Console->ActiveBuffer)
- {
- ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputRequest->Position,
- FillOutputRequest->Length);
- ConioDrawRegion(Console, &UpdateRect);
- }
-
ConioUnlockScreenBuffer(Buff);
- Length = FillOutputRequest->Length;
- FillOutputRequest->NrCharactersWritten = Length;
+
+ 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(CsrWriteConsoleOutputAttrib)
+CSR_API(SrvWriteConsole)
{
- 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;
+ PCSRSS_WRITE_CONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
+
+ DPRINT("SrvWriteConsole\n");
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID)&WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->BufferSize,
+ sizeof(BYTE)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = DoWriteConsole(ApiMessage,
+ CsrGetClientThread(),
+ TRUE);
+
+ if (Status == STATUS_PENDING)
+ *ReplyCode = CsrReplyPending;
+
+ return Status;
+}
+
+CSR_API(SrvWriteConsoleOutput)
+{
+ PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputRequest;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ 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("CsrWriteConsoleOutputAttrib\n");
+ DPRINT("SrvWriteConsoleOutput\n");
+
+ BufferSize = WriteConsoleOutputRequest->BufferSize;
+ BufferCoord = WriteConsoleOutputRequest->BufferCoord;
+ CharInfo = WriteConsoleOutputRequest->CharInfo;
- if (ApiMessage->Header.u1.s1.TotalLength
- < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB)
- + WriteConsoleOutputAttribRequest->Length * sizeof(WORD))
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&WriteConsoleOutputRequest->CharInfo,
+ BufferSize.X * BufferSize.Y,
+ sizeof(CHAR_INFO)))
{
- DPRINT1("Invalid ApiMessage size\n");
return STATUS_INVALID_PARAMETER;
}
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process,
- WriteConsoleOutputAttribRequest->ConsoleHandle,
+ Status = ConioLockScreenBuffer(ProcessData,
+ WriteConsoleOutputRequest->ConsoleHandle,
&Buff,
GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ WriteRegion = 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))
{
- return Status;
+ ConioUnlockScreenBuffer(Buff);
+
+ /* It is okay to have a WriteRegion completely outside the screen buffer.
+ No data is written then. */
+ return STATUS_SUCCESS;
}
- 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--)
+ for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++)
{
- *Buffer = (UCHAR)(*Attribute++);
- Buffer += 2;
- if (++X == Buff->MaxX)
+ CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
+ Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y);
+ for (X = WriteRegion.Left; X <= WriteRegion.Right; X++)
{
- if (++Y == Buff->MaxY)
+ CHAR AsciiChar;
+ if (WriteConsoleOutputRequest->Unicode)
{
- Y = 0;
- Buffer = Buff->Buffer + 1;
+ ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
}
- X = 0;
+ else
+ {
+ AsciiChar = CurCharInfo->Char.AsciiChar;
+ }
+ *Ptr++ = AsciiChar;
+ *Ptr++ = CurCharInfo->Attributes;
+ CurCharInfo++;
}
}
- if (Buff == Console->ActiveBuffer)
+ ConioDrawRegion(Console, &WriteRegion);
+
+ ConioUnlockScreenBuffer(Buff);
+
+ WriteConsoleOutputRequest->WriteRegion.Right = WriteRegion.Left + SizeX - 1;
+ WriteConsoleOutputRequest->WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
+ WriteConsoleOutputRequest->WriteRegion.Left = WriteRegion.Left;
+ WriteConsoleOutputRequest->WriteRegion.Top = WriteRegion.Top;
+
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvReadConsoleOutputString)
+{
+ NTSTATUS Status;
+ PCSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputCodeRequest;
+ PCSRSS_CONSOLE Console;
+ PCSRSS_SCREEN_BUFFER Buff;
+ USHORT CodeType;
+ DWORD Xpos, Ypos;
+ PVOID ReadBuffer;
+ DWORD i;
+ ULONG CodeSize;
+ BYTE Code;
+
+ DPRINT("SrvReadConsoleOutputString\n");
+
+ CodeType = ReadConsoleOutputCodeRequest->CodeType;
+ switch (CodeType)
{
- ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputAttribRequest->Coord,
- WriteConsoleOutputAttribRequest->Length);
- ConioDrawRegion(Console, &UpdateRect);
+ case CODE_ASCII:
+ CodeSize = sizeof(CHAR);
+ break;
+
+ case CODE_UNICODE:
+ CodeSize = sizeof(WCHAR);
+ break;
+
+ case CODE_ATTRIBUTE:
+ CodeSize = sizeof(WORD);
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&ReadConsoleOutputCodeRequest->pCode.pCode,
+ ReadConsoleOutputCodeRequest->NumCodesToRead,
+ CodeSize))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadConsoleOutputCodeRequest->ConsoleHandle, &Buff, GENERIC_READ);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ ReadBuffer = ReadConsoleOutputCodeRequest->pCode.pCode;
+ Xpos = ReadConsoleOutputCodeRequest->ReadCoord.X;
+ Ypos = (ReadConsoleOutputCodeRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
+
+ /*
+ * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
+ *
+ * If the number of attributes (resp. characters) to be read from extends
+ * beyond the end of the specified screen buffer row, attributes (resp.
+ * characters) are read from the next row. If the number of attributes
+ * (resp. characters) to be read from extends beyond the end of the console
+ * screen buffer, attributes (resp. characters) up to the end of the console
+ * screen buffer are read.
+ *
+ * TODO: Do NOT loop up to NumCodesToRead, but stop before
+ * if we are going to overflow...
+ */
+ for (i = 0; i < ReadConsoleOutputCodeRequest->NumCodesToRead; ++i)
+ {
+ Code = Buff->Buffer[2 * (Xpos + Ypos * Buff->MaxX) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
+
+ switch (CodeType)
+ {
+ case CODE_UNICODE:
+ ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)ReadBuffer, (PCHAR)&Code);
+ break;
+
+ case CODE_ASCII:
+ *(PCHAR)ReadBuffer = (CHAR)Code;
+ break;
+
+ case CODE_ATTRIBUTE:
+ *(PWORD)ReadBuffer = (WORD)Code;
+ break;
+ }
+ ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
+
+ Xpos++;
+
+ if (Xpos == Buff->MaxX)
+ {
+ Xpos = 0;
+ Ypos++;
+
+ if (Ypos == Buff->MaxY)
+ {
+ Ypos = 0;
+ }
+ }
+ }
+
+ switch (CodeType)
+ {
+ case CODE_UNICODE:
+ *(PWCHAR)ReadBuffer = 0;
+ break;
+
+ case CODE_ASCII:
+ *(PCHAR)ReadBuffer = 0;
+ break;
+
+ case CODE_ATTRIBUTE:
+ *(PWORD)ReadBuffer = 0;
+ break;
}
- WriteConsoleOutputAttribRequest->EndCoord.X = X;
- WriteConsoleOutputAttribRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
+ ReadConsoleOutputCodeRequest->EndCoord.X = Xpos;
+ ReadConsoleOutputCodeRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
ConioUnlockScreenBuffer(Buff);
+ ReadConsoleOutputCodeRequest->CodesRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadConsoleOutputCodeRequest->pCode.pCode) / CodeSize;
+ // <= ReadConsoleOutputCodeRequest->NumCodesToRead
+
return STATUS_SUCCESS;
}
-CSR_API(CsrFillOutputAttrib)
+CSR_API(SrvWriteConsoleOutputString)
{
- 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_WRITE_CONSOLE_OUTPUT_CODE WriteConsoleOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputCodeRequest;
PCSRSS_CONSOLE Console;
+ PCSRSS_SCREEN_BUFFER Buff;
+ USHORT CodeType;
+ PBYTE Buffer; // PUCHAR
+ PCHAR String, tmpString = NULL;
+ DWORD X, Y, Length; // , Written = 0;
+ ULONG CodeSize;
+ SMALL_RECT UpdateRect;
- DPRINT("CsrFillOutputAttrib\n");
+ DPRINT("SrvWriteConsoleOutputString\n");
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, FillOutputAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
+ CodeType = WriteConsoleOutputCodeRequest->CodeType;
+ switch (CodeType)
{
- return Status;
+ case CODE_ASCII:
+ CodeSize = sizeof(CHAR);
+ break;
+
+ case CODE_UNICODE:
+ CodeSize = sizeof(WCHAR);
+ break;
+
+ case CODE_ATTRIBUTE:
+ CodeSize = sizeof(WORD);
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&WriteConsoleOutputCodeRequest->pCode.pCode,
+ WriteConsoleOutputCodeRequest->Length,
+ CodeSize))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ WriteConsoleOutputCodeRequest->ConsoleHandle,
+ &Buff,
+ GENERIC_WRITE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ switch (CodeType)
+ {
+ case CODE_UNICODE:
+ {
+ Length = WideCharToMultiByte(Console->OutputCodePage, 0,
+ (PWCHAR)WriteConsoleOutputCodeRequest->pCode.UnicodeChar,
+ WriteConsoleOutputCodeRequest->Length,
+ NULL, 0, NULL, NULL);
+ tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
+ if (String)
+ {
+ WideCharToMultiByte(Console->OutputCodePage, 0,
+ (PWCHAR)WriteConsoleOutputCodeRequest->pCode.UnicodeChar,
+ WriteConsoleOutputCodeRequest->Length,
+ String, Length, NULL, NULL);
+ }
+ else
+ {
+ Status = STATUS_NO_MEMORY;
+ }
+
+ break;
+ }
+
+ case CODE_ASCII:
+ String = (PCHAR)WriteConsoleOutputCodeRequest->pCode.AsciiChar;
+ break;
+
+ case CODE_ATTRIBUTE:
+ default:
+ // *(ReadBuffer++) = Code;
+ String = (PCHAR)WriteConsoleOutputCodeRequest->pCode.Attribute;
+ break;
+ }
+
+ if (String && NT_SUCCESS(Status))
+ {
+ X = WriteConsoleOutputCodeRequest->Coord.X;
+ Y = (WriteConsoleOutputCodeRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY;
+ Length = WriteConsoleOutputCodeRequest->Length;
+ Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
+
+ while (Length--)
+ {
+ *Buffer = *String++;
+ // ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
+ String = (PCHAR)((ULONG_PTR)String + CodeSize);
+ // Written++;
+ Buffer += 2;
+ if (++X == Buff->MaxX)
+ {
+ if (++Y == Buff->MaxY)
+ {
+ Y = 0;
+ Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
+ }
+ X = 0;
+ }
+ }
+
+ if (Buff == Console->ActiveBuffer)
+ {
+ ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputCodeRequest->Coord,
+ WriteConsoleOutputCodeRequest->Length);
+ ConioDrawRegion(Console, &UpdateRect);
+ }
+
+ WriteConsoleOutputCodeRequest->EndCoord.X = X;
+ WriteConsoleOutputCodeRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
+ }
+
+ if (tmpString)
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, tmpString);
}
+
+ ConioUnlockScreenBuffer(Buff);
+
+ // WriteConsoleOutputCodeRequest->NrCharactersWritten = Written;
+ return Status;
+}
+
+CSR_API(SrvFillConsoleOutput)
+{
+ 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;
+ USHORT CodeType;
+ BYTE Code;
+ PBYTE Buffer;
+ SMALL_RECT UpdateRect;
+
+ DPRINT("SrvFillConsoleOutput\n");
+
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), FillOutputRequest->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];
+ CodeType = FillOutputRequest->CodeType;
+
+ X = FillOutputRequest->Coord.X;
+ Y = (FillOutputRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY;
+ Length = FillOutputRequest->Length;
+ Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
+
+ switch (CodeType)
+ {
+ case CODE_ASCII:
+ Code = (BYTE)FillOutputRequest->Code.AsciiChar;
+ break;
+
+ case CODE_UNICODE:
+ ConsoleUnicodeCharToAnsiChar(Console, (PCHAR)&Code, &FillOutputRequest->Code.UnicodeChar);
+ break;
+
+ case CODE_ATTRIBUTE:
+ Code = (BYTE)FillOutputRequest->Code.Attribute;
+ break;
+
+ default:
+ ConioUnlockScreenBuffer(Buff);
+ return STATUS_INVALID_PARAMETER;
+ }
+
while (Length--)
{
- *Buffer = Attr;
+ *Buffer = Code;
Buffer += 2;
+ // Written++;
if (++X == Buff->MaxX)
{
if (++Y == Buff->MaxY)
{
Y = 0;
- Buffer = Buff->Buffer + 1;
+ Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
}
X = 0;
}
if (Buff == Console->ActiveBuffer)
{
- ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputAttribRequest->Coord,
- FillOutputAttribRequest->Length);
+ ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputRequest->Coord,
+ FillOutputRequest->Length);
ConioDrawRegion(Console, &UpdateRect);
}
ConioUnlockScreenBuffer(Buff);
-
+/*
+ Length = FillOutputRequest->Length;
+ FillOutputRequest->NrCharactersWritten = Length;
+*/
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_CURSOR_INFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest;
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;
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->ConsoleHandle, &Buff, GENERIC_READ);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ CursorInfoRequest->Info.bVisible = Buff->CursorInfo.bVisible;
+ CursorInfoRequest->Info.dwSize = Buff->CursorInfo.dwSize;
ConioUnlockScreenBuffer(Buff);
return STATUS_SUCCESS;
CSR_API(SrvSetConsoleCursorInfo)
{
- PCSRSS_SET_CURSOR_INFO SetCursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorInfoRequest;
+ NTSTATUS Status;
+ PCSRSS_CURSOR_INFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest;
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;
- }
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
+ if (!NT_SUCCESS(Status)) return Status;
+
Console = Buff->Header.Console;
- Size = SetCursorInfoRequest->Info.dwSize;
- Visible = SetCursorInfoRequest->Info.bVisible;
+ Size = CursorInfoRequest->Info.dwSize;
+ Visible = CursorInfoRequest->Info.bVisible;
if (Size < 1)
{
Size = 1;
Size = 100;
}
- if (Size != Buff->CursorInfo.dwSize
- || (Visible && ! Buff->CursorInfo.bVisible) || (! Visible && Buff->CursorInfo.bVisible))
+ 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))
+ if (!ConioSetCursorInfo(Console, Buff))
{
ConioUnlockScreenBuffer(Buff);
return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}
-CSR_API(CsrSetTextAttrib)
+CSR_API(SrvSetConsoleCursorPosition)
{
NTSTATUS Status;
- PCSRSS_SET_ATTRIB SetAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetAttribRequest;
+ PCSRSS_SET_CURSOR_POSITION SetCursorPositionRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorPositionRequest;
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
+ LONG OldCursorX, OldCursorY;
+ LONG NewCursorX, NewCursorY;
- DPRINT("CsrSetTextAttrib\n");
+ DPRINT("SrvSetConsoleCursorPosition\n");
+
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetCursorPositionRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
+ if (!NT_SUCCESS(Status)) return Status;
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
Console = Buff->Header.Console;
- Buff->DefaultAttrib = SetAttribRequest->Attrib;
+ NewCursorX = SetCursorPositionRequest->Position.X;
+ NewCursorY = SetCursorPositionRequest->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 (! ConioUpdateScreenInfo(Console, Buff))
+ if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
{
ConioUnlockScreenBuffer(Buff);
return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}
-CSR_API(SrvCreateConsoleScreenBuffer)
+CSR_API(SrvSetConsoleTextAttribute)
{
- PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+ NTSTATUS Status;
+ PCSRSS_SET_ATTRIB SetAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetAttribRequest;
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
+
+ DPRINT("SrvSetConsoleTextAttribute\n");
+
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(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)
+{
NTSTATUS Status;
+ PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ PCSRSS_CONSOLE Console;
+ PCSRSS_SCREEN_BUFFER Buff;
DPRINT("SrvCreateConsoleScreenBuffer\n");
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+
Status = ConioConsoleFromProcessData(ProcessData, &Console);
- if (! NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
}
Buff = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER));
-
if (Buff != NULL)
{
if (Console->ActiveBuffer)
}
ConioUnlockConsole(Console);
+
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+
return Status;
}
-CSR_API(SrvSetConsoleActiveScreenBuffer)
+CSR_API(SrvGetConsoleScreenBufferInfo)
{
NTSTATUS Status;
- PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest;
+ PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest;
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
+ PCONSOLE_SCREEN_BUFFER_INFO pInfo = &ScreenBufferInfoRequest->Info;
- DPRINT("SrvSetConsoleActiveScreenBuffer\n");
+ DPRINT("SrvGetConsoleScreenBufferInfo\n");
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetScreenBufferRequest->OutputHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ScreenBufferInfoRequest->ConsoleHandle, &Buff, GENERIC_READ);
+ if (!NT_SUCCESS(Status)) return Status;
- if (Buff == Console->ActiveBuffer)
- {
- ConioUnlockScreenBuffer(Buff);
- return STATUS_SUCCESS;
- }
+ Console = Buff->Header.Console;
- /* 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);
+ 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(SrvWriteConsoleOutput)
+CSR_API(SrvSetConsoleActiveScreenBuffer)
{
- PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputRequest;
- SHORT i, X, Y, SizeX, SizeY;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+ NTSTATUS Status;
+ PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest;
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("SrvWriteConsoleOutput\n");
- Status = ConioLockScreenBuffer(ProcessData,
- WriteConsoleOutputRequest->ConsoleHandle,
- &Buff,
- GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
+ DPRINT("SrvSetConsoleActiveScreenBuffer\n");
- BufferSize = WriteConsoleOutputRequest->BufferSize;
- BufferCoord = WriteConsoleOutputRequest->BufferCoord;
- CharInfo = WriteConsoleOutputRequest->CharInfo;
- if (!Win32CsrValidateBuffer(ProcessData, CharInfo,
- BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
- {
- ConioUnlockScreenBuffer(Buff);
- return STATUS_ACCESS_VIOLATION;
- }
- WriteRegion = WriteConsoleOutputRequest->WriteRegion;
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetScreenBufferRequest->OutputHandle, &Buff, GENERIC_WRITE);
+ if (!NT_SUCCESS(Status)) return Status;
- 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;
+ Console = Buff->Header.Console;
- /* Make sure WriteRegion is inside the screen buffer */
- ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
- if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
+ if (Buff == Console->ActiveBuffer)
{
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++)
+ /* If old buffer has no handles, it's now unreferenced */
+ if (Console->ActiveBuffer->Header.HandleCount == 0)
{
- 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 (WriteConsoleOutputRequest->Unicode)
- {
- ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
- }
- else
- {
- AsciiChar = CurCharInfo->Char.AsciiChar;
- }
- *Ptr++ = AsciiChar;
- *Ptr++ = CurCharInfo->Attributes;
- CurCharInfo++;
- }
+ ConioDeleteScreenBuffer(Console->ActiveBuffer);
}
- ConioDrawRegion(Console, &WriteRegion);
+ /* Tie console to new buffer */
+ Console->ActiveBuffer = Buff;
- ConioUnlockScreenBuffer(Buff);
+ /* Redraw the console */
+ ConioDrawConsole(Console);
- WriteConsoleOutputRequest->WriteRegion.Right = WriteRegion.Left + SizeX - 1;
- WriteConsoleOutputRequest->WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
- WriteConsoleOutputRequest->WriteRegion.Left = WriteRegion.Left;
- WriteConsoleOutputRequest->WriteRegion.Top = WriteRegion.Top;
+ ConioUnlockScreenBuffer(Buff);
return STATUS_SUCCESS;
}
DestinationOrigin = ScrollConsoleScreenBufferRequest->DestinationOrigin;
Fill = ScrollConsoleScreenBufferRequest->Fill;
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ConsoleHandle, &Buff, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ConsoleHandle, &Buff, GENERIC_WRITE);
+ if (!NT_SUCCESS(Status)) return Status;
+
Console = Buff->Header.Console;
ScrollRectangle = ScrollConsoleScreenBufferRequest->ScrollRectangle;
return STATUS_SUCCESS;
}
-CSR_API(CsrReadConsoleOutputChar)
-{
- NTSTATUS Status;
- PCSRSS_READ_CONSOLE_OUTPUT_CHAR ReadConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputCharRequest;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
- DWORD Xpos, Ypos;
- PCHAR ReadBuffer;
- DWORD i;
- ULONG CharSize;
- CHAR Char;
-
- DPRINT("CsrReadConsoleOutputChar\n");
-
- ReadBuffer = ReadConsoleOutputCharRequest->String;
-
- CharSize = (ReadConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ReadConsoleOutputCharRequest->ConsoleHandle, &Buff, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
-
- Xpos = ReadConsoleOutputCharRequest->ReadCoord.X;
- Ypos = (ReadConsoleOutputCharRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
-
- for (i = 0; i < ReadConsoleOutputCharRequest->NumCharsToRead; ++i)
- {
- Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)];
-
- if(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;
- ReadConsoleOutputCharRequest->EndCoord.X = Xpos;
- ReadConsoleOutputCharRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
-
- ConioUnlockScreenBuffer(Buff);
-
- ReadConsoleOutputCharRequest->CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadConsoleOutputCharRequest->String) / CharSize;
- if (ReadConsoleOutputCharRequest->CharsRead * CharSize + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) > sizeof(CSR_API_MESSAGE))
- {
- DPRINT1("Length won't fit in message\n");
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(CsrReadConsoleOutputAttrib)
-{
- NTSTATUS Status;
- PCSRSS_READ_CONSOLE_OUTPUT_ATTRIB ReadConsoleOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputAttribRequest;
- PCSRSS_SCREEN_BUFFER Buff;
- DWORD Xpos, Ypos;
- PWORD ReadBuffer;
- DWORD i;
- DWORD CurrentLength;
-
- DPRINT("CsrReadConsoleOutputAttrib\n");
-
- ReadBuffer = ReadConsoleOutputAttribRequest->Attribute;
-
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ReadConsoleOutputAttribRequest->ConsoleHandle, &Buff, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Xpos = ReadConsoleOutputAttribRequest->ReadCoord.X;
- Ypos = (ReadConsoleOutputAttribRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
-
- for (i = 0; i < ReadConsoleOutputAttribRequest->NumAttrsToRead; ++i)
- {
- *ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX) + 1];
-
- ReadBuffer++;
- Xpos++;
-
- if (Xpos == Buff->MaxX)
- {
- Xpos = 0;
- Ypos++;
-
- if (Ypos == Buff->MaxY)
- {
- Ypos = 0;
- }
- }
- }
-
- *ReadBuffer = 0;
-
- ReadConsoleOutputAttribRequest->EndCoord.X = Xpos;
- ReadConsoleOutputAttribRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
-
- ConioUnlockScreenBuffer(Buff);
-
- CurrentLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB)
- + ReadConsoleOutputAttribRequest->NumAttrsToRead * sizeof(WORD);
- if (CurrentLength > sizeof(CSR_API_MESSAGE))
- {
- DPRINT1("Length won't fit in message\n");
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- return STATUS_SUCCESS;
-}
-
-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(SrvSetConsoleScreenBufferSize)
{
NTSTATUS Status;
PCSRSS_SET_SCREEN_BUFFER_SIZE SetScreenBufferSize = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferSize;
- PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
- Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetScreenBufferSize->OutputHandle, &Buff, GENERIC_WRITE);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- Console = Buff->Header.Console;
+ Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetScreenBufferSize->OutputHandle, &Buff, GENERIC_WRITE);
+ if (!NT_SUCCESS(Status)) return Status;
- Status = ConioResizeBuffer(Console, Buff, SetScreenBufferSize->Size);
+ Status = ConioResizeBuffer(Buff->Header.Console, Buff, SetScreenBufferSize->Size);
ConioUnlockScreenBuffer(Buff);
return Status;