NTSTATUS NTAPI
ConDrvReadConsole(IN PCONSOLE Console,
IN PCONSOLE_INPUT_BUFFER InputBuffer,
+ /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/
IN BOOLEAN Unicode,
OUT PVOID Buffer,
IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
CONSOLE_READCONSOLE_CONTROL ReadControl;
+ UNICODE_STRING ExeName;
+
+ PVOID Buffer;
+ ULONG NrCharactersRead = 0;
+ ULONG CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
+
+ /* Compute the executable name, if needed */
+ if (ReadConsoleRequest->InitialNumBytes == 0 &&
+ ReadConsoleRequest->ExeLength <= sizeof(ReadConsoleRequest->StaticBuffer))
+ {
+ ExeName.Length = ExeName.MaximumLength = ReadConsoleRequest->ExeLength;
+ ExeName.Buffer = (PWCHAR)ReadConsoleRequest->StaticBuffer;
+ }
+ else
+ {
+ ExeName.Length = ExeName.MaximumLength = 0;
+ ExeName.Buffer = NULL;
+ }
+
+ /* Build the ReadControl structure */
ReadControl.nLength = sizeof(CONSOLE_READCONSOLE_CONTROL);
- ReadControl.nInitialChars = ReadConsoleRequest->NrCharactersRead;
+ ReadControl.nInitialChars = ReadConsoleRequest->InitialNumBytes / CharSize;
ReadControl.dwCtrlWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
ReadControl.dwControlKeyState = ReadConsoleRequest->ControlKeyState;
+ /*
+ * For optimization purposes, Windows (and hence ReactOS, too, for
+ * compatibility reasons) uses a static buffer if no more than eighty
+ * bytes are read. Otherwise a new buffer is used.
+ * The client-side expects that we know this behaviour.
+ */
+ if (ReadConsoleRequest->CaptureBufferSize <= sizeof(ReadConsoleRequest->StaticBuffer))
+ {
+ /*
+ * Adjust the internal pointer, because its old value points to
+ * the static buffer in the original ApiMessage structure.
+ */
+ // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
+ Buffer = ReadConsoleRequest->StaticBuffer;
+ }
+ else
+ {
+ Buffer = ReadConsoleRequest->Buffer;
+ }
+
+ DPRINT1("Calling ConDrvReadConsole(%wZ)\n", &ExeName);
Status = ConDrvReadConsole(InputBuffer->Header.Console,
InputBuffer,
+ &ExeName,
ReadConsoleRequest->Unicode,
- ReadConsoleRequest->Buffer,
+ Buffer,
&ReadControl,
- ReadConsoleRequest->NrCharactersToRead,
- &ReadConsoleRequest->NrCharactersRead);
+ ReadConsoleRequest->NumBytes / CharSize, // NrCharactersToRead
+ &NrCharactersRead);
+ DPRINT1("ConDrvReadConsole returned (%d ; Status = 0x%08x)\n",
+ NrCharactersRead, Status);
- ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
+ // ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
if (Status == STATUS_PENDING)
{
}
else
{
- /* We read all what we wanted, we return the error code we were given */
+ /*
+ * We read all what we wanted. Set the number of bytes read and
+ * return the error code we were given.
+ */
+ ReadConsoleRequest->NumBytes = NrCharactersRead * CharSize;
+ ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
+
return Status;
// return STATUS_SUCCESS;
}
}
else
{
- /* We read all what we wanted, we return the error code we were given */
+ /*
+ * We read all what we wanted. Set the number of events read and
+ * return the error code we were given.
+ */
GetInputRequest->NumRecords = NumEventsRead;
+
return Status;
// return STATUS_SUCCESS;
}
DPRINT("SrvReadConsole\n");
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&ReadConsoleRequest->Buffer,
- ReadConsoleRequest->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 read. Otherwise a new buffer is used.
+ * The client-side expects that we know this behaviour.
+ */
+ if (ReadConsoleRequest->CaptureBufferSize <= sizeof(ReadConsoleRequest->StaticBuffer))
{
- return STATUS_INVALID_PARAMETER;
+ /*
+ * Adjust the internal pointer, because its old value points to
+ * the static buffer in the original ApiMessage structure.
+ */
+ // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
+ }
+ else
+ {
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&ReadConsoleRequest->Buffer,
+ ReadConsoleRequest->CaptureBufferSize,
+ sizeof(BYTE)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
}
- if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
+ if (ReadConsoleRequest->InitialNumBytes > ReadConsoleRequest->NumBytes)
{
return STATUS_INVALID_PARAMETER;
}
Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- // This member is set by the caller (IntReadConsole in kernel32)
- // ReadConsoleRequest->NrCharactersRead = 0;
-
InputInfo.CallingThread = CsrGetClientThread();
InputInfo.HandleEntry = HandleEntry;
InputInfo.InputBuffer = InputBuffer;
Status = ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
WriteInputRequest->InputHandle,
&InputBuffer, GENERIC_WRITE, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status))
+ {
+ WriteInputRequest->NumRecords = 0;
+ return Status;
+ }
NumEventsWritten = 0;
Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,