* Read functions *
******************/
+DWORD
+WINAPI
+GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer);
+
static
BOOL
-IntReadConsole(HANDLE hConsoleInput,
- PVOID lpBuffer,
- DWORD nNumberOfCharsToRead,
- LPDWORD lpNumberOfCharsRead,
- PCONSOLE_READCONSOLE_CONTROL pInputControl,
- BOOL bUnicode)
+IntReadConsole(IN HANDLE hConsoleInput,
+ OUT PVOID lpBuffer,
+ IN DWORD nNumberOfCharsToRead,
+ OUT LPDWORD lpNumberOfCharsRead,
+ IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL,
+ IN BOOLEAN bUnicode)
{
+ BOOL Success;
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_READCONSOLE ReadConsoleRequest = &ApiMessage.Data.ReadConsoleRequest;
- PCSR_CAPTURE_BUFFER CaptureBuffer;
- ULONG CharSize;
+ PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+ ULONG CharSize, SizeBytes;
+
+ DPRINT("IntReadConsole\n");
+
+ /* Set up the data to send to the Console Server */
+ ReadConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+ ReadConsoleRequest->InputHandle = hConsoleInput;
+ ReadConsoleRequest->Unicode = bUnicode;
+
+ /*
+ * Retrieve the current console executable name string and length (always
+ * in UNICODE format).
+ * FIXME: Do not use GetConsoleInputExeNameW but use something else...
+ */
+ // 1- Get the exe name length in characters, including NULL character.
+ ReadConsoleRequest->ExeLength =
+ GetConsoleInputExeNameW(0, (PWCHAR)ReadConsoleRequest->StaticBuffer);
+ // 2- Get the exe name (GetConsoleInputExeNameW returns 1 in case of success).
+ if (GetConsoleInputExeNameW(ReadConsoleRequest->ExeLength,
+ (PWCHAR)ReadConsoleRequest->StaticBuffer) != 1)
+ {
+ // Nothing
+ ReadConsoleRequest->ExeLength = 0;
+ }
+ else
+ {
+ // Remove the NULL character, and convert in number of bytes.
+ ReadConsoleRequest->ExeLength--;
+ ReadConsoleRequest->ExeLength *= sizeof(WCHAR);
+ }
+
+ /*** For DEBUGGING purposes ***/
+ {
+ UNICODE_STRING ExeName;
+ ExeName.Length = ExeName.MaximumLength = ReadConsoleRequest->ExeLength;
+ ExeName.Buffer = (PWCHAR)ReadConsoleRequest->StaticBuffer;
+ DPRINT1("IntReadConsole(ExeName = %wZ)\n", &ExeName);
+ }
+ /******************************/
/* Determine the needed size */
- CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
- ReadConsoleRequest->BufferSize = nNumberOfCharsToRead * CharSize;
+ CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+ SizeBytes = nNumberOfCharsToRead * CharSize;
- /* Allocate a Capture Buffer */
- CaptureBuffer = CsrAllocateCaptureBuffer(1, ReadConsoleRequest->BufferSize);
- if (CaptureBuffer == NULL)
+ ReadConsoleRequest->CaptureBufferSize =
+ ReadConsoleRequest->NumBytes = SizeBytes;
+
+ /*
+ * 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 allocated.
+ * This behaviour is also expected in the server-side.
+ */
+ if (SizeBytes <= sizeof(ReadConsoleRequest->StaticBuffer))
{
- DPRINT1("CsrAllocateCaptureBuffer failed!\n");
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
+ ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
+ // CaptureBuffer = NULL;
+ }
+ else
+ {
+ /* Allocate a Capture Buffer */
+ CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
+ if (CaptureBuffer == NULL)
+ {
+ DPRINT1("CsrAllocateCaptureBuffer failed!\n");
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ /* Allocate space in the Buffer */
+ CsrAllocateMessagePointer(CaptureBuffer,
+ SizeBytes,
+ (PVOID*)&ReadConsoleRequest->Buffer);
}
- /* Allocate space in the Buffer */
- CsrAllocateMessagePointer(CaptureBuffer,
- ReadConsoleRequest->BufferSize,
- (PVOID*)&ReadConsoleRequest->Buffer);
+ ReadConsoleRequest->InitialNumBytes = 0;
+ ReadConsoleRequest->CtrlWakeupMask = 0;
+ ReadConsoleRequest->ControlKeyState = 0;
- /* Set up the data to send to the Console Server */
- ReadConsoleRequest->InputHandle = hConsoleInput;
- ReadConsoleRequest->Unicode = bUnicode;
- ReadConsoleRequest->NrCharactersToRead = nNumberOfCharsToRead;
- ReadConsoleRequest->NrCharactersRead = 0;
- ReadConsoleRequest->CtrlWakeupMask = 0;
- if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
+ /*
+ * From MSDN (ReadConsole function), the description
+ * for pInputControl says:
+ * "This parameter requires Unicode input by default.
+ * For ANSI mode, set this parameter to NULL."
+ */
+ if (bUnicode && pInputControl &&
+ pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
+ {
+ /* Sanity check */
+ if (pInputControl->nInitialChars <= nNumberOfCharsToRead)
+ {
+ ReadConsoleRequest->InitialNumBytes =
+ pInputControl->nInitialChars * sizeof(WCHAR); // CharSize
+
+ if (pInputControl->nInitialChars != 0)
+ {
+ /*
+ * It is possible here to overwrite the static buffer, in case
+ * the number of bytes to read was smaller than the static buffer.
+ * In this case, this means we are continuing a pending read,
+ * and we do not need in fact the executable name that was
+ * stored in the static buffer because it was first grabbed when
+ * we started the first read.
+ */
+ RtlCopyMemory(ReadConsoleRequest->Buffer,
+ lpBuffer,
+ ReadConsoleRequest->InitialNumBytes);
+ }
+
+ ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask;
+ }
+ else
+ {
+ // Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ else
{
- /*
- * From MSDN (ReadConsole function), the description
- * for pInputControl says:
- * "This parameter requires Unicode input by default.
- * For ANSI mode, set this parameter to NULL."
- */
- ReadConsoleRequest->NrCharactersRead = pInputControl->nInitialChars;
- RtlCopyMemory(ReadConsoleRequest->Buffer,
- lpBuffer,
- pInputControl->nInitialChars * sizeof(WCHAR));
- ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask;
+ /* We are in a situation where pInputControl has no meaning */
+ pInputControl = NULL;
}
+ /* Check for sanity */
+/*
+ if (!NT_SUCCESS(Status) && pInputControl)
+ {
+ // Free CaptureBuffer if needed
+ // Set last error to last status
+ // Return FALSE
+ }
+*/
+
/* Call the server */
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
CaptureBuffer,
sizeof(*ReadConsoleRequest));
/* Check for success */
- if (NT_SUCCESS(ApiMessage.Status))
+ Success = NT_SUCCESS(ApiMessage.Status);
+
+ /* Retrieve the results */
+ if (Success)
{
- RtlCopyMemory(lpBuffer,
- ReadConsoleRequest->Buffer,
- ReadConsoleRequest->NrCharactersRead * CharSize);
+ _SEH2_TRY
+ {
+ *lpNumberOfCharsRead = ReadConsoleRequest->NumBytes / CharSize;
- if (lpNumberOfCharsRead != NULL)
- *lpNumberOfCharsRead = ReadConsoleRequest->NrCharactersRead;
+ if (bUnicode && pInputControl)
+ pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState;
- if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
- pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState;
+ RtlCopyMemory(lpBuffer,
+ ReadConsoleRequest->Buffer,
+ ReadConsoleRequest->NumBytes);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastError(ERROR_INVALID_ACCESS);
+ Success = FALSE;
+ }
+ _SEH2_END;
}
else
{
- DPRINT1("CSR returned error in ReadConsole\n");
-
- if (lpNumberOfCharsRead != NULL)
- *lpNumberOfCharsRead = 0;
-
- /* Error out */
BaseSetLastNTError(ApiMessage.Status);
}
- CsrFreeCaptureBuffer(CaptureBuffer);
+ /* Release the capture buffer if needed */
+ if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
- /* Return TRUE or FALSE */
- // return TRUE;
- return (ReadConsoleRequest->NrCharactersRead > 0);
- // return NT_SUCCESS(ApiMessage.Status);
+ if (Success)
+ {
+ /* Yield execution to another thread if Ctrl-C or Ctrl-Break happened */
+ if (ApiMessage.Status == STATUS_ALERTED /* || ApiMessage.Status == STATUS_CANCELLED */)
+ {
+ NtYieldExecution();
+ SetLastError(ERROR_OPERATION_ABORTED); // STATUS_CANCELLED
+ }
+ }
+
+ /* Return success status */
+ return Success;
}
static
BOOL
-IntReadConsoleOutput(HANDLE hConsoleOutput,
- PCHAR_INFO lpBuffer,
- COORD dwBufferSize,
- COORD dwBufferCoord,
- PSMALL_RECT lpReadRegion,
- BOOL bUnicode)
+IntReadConsoleOutput(IN HANDLE hConsoleOutput,
+ OUT PCHAR_INFO lpBuffer,
+ IN COORD dwBufferSize,
+ IN COORD dwBufferCoord,
+ IN OUT PSMALL_RECT lpReadRegion,
+ IN BOOLEAN bUnicode)
{
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_READOUTPUT ReadOutputRequest = &ApiMessage.Data.ReadOutputRequest;
}
else
{
- /* Error out */
BaseSetLastNTError(ApiMessage.Status);
}
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest;
PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
- ULONG SizeBytes, CodeSize;
+ ULONG CodeSize, SizeBytes;
DPRINT("IntReadConsoleOutputCode\n");
static
BOOL
-IntWriteConsole(HANDLE hConsoleOutput,
- PVOID lpBuffer,
- DWORD nNumberOfCharsToWrite,
- LPDWORD lpNumberOfCharsWritten,
+IntWriteConsole(IN HANDLE hConsoleOutput,
+ IN PVOID lpBuffer,
+ IN DWORD nNumberOfCharsToWrite,
+ OUT LPDWORD lpNumberOfCharsWritten,
LPVOID lpReserved,
- BOOL bUnicode)
+ IN BOOLEAN bUnicode)
{
- BOOL bRet = TRUE;
+ BOOL Success;
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_WRITECONSOLE WriteConsoleRequest = &ApiMessage.Data.WriteConsoleRequest;
- PCSR_CAPTURE_BUFFER CaptureBuffer;
- ULONG CharSize;
+ PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+ ULONG CharSize, SizeBytes;
+
+ DPRINT("IntWriteConsole\n");
+
+ /* Set up the data to send to the Console Server */
+ WriteConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+ WriteConsoleRequest->OutputHandle = hConsoleOutput;
+ WriteConsoleRequest->Unicode = bUnicode;
+
+ /* Those members are unused by the client, on Windows */
+ WriteConsoleRequest->Reserved1 = 0;
+ // WriteConsoleRequest->Reserved2 = {0};
/* Determine the needed size */
- CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
- WriteConsoleRequest->BufferSize = nNumberOfCharsToWrite * CharSize;
+ CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+ SizeBytes = nNumberOfCharsToWrite * CharSize;
- /* Allocate a Capture Buffer */
- CaptureBuffer = CsrAllocateCaptureBuffer(1, WriteConsoleRequest->BufferSize);
- if (CaptureBuffer == NULL)
+ WriteConsoleRequest->NumBytes = SizeBytes;
+
+ /*
+ * 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 allocated.
+ * This behaviour is also expected in the server-side.
+ */
+ if (SizeBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
{
- DPRINT1("CsrAllocateCaptureBuffer failed!\n");
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
+ WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
+ // CaptureBuffer = NULL;
+ WriteConsoleRequest->UsingStaticBuffer = TRUE;
- /* Capture the buffer to write */
- CsrCaptureMessageBuffer(CaptureBuffer,
- (PVOID)lpBuffer,
- WriteConsoleRequest->BufferSize,
- (PVOID*)&WriteConsoleRequest->Buffer);
+ _SEH2_TRY
+ {
+ RtlCopyMemory(WriteConsoleRequest->Buffer,
+ lpBuffer,
+ SizeBytes);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastError(ERROR_INVALID_ACCESS);
+ return FALSE;
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ /* Allocate a Capture Buffer */
+ CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
+ if (CaptureBuffer == NULL)
+ {
+ DPRINT1("CsrAllocateCaptureBuffer failed!\n");
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
- /* Start writing */
- WriteConsoleRequest->NrCharactersToWrite = nNumberOfCharsToWrite;
- WriteConsoleRequest->OutputHandle = hConsoleOutput;
- WriteConsoleRequest->Unicode = bUnicode;
+ /* Capture the buffer to write */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ (PVOID)lpBuffer,
+ SizeBytes,
+ (PVOID*)&WriteConsoleRequest->Buffer);
+ WriteConsoleRequest->UsingStaticBuffer = FALSE;
+ }
/* Call the server */
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
sizeof(*WriteConsoleRequest));
/* Check for success */
- if (NT_SUCCESS(ApiMessage.Status))
- {
- if (lpNumberOfCharsWritten != NULL)
- *lpNumberOfCharsWritten = WriteConsoleRequest->NrCharactersWritten;
+ Success = NT_SUCCESS(ApiMessage.Status);
+
+ /* Release the capture buffer if needed */
+ if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
- bRet = TRUE;
+ /* Retrieve the results */
+ if (Success)
+ {
+ _SEH2_TRY
+ {
+ *lpNumberOfCharsWritten = WriteConsoleRequest->NumBytes / CharSize;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastError(ERROR_INVALID_ACCESS);
+ Success = FALSE;
+ }
+ _SEH2_END;
}
else
{
- if (lpNumberOfCharsWritten != NULL)
- *lpNumberOfCharsWritten = 0;
-
- /* Error out */
BaseSetLastNTError(ApiMessage.Status);
- bRet = FALSE;
}
- CsrFreeCaptureBuffer(CaptureBuffer);
-
- return bRet;
+ /* Return success status */
+ return Success;
}
static
BOOL
-IntWriteConsoleOutput(HANDLE hConsoleOutput,
- CONST CHAR_INFO *lpBuffer,
- COORD dwBufferSize,
- COORD dwBufferCoord,
- PSMALL_RECT lpWriteRegion,
- BOOL bUnicode)
+IntWriteConsoleOutput(IN HANDLE hConsoleOutput,
+ IN CONST CHAR_INFO *lpBuffer,
+ IN COORD dwBufferSize,
+ IN COORD dwBufferCoord,
+ IN OUT PSMALL_RECT lpWriteRegion,
+ IN BOOLEAN bUnicode)
{
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest;
/* Check for success */
if (!NT_SUCCESS(ApiMessage.Status))
{
- /* Error out */
BaseSetLastNTError(ApiMessage.Status);
}
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest;
PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
- ULONG SizeBytes, CodeSize;
+ ULONG CodeSize, SizeBytes;
if ( (CodeType != CODE_ASCII ) &&
(CodeType != CODE_UNICODE ) &&
*/
BOOL
WINAPI
-ReadConsoleW(HANDLE hConsoleInput,
- LPVOID lpBuffer,
- DWORD nNumberOfCharsToRead,
- LPDWORD lpNumberOfCharsRead,
- PCONSOLE_READCONSOLE_CONTROL pInputControl)
+ReadConsoleW(IN HANDLE hConsoleInput,
+ OUT LPVOID lpBuffer,
+ IN DWORD nNumberOfCharsToRead,
+ OUT LPDWORD lpNumberOfCharsRead,
+ IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
{
return IntReadConsole(hConsoleInput,
lpBuffer,
*/
BOOL
WINAPI
-ReadConsoleA(HANDLE hConsoleInput,
- LPVOID lpBuffer,
- DWORD nNumberOfCharsToRead,
- LPDWORD lpNumberOfCharsRead,
- PCONSOLE_READCONSOLE_CONTROL pInputControl)
+ReadConsoleA(IN HANDLE hConsoleInput,
+ OUT LPVOID lpBuffer,
+ IN DWORD nNumberOfCharsToRead,
+ OUT LPDWORD lpNumberOfCharsRead,
+ IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
{
return IntReadConsole(hConsoleInput,
lpBuffer,
*/
BOOL
WINAPI
-ReadConsoleOutputW(HANDLE hConsoleOutput,
- PCHAR_INFO lpBuffer,
- COORD dwBufferSize,
- COORD dwBufferCoord,
- PSMALL_RECT lpReadRegion)
+ReadConsoleOutputW(IN HANDLE hConsoleOutput,
+ OUT PCHAR_INFO lpBuffer,
+ IN COORD dwBufferSize,
+ IN COORD dwBufferCoord,
+ IN OUT PSMALL_RECT lpReadRegion)
{
return IntReadConsoleOutput(hConsoleOutput,
lpBuffer,
*/
BOOL
WINAPI
-ReadConsoleOutputA(HANDLE hConsoleOutput,
- PCHAR_INFO lpBuffer,
- COORD dwBufferSize,
- COORD dwBufferCoord,
- PSMALL_RECT lpReadRegion)
+ReadConsoleOutputA(IN HANDLE hConsoleOutput,
+ OUT PCHAR_INFO lpBuffer,
+ IN COORD dwBufferSize,
+ IN COORD dwBufferCoord,
+ IN OUT PSMALL_RECT lpReadRegion)
{
return IntReadConsoleOutput(hConsoleOutput,
lpBuffer,
*/
BOOL
WINAPI
-WriteConsoleW(HANDLE hConsoleOutput,
- CONST VOID *lpBuffer,
- DWORD nNumberOfCharsToWrite,
- LPDWORD lpNumberOfCharsWritten,
+WriteConsoleW(IN HANDLE hConsoleOutput,
+ IN CONST VOID *lpBuffer,
+ IN DWORD nNumberOfCharsToWrite,
+ OUT LPDWORD lpNumberOfCharsWritten,
LPVOID lpReserved)
{
return IntWriteConsole(hConsoleOutput,
*/
BOOL
WINAPI
-WriteConsoleA(HANDLE hConsoleOutput,
- CONST VOID *lpBuffer,
- DWORD nNumberOfCharsToWrite,
- LPDWORD lpNumberOfCharsWritten,
+WriteConsoleA(IN HANDLE hConsoleOutput,
+ IN CONST VOID *lpBuffer,
+ IN DWORD nNumberOfCharsToWrite,
+ OUT LPDWORD lpNumberOfCharsWritten,
LPVOID lpReserved)
{
return IntWriteConsole(hConsoleOutput,
*/
BOOL
WINAPI
-WriteConsoleOutputW(HANDLE hConsoleOutput,
- CONST CHAR_INFO *lpBuffer,
- COORD dwBufferSize,
- COORD dwBufferCoord,
- PSMALL_RECT lpWriteRegion)
+WriteConsoleOutputW(IN HANDLE hConsoleOutput,
+ IN CONST CHAR_INFO *lpBuffer,
+ IN COORD dwBufferSize,
+ IN COORD dwBufferCoord,
+ IN OUT PSMALL_RECT lpWriteRegion)
{
return IntWriteConsoleOutput(hConsoleOutput,
lpBuffer,
*/
BOOL
WINAPI
-WriteConsoleOutputA(HANDLE hConsoleOutput,
- CONST CHAR_INFO *lpBuffer,
- COORD dwBufferSize,
- COORD dwBufferCoord,
- PSMALL_RECT lpWriteRegion)
+WriteConsoleOutputA(IN HANDLE hConsoleOutput,
+ IN CONST CHAR_INFO *lpBuffer,
+ IN COORD dwBufferSize,
+ IN COORD dwBufferCoord,
+ IN OUT PSMALL_RECT lpWriteRegion)
{
return IntWriteConsoleOutput(hConsoleOutput,
lpBuffer,