PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
PTEXTMODE_SCREEN_BUFFER ScreenBuffer;
+ PVOID Buffer;
+ ULONG NrCharactersWritten = 0;
+ ULONG CharSize = (WriteConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
+
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process),
WriteConsoleRequest->OutputHandle,
&ScreenBuffer, GENERIC_WRITE, FALSE);
if (!NT_SUCCESS(Status)) return Status;
+ /*
+ * For optimization purposes, Windows (and hence ReactOS, too, for
+ * compatibility reasons) uses a static buffer if no more than eighty
+ * bytes are written. Otherwise a new buffer is used.
+ * The client-side expects that we know this behaviour.
+ */
+ if (WriteConsoleRequest->UsingStaticBuffer &&
+ WriteConsoleRequest->NumBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
+ {
+ /*
+ * Adjust the internal pointer, because its old value points to
+ * the static buffer in the original ApiMessage structure.
+ */
+ // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
+ Buffer = WriteConsoleRequest->StaticBuffer;
+ }
+ else
+ {
+ Buffer = WriteConsoleRequest->Buffer;
+ }
+
+ DPRINT("Calling ConDrvWriteConsole\n");
Status = ConDrvWriteConsole(ScreenBuffer->Header.Console,
ScreenBuffer,
WriteConsoleRequest->Unicode,
- WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- &WriteConsoleRequest->NrCharactersWritten);
+ Buffer,
+ WriteConsoleRequest->NumBytes / CharSize, // NrCharactersToWrite
+ &NrCharactersWritten);
+ DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n",
+ NrCharactersWritten, Status);
if (Status == STATUS_PENDING)
{
/* Wait until we un-pause the console */
// Status = STATUS_PENDING;
}
+ else
+ {
+ /* We read all what we wanted. Set the number of bytes written. */
+ WriteConsoleRequest->NumBytes = NrCharactersWritten * CharSize;
+ }
Quit:
ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE);
IN PTEXTMODE_SCREEN_BUFFER Buffer,
IN BOOLEAN Unicode,
OUT PCHAR_INFO CharInfo/*Buffer*/,
- IN PCOORD BufferSize,
- IN PCOORD BufferCoord,
IN OUT PSMALL_RECT ReadRegion);
CSR_API(SrvReadConsoleOutput)
{
PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest;
PTEXTMODE_SCREEN_BUFFER Buffer;
+ ULONG NumCells;
+ PCHAR_INFO CharInfo;
+
DPRINT("SrvReadConsoleOutput\n");
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&ReadOutputRequest->CharInfo,
- ReadOutputRequest->BufferSize.X * ReadOutputRequest->BufferSize.Y,
- sizeof(CHAR_INFO)))
+ /*
+ * For optimization purposes, Windows (and hence ReactOS, too, for
+ * compatibility reasons) uses a static buffer if no more than one
+ * cell is read. Otherwise a new buffer is used.
+ * The client-side expects that we know this behaviour.
+ */
+ NumCells = (ReadOutputRequest->ReadRegion.Right - ReadOutputRequest->ReadRegion.Left + 1) *
+ (ReadOutputRequest->ReadRegion.Bottom - ReadOutputRequest->ReadRegion.Top + 1);
+
+ if (NumCells <= 1)
{
- return STATUS_INVALID_PARAMETER;
+ /*
+ * Adjust the internal pointer, because its old value points to
+ * the static buffer in the original ApiMessage structure.
+ */
+ // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
+ CharInfo = &ReadOutputRequest->StaticBuffer;
+ }
+ else
+ {
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&ReadOutputRequest->CharInfo,
+ NumCells,
+ sizeof(CHAR_INFO)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ CharInfo = ReadOutputRequest->CharInfo;
}
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
Status = ConDrvReadConsoleOutput(Buffer->Header.Console,
Buffer,
ReadOutputRequest->Unicode,
- ReadOutputRequest->CharInfo,
- &ReadOutputRequest->BufferSize,
- &ReadOutputRequest->BufferCoord,
+ CharInfo,
&ReadOutputRequest->ReadRegion);
ConSrvReleaseScreenBuffer(Buffer, TRUE);
IN PTEXTMODE_SCREEN_BUFFER Buffer,
IN BOOLEAN Unicode,
IN PCHAR_INFO CharInfo/*Buffer*/,
- IN PCOORD BufferSize,
- IN PCOORD BufferCoord,
IN OUT PSMALL_RECT WriteRegion);
CSR_API(SrvWriteConsoleOutput)
{
PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest;
PTEXTMODE_SCREEN_BUFFER Buffer;
+ ULONG NumCells;
+ PCHAR_INFO CharInfo;
+
DPRINT("SrvWriteConsoleOutput\n");
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&WriteOutputRequest->CharInfo,
- WriteOutputRequest->BufferSize.X * WriteOutputRequest->BufferSize.Y,
- sizeof(CHAR_INFO)))
+ /*
+ * For optimization purposes, Windows (and hence ReactOS, too, for
+ * compatibility reasons) uses a static buffer if no more than one
+ * cell is written. Otherwise a new buffer is used.
+ * The client-side expects that we know this behaviour.
+ */
+ NumCells = (WriteOutputRequest->WriteRegion.Right - WriteOutputRequest->WriteRegion.Left + 1) *
+ (WriteOutputRequest->WriteRegion.Bottom - WriteOutputRequest->WriteRegion.Top + 1);
+
+ if (NumCells <= 1)
{
- return STATUS_INVALID_PARAMETER;
+ /*
+ * Adjust the internal pointer, because its old value points to
+ * the static buffer in the original ApiMessage structure.
+ */
+ // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
+ CharInfo = &WriteOutputRequest->StaticBuffer;
+ }
+ else
+ {
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&WriteOutputRequest->CharInfo,
+ NumCells,
+ sizeof(CHAR_INFO)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ CharInfo = WriteOutputRequest->CharInfo;
}
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
Status = ConDrvWriteConsoleOutput(Buffer->Header.Console,
Buffer,
WriteOutputRequest->Unicode,
- WriteOutputRequest->CharInfo,
- &WriteOutputRequest->BufferSize,
- &WriteOutputRequest->BufferCoord,
+ CharInfo,
&WriteOutputRequest->WriteRegion);
ConSrvReleaseScreenBuffer(Buffer, TRUE);
DPRINT("SrvWriteConsole\n");
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID)&WriteConsoleRequest->Buffer,
- WriteConsoleRequest->BufferSize,
- sizeof(BYTE)))
+ /*
+ * For optimization purposes, Windows (and hence ReactOS, too, for
+ * compatibility reasons) uses a static buffer if no more than eighty
+ * bytes are written. Otherwise a new buffer is used.
+ * The client-side expects that we know this behaviour.
+ */
+ if (WriteConsoleRequest->UsingStaticBuffer &&
+ WriteConsoleRequest->NumBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
{
- return STATUS_INVALID_PARAMETER;
+ /*
+ * Adjust the internal pointer, because its old value points to
+ * the static buffer in the original ApiMessage structure.
+ */
+ // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
+ }
+ else
+ {
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID)&WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NumBytes,
+ sizeof(BYTE)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
}
Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE);
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
ReadOutputCodeRequest->OutputHandle,
&Buffer, GENERIC_READ, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status))
+ {
+ ReadOutputCodeRequest->NumCodes = 0;
+ return Status;
+ }
Status = ConDrvReadConsoleOutputString(Buffer->Header.Console,
Buffer,
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
WriteOutputCodeRequest->OutputHandle,
&Buffer, GENERIC_WRITE, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status))
+ {
+ WriteOutputCodeRequest->NumCodes = 0;
+ return Status;
+ }
Status = ConDrvWriteConsoleOutputString(Buffer->Header.Console,
Buffer,
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
FillOutputRequest->OutputHandle,
&Buffer, GENERIC_WRITE, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status))
+ {
+ FillOutputRequest->NumCodes = 0;
+ return Status;
+ }
Status = ConDrvFillConsoleOutput(Buffer->Header.Console,
Buffer,