Author: hbelusca
Date: Fri Aug 1 18:08:29 2014
New Revision: 63793
URL:
http://svn.reactos.org/svn/reactos?rev=63793&view=rev
Log:
[KERNEL32][CONSRV]
- Make kernel32 / winsrv console CSR structures Win2k3-compliant for Read/WriteConsole
functions.
An attentive code reader will see that there are structure members in
CONSOLE_WRITECONSOLE that are
indeed unused by kernel32 that can be used in ReactOS for undocumented extensions of
WriteConsole...
(for instance, adding a parameter for ANSI codes support, who knows!... :P)
- Fix a bit the support for the CONSOLE_READCONSOLE_CONTROL parameter in ReadConsole (for
unicode only).
- Use the actual exe name for command history management, given via a hackish way by
ReadConsole:
the exe name is passed via the 80-byte-length limited static buffer, and is of course
retrieved before
actually using the static buffer (if needed).
[CONSRV]
- Fix writing input events in the console, but first preprocessing them for pausing
commands (we treat them separately and remove them),
then, in case we write many single events, we merge them in case they are mouse moves or
repeated key down presses. This helps in not
overflowing too quickly the input buffer, and that fixes all the remaining
kernel32:console winetests!! (see CORE-8256)
- Use the actual exe name for command history management, given via a hackish way by
ReadConsole (blame MS!)
Part 8/X
CORE-7931
CORE-8256 #resolve #comment Fixed in the condrv_restructure branch in revision .
Modified:
branches/condrv_restructure/dll/win32/kernel32/client/console/readwrite.c
branches/condrv_restructure/include/reactos/subsys/win/conmsg.h
branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/coninput.c
branches/condrv_restructure/win32ss/user/winsrv/consrv/coninput.c
branches/condrv_restructure/win32ss/user/winsrv/consrv/conoutput.c
branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h
branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h
branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.c
branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.h
Modified: branches/condrv_restructure/dll/win32/kernel32/client/console/readwrite.c
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/dll/win32/ke…
==============================================================================
--- branches/condrv_restructure/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1]
(original)
+++ branches/condrv_restructure/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1]
Fri Aug 1 18:08:29 2014
@@ -24,58 +24,154 @@
* 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;
-
- /* Allocate a Capture Buffer */
- CaptureBuffer = CsrAllocateCaptureBuffer(1, ReadConsoleRequest->BufferSize);
- if (CaptureBuffer == NULL)
- {
- DPRINT1("CsrAllocateCaptureBuffer failed!\n");
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
-
- /* Allocate space in the Buffer */
- CsrAllocateMessagePointer(CaptureBuffer,
- ReadConsoleRequest->BufferSize,
- (PVOID*)&ReadConsoleRequest->Buffer);
-
- /* 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."
- */
- ReadConsoleRequest->NrCharactersRead = pInputControl->nInitialChars;
- RtlCopyMemory(ReadConsoleRequest->Buffer,
- lpBuffer,
- pInputControl->nInitialChars * sizeof(WCHAR));
- ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask;
- }
+ CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+ SizeBytes = nNumberOfCharsToRead * CharSize;
+
+ 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))
+ {
+ 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);
+ }
+
+ ReadConsoleRequest->InitialNumBytes = 0;
+ ReadConsoleRequest->CtrlWakeupMask = 0;
+ ReadConsoleRequest->ControlKeyState = 0;
+
+ /*
+ * 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
+ {
+ /* 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,
@@ -84,35 +180,49 @@
sizeof(*ReadConsoleRequest));
/* Check for success */
- if (NT_SUCCESS(ApiMessage.Status))
- {
- RtlCopyMemory(lpBuffer,
- ReadConsoleRequest->Buffer,
- ReadConsoleRequest->NrCharactersRead * CharSize);
-
- if (lpNumberOfCharsRead != NULL)
- *lpNumberOfCharsRead = ReadConsoleRequest->NrCharactersRead;
-
- if (pInputControl && pInputControl->nLength ==
sizeof(CONSOLE_READCONSOLE_CONTROL))
- pInputControl->dwControlKeyState =
ReadConsoleRequest->ControlKeyState;
+ Success = NT_SUCCESS(ApiMessage.Status);
+
+ /* Retrieve the results */
+ if (Success)
+ {
+ _SEH2_TRY
+ {
+ *lpNumberOfCharsRead = ReadConsoleRequest->NumBytes / CharSize;
+
+ if (bUnicode && pInputControl)
+ 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);
-
- /* Return TRUE or FALSE */
- // return TRUE;
- return (ReadConsoleRequest->NrCharactersRead > 0);
- // return NT_SUCCESS(ApiMessage.Status);
+ /* Release the capture buffer if needed */
+ if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
+
+ 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;
}
@@ -228,12 +338,12 @@
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;
@@ -292,7 +402,6 @@
}
else
{
- /* Error out */
BaseSetLastNTError(ApiMessage.Status);
}
@@ -321,7 +430,7 @@
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest =
&ApiMessage.Data.ReadOutputCodeRequest;
PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
- ULONG SizeBytes, CodeSize;
+ ULONG CodeSize, SizeBytes;
DPRINT("IntReadConsoleOutputCode\n");
@@ -431,42 +540,79 @@
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)
-{
- BOOL bRet = TRUE;
+ IN BOOLEAN bUnicode)
+{
+ 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;
-
- /* Allocate a Capture Buffer */
- CaptureBuffer = CsrAllocateCaptureBuffer(1, WriteConsoleRequest->BufferSize);
- if (CaptureBuffer == NULL)
- {
- DPRINT1("CsrAllocateCaptureBuffer failed!\n");
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
-
- /* Capture the buffer to write */
- CsrCaptureMessageBuffer(CaptureBuffer,
- (PVOID)lpBuffer,
- WriteConsoleRequest->BufferSize,
- (PVOID*)&WriteConsoleRequest->Buffer);
-
- /* Start writing */
- WriteConsoleRequest->NrCharactersToWrite = nNumberOfCharsToWrite;
- WriteConsoleRequest->OutputHandle = hConsoleOutput;
- WriteConsoleRequest->Unicode = bUnicode;
+ CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+ SizeBytes = nNumberOfCharsToWrite * CharSize;
+
+ 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))
+ {
+ WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
+ // CaptureBuffer = NULL;
+ WriteConsoleRequest->UsingStaticBuffer = TRUE;
+
+ _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;
+ }
+
+ /* Capture the buffer to write */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ (PVOID)lpBuffer,
+ SizeBytes,
+ (PVOID*)&WriteConsoleRequest->Buffer);
+ WriteConsoleRequest->UsingStaticBuffer = FALSE;
+ }
/* Call the server */
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
@@ -475,26 +621,32 @@
sizeof(*WriteConsoleRequest));
/* Check for success */
- if (NT_SUCCESS(ApiMessage.Status))
- {
- if (lpNumberOfCharsWritten != NULL)
- *lpNumberOfCharsWritten = WriteConsoleRequest->NrCharactersWritten;
-
- bRet = TRUE;
+ Success = NT_SUCCESS(ApiMessage.Status);
+
+ /* Release the capture buffer if needed */
+ if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
+
+ /* 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;
}
@@ -600,12 +752,12 @@
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;
@@ -660,7 +812,6 @@
/* Check for success */
if (!NT_SUCCESS(ApiMessage.Status))
{
- /* Error out */
BaseSetLastNTError(ApiMessage.Status);
}
@@ -689,7 +840,7 @@
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 ) &&
@@ -872,11 +1023,11 @@
*/
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,
@@ -894,11 +1045,11 @@
*/
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,
@@ -1044,11 +1195,11 @@
*/
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,
@@ -1066,11 +1217,11 @@
*/
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,
@@ -1158,10 +1309,10 @@
*/
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,
@@ -1180,10 +1331,10 @@
*/
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,
@@ -1286,11 +1437,11 @@
*/
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,
@@ -1308,11 +1459,11 @@
*/
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,
Modified: branches/condrv_restructure/include/reactos/subsys/win/conmsg.h
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/include/reac…
==============================================================================
--- branches/condrv_restructure/include/reactos/subsys/win/conmsg.h [iso-8859-1]
(original)
+++ branches/condrv_restructure/include/reactos/subsys/win/conmsg.h [iso-8859-1] Fri Aug
1 18:08:29 2014
@@ -218,30 +218,40 @@
typedef struct
{
- HANDLE OutputHandle;
-
- BOOL Unicode;
- ULONG NrCharactersToWrite;
- ULONG NrCharactersWritten;
-
- ULONG BufferSize;
- PVOID Buffer;
+ HANDLE ConsoleHandle;
+ HANDLE OutputHandle;
+
+ CHAR StaticBuffer[80];
+ PVOID Buffer; // BufPtr
+ ULONG NumBytes;
+
+ // On Windows, the client never uses this member
+ ULONG Reserved1;
+
+ BOOLEAN UsingStaticBuffer;
+ BOOLEAN Unicode;
+
+ // On Windows, the client never uses this member
+ CHAR Reserved2[6];
} CONSOLE_WRITECONSOLE, *PCONSOLE_WRITECONSOLE;
typedef struct
{
+ HANDLE ConsoleHandle;
HANDLE InputHandle;
- BOOL Unicode;
- ULONG NrCharactersToRead;
- ULONG NrCharactersRead;
-
- UNICODE_STRING ExeName;
- DWORD CtrlWakeupMask;
- DWORD ControlKeyState;
-
- ULONG BufferSize;
- PVOID Buffer;
+ USHORT ExeLength;
+
+ CHAR StaticBuffer[80];
+ PVOID Buffer; // BufPtr
+ ULONG NumBytes;
+
+ ULONG CaptureBufferSize;
+
+ ULONG InitialNumBytes;
+ ULONG CtrlWakeupMask;
+ ULONG ControlKeyState;
+ BOOLEAN Unicode;
} CONSOLE_READCONSOLE, *PCONSOLE_READCONSOLE;
typedef struct
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/coninput.c
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user…
==============================================================================
--- branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/coninput.c [iso-8859-1]
(original)
+++ branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/coninput.c [iso-8859-1]
Fri Aug 1 18:08:29 2014
@@ -65,58 +65,75 @@
}
}
-NTSTATUS
-ConioAddInputEvent(PCONSOLE Console,
- PINPUT_RECORD InputEvent,
- BOOLEAN AppendToEnd)
-{
- ConsoleInput *ConInRec;
-
- /* Check for pause or unpause */
- if (InputEvent->EventType == KEY_EVENT &&
InputEvent->Event.KeyEvent.bKeyDown)
- {
- WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
- if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
- {
- DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState;
- if (Console->InputBuffer.Mode & ENABLE_LINE_INPUT &&
- (vk == VK_PAUSE || (vk == 'S' &&
- (cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
&&
- !(cks & (LEFT_ALT_PRESSED |
RIGHT_ALT_PRESSED)))))
- {
- ConioPause(Console, PAUSED_FROM_KEYBOARD);
- return STATUS_SUCCESS;
- }
- }
- else
- {
- if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN
&&
- vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL)
- {
- ConioUnpause(Console, PAUSED_FROM_KEYBOARD);
- return STATUS_SUCCESS;
- }
- }
- }
-
- /* Add event to the queue */
- ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput));
- if (ConInRec == NULL) return STATUS_INSUFFICIENT_RESOURCES;
-
- ConInRec->InputEvent = *InputEvent;
-
- if (AppendToEnd)
- {
- /* Append the event to the end of the queue */
- InsertTailList(&Console->InputBuffer.InputEvents,
&ConInRec->ListEntry);
- }
- else
- {
- /* Append the event to the beginning of the queue */
- InsertHeadList(&Console->InputBuffer.InputEvents,
&ConInRec->ListEntry);
- }
-
- SetEvent(Console->InputBuffer.ActiveEvent);
+
+/*
+ * This pre-processing code MUST be IN consrv ONLY
+ */
+static ULONG
+PreprocessInput(PCONSOLE Console,
+ PINPUT_RECORD InputEvent,
+ ULONG NumEventsToWrite)
+{
+ ULONG NumEvents;
+
+ /*
+ * Loop each event, and for each, check for pause or unpause
+ * and perform adequate behaviour.
+ */
+ for (NumEvents = NumEventsToWrite; NumEvents > 0; --NumEvents)
+ {
+ /* Check for pause or unpause */
+ if (InputEvent->EventType == KEY_EVENT &&
InputEvent->Event.KeyEvent.bKeyDown)
+ {
+ WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
+ if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
+ {
+ DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState;
+ if (Console->InputBuffer.Mode & ENABLE_LINE_INPUT &&
+ (vk == VK_PAUSE ||
+ (vk == 'S' && (cks & (LEFT_CTRL_PRESSED |
RIGHT_CTRL_PRESSED)) &&
+ !(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))))
+ {
+ ConioPause(Console, PAUSED_FROM_KEYBOARD);
+
+ /* Skip the event */
+ RtlMoveMemory(InputEvent,
+ InputEvent + 1,
+ (NumEvents - 1) * sizeof(INPUT_RECORD));
+ --NumEventsToWrite;
+ continue;
+ }
+ }
+ else
+ {
+ if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN
&&
+ vk != VK_RWIN && vk != VK_NUMLOCK && vk !=
VK_SCROLL)
+ {
+ ConioUnpause(Console, PAUSED_FROM_KEYBOARD);
+
+ /* Skip the event */
+ RtlMoveMemory(InputEvent,
+ InputEvent + 1,
+ (NumEvents - 1) * sizeof(INPUT_RECORD));
+ --NumEventsToWrite;
+ continue;
+ }
+ }
+ }
+
+ /* Go to the next event */
+ ++InputEvent;
+ }
+
+ return NumEventsToWrite;
+}
+
+/*
+ * This post-processing code MUST be IN consrv ONLY
+ */
+static VOID
+PostprocessInput(PCONSOLE Console)
+{
CsrNotifyWait(&Console->ReadWaitQueue,
FALSE,
NULL,
@@ -125,6 +142,170 @@
{
CsrDereferenceWait(&Console->ReadWaitQueue);
}
+}
+
+NTSTATUS
+ConioAddInputEvents(PCONSOLE Console,
+ PINPUT_RECORD InputRecords, // InputEvent
+ ULONG NumEventsToWrite,
+ PULONG NumEventsWritten,
+ BOOLEAN AppendToEnd)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG i = 0;
+ BOOLEAN SetWaitEvent = FALSE;
+
+ if (NumEventsWritten) *NumEventsWritten = 0;
+
+ /*
+ * This pre-processing code MUST be IN consrv ONLY!!
+ */
+ NumEventsToWrite = PreprocessInput(Console, InputRecords, NumEventsToWrite);
+ if (NumEventsToWrite == 0) return STATUS_SUCCESS;
+
+
+ /*
+ * When adding many single events, in the case of repeated mouse move or
+ * key down events, we try to coalesce them so that we do not saturate
+ * too quickly the input buffer.
+ */
+ if (NumEventsToWrite == 1 &&
!IsListEmpty(&Console->InputBuffer.InputEvents))
+ {
+ PINPUT_RECORD InputRecord = InputRecords; // Only one element
+ PINPUT_RECORD LastInputRecord;
+ ConsoleInput* ConInRec; // Input
+
+ /* Get the "next" event of the input buffer */
+ if (AppendToEnd)
+ {
+ /* Get the tail element */
+ ConInRec = CONTAINING_RECORD(Console->InputBuffer.InputEvents.Blink,
+ ConsoleInput, ListEntry);
+ }
+ else
+ {
+ /* Get the head element */
+ ConInRec = CONTAINING_RECORD(Console->InputBuffer.InputEvents.Flink,
+ ConsoleInput, ListEntry);
+ }
+ LastInputRecord = &ConInRec->InputEvent;
+
+ if (InputRecord->EventType == MOUSE_EVENT &&
+ InputRecord->Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
+ {
+ if (LastInputRecord->EventType == MOUSE_EVENT &&
+ LastInputRecord->Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
+ {
+ /* Update the mouse position */
+ LastInputRecord->Event.MouseEvent.dwMousePosition.X =
+ InputRecord->Event.MouseEvent.dwMousePosition.X;
+ LastInputRecord->Event.MouseEvent.dwMousePosition.Y =
+ InputRecord->Event.MouseEvent.dwMousePosition.Y;
+
+ i = 1;
+ // return STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else if (InputRecord->EventType == KEY_EVENT &&
+ InputRecord->Event.KeyEvent.bKeyDown)
+ {
+ if (LastInputRecord->EventType == KEY_EVENT &&
+ LastInputRecord->Event.KeyEvent.bKeyDown &&
+ (LastInputRecord->Event.KeyEvent.wVirtualScanCode == // Same
scancode
+ InputRecord->Event.KeyEvent.wVirtualScanCode) &&
+ (LastInputRecord->Event.KeyEvent.uChar.UnicodeChar == // Same
character
+ InputRecord->Event.KeyEvent.uChar.UnicodeChar) &&
+ (LastInputRecord->Event.KeyEvent.dwControlKeyState == // Same
Ctrl/Alt/Shift state
+ InputRecord->Event.KeyEvent.dwControlKeyState) )
+ {
+ /* Update the repeat count */
+ LastInputRecord->Event.KeyEvent.wRepeatCount +=
+ InputRecord->Event.KeyEvent.wRepeatCount;
+
+ i = 1;
+ // return STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
+ }
+ }
+ }
+
+ /* If we coalesced the only one element, we can quit */
+ if (i == 1 && Status == STATUS_SUCCESS /* && NumEventsToWrite == 1
*/)
+ goto Done;
+
+ /*
+ * No event coalesced, add them in the usual way.
+ */
+
+ if (AppendToEnd)
+ {
+ /* Go to the beginning of the list */
+ // InputRecords = InputRecords;
+ }
+ else
+ {
+ /* Go to the end of the list */
+ InputRecords = &InputRecords[NumEventsToWrite - 1];
+ }
+
+ /* Set the event if the list is going to be non-empty */
+ if (IsListEmpty(&Console->InputBuffer.InputEvents))
+ SetWaitEvent = TRUE;
+
+ for (i = 0; i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
+ {
+ PINPUT_RECORD InputRecord;
+ ConsoleInput* ConInRec;
+
+ if (AppendToEnd)
+ {
+ /* Select the event and go to the next one */
+ InputRecord = InputRecords++;
+ }
+ else
+ {
+ /* Select the event and go to the previous one */
+ InputRecord = InputRecords--;
+ }
+
+ /* Add event to the queue */
+ ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput));
+ if (ConInRec == NULL)
+ {
+ // return STATUS_INSUFFICIENT_RESOURCES;
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ continue;
+ }
+
+ ConInRec->InputEvent = *InputRecord;
+
+ if (AppendToEnd)
+ {
+ /* Append the event to the end of the queue */
+ InsertTailList(&Console->InputBuffer.InputEvents,
&ConInRec->ListEntry);
+ }
+ else
+ {
+ /* Append the event to the beginning of the queue */
+ InsertHeadList(&Console->InputBuffer.InputEvents,
&ConInRec->ListEntry);
+ }
+
+ // return STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
+ }
+
+ if (SetWaitEvent) SetEvent(Console->InputBuffer.ActiveEvent);
+
+Done:
+ if (NumEventsWritten) *NumEventsWritten = i;
+
+
+ /*
+ * This post-processing code MUST be IN consrv ONLY!!
+ */
+ // if (NT_SUCCESS(Status))
+ if (Status == STATUS_SUCCESS) PostprocessInput(Console);
return STATUS_SUCCESS;
}
@@ -133,8 +314,14 @@
ConioProcessInputEvent(PCONSOLE Console,
PINPUT_RECORD InputEvent)
{
- return ConioAddInputEvent(Console, InputEvent, TRUE);
-}
+ ULONG NumEventsWritten;
+ return ConioAddInputEvents(Console,
+ InputEvent,
+ 1,
+ &NumEventsWritten,
+ TRUE);
+}
+
VOID
PurgeInputBuffer(PCONSOLE Console)
@@ -158,6 +345,7 @@
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,
@@ -228,7 +416,8 @@
if (Input->InputEvent.EventType == KEY_EVENT &&
Input->InputEvent.Event.KeyEvent.bKeyDown)
{
- LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
+ LineInputKeyDown(Console, ExeName,
+ &Input->InputEvent.Event.KeyEvent);
ReadControl->dwControlKeyState =
Input->InputEvent.Event.KeyEvent.dwControlKeyState;
}
ConsoleFreeHeap(Input);
@@ -299,6 +488,7 @@
}
}
+ // FIXME: Only set if Status == STATUS_SUCCESS ???
if (NumCharsRead) *NumCharsRead = i;
return Status;
@@ -345,11 +535,6 @@
*InputRecord = Input->InputEvent;
- if (!Unicode)
- {
- ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord);
- }
-
++InputRecord;
++i;
CurrentInput = CurrentInput->Flink;
@@ -363,6 +548,15 @@
}
if (NumEventsRead) *NumEventsRead = i;
+
+ /* Now translate everything to ANSI */
+ if (!Unicode)
+ {
+ for (; i > 0; --i)
+ {
+ ConioInputEventToAnsi(InputBuffer->Header.Console, --InputRecord);
+ }
+ }
if (IsListEmpty(&InputBuffer->InputEvents))
{
@@ -392,20 +586,23 @@
ASSERT(Console == InputBuffer->Header.Console);
ASSERT((InputRecord != NULL) || (InputRecord == NULL && NumEventsToWrite ==
0));
+ /* First translate everything to UNICODE */
+ if (!Unicode)
+ {
+ for (i = 0; i < NumEventsToWrite; ++i)
+ {
+ ConioInputEventToUnicode(Console, &InputRecord[i]);
+ }
+ }
+
+ /* Now, add the events */
// if (NumEventsWritten) *NumEventsWritten = 0;
- // Status = ConioAddInputEvents(Console, InputRecord, NumEventsToWrite,
NumEventsWritten, AppendToEnd);
-
- for (i = 0; i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
- {
- if (!Unicode)
- {
- ConioInputEventToUnicode(Console, InputRecord);
- }
-
- Status = ConioAddInputEvent(Console, InputRecord++, AppendToEnd);
- }
-
- if (NumEventsWritten) *NumEventsWritten = i;
+ Status = ConioAddInputEvents(Console,
+ InputRecord,
+ NumEventsToWrite,
+ NumEventsWritten,
+ AppendToEnd);
+ // if (NumEventsWritten) *NumEventsWritten = i;
return Status;
}
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/coninput.c
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user…
==============================================================================
--- branches/condrv_restructure/win32ss/user/winsrv/consrv/coninput.c [iso-8859-1]
(original)
+++ branches/condrv_restructure/win32ss/user/winsrv/consrv/coninput.c [iso-8859-1] Fri Aug
1 18:08:29 2014
@@ -133,6 +133,7 @@
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,
@@ -148,20 +149,64 @@
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->ControlKeyState = ReadControl.dwControlKeyState;
+ ReadConsoleRequest->NumBytes / CharSize, //
NrCharactersToRead
+ &NrCharactersRead);
+ DPRINT1("ConDrvReadConsole returned (%d ; Status = 0x%08x)\n",
+ NrCharactersRead, Status);
+
+ // ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
if (Status == STATUS_PENDING)
{
@@ -173,7 +218,13 @@
}
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;
}
@@ -304,8 +355,12 @@
}
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;
}
@@ -325,24 +380,38 @@
DPRINT("SrvReadConsole\n");
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&ReadConsoleRequest->Buffer,
- ReadConsoleRequest->BufferSize,
- sizeof(BYTE)))
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- if (ReadConsoleRequest->NrCharactersRead >
ReadConsoleRequest->NrCharactersToRead)
+ /*
+ * 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;
+ }
+ else
+ {
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&ReadConsoleRequest->Buffer,
+ ReadConsoleRequest->CaptureBufferSize,
+ sizeof(BYTE)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ 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;
@@ -462,7 +531,11 @@
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,
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/conoutput.c
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user…
==============================================================================
--- branches/condrv_restructure/win32ss/user/winsrv/consrv/conoutput.c [iso-8859-1]
(original)
+++ branches/condrv_restructure/win32ss/user/winsrv/consrv/conoutput.c [iso-8859-1] Fri
Aug 1 18:08:29 2014
@@ -373,17 +373,45 @@
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)
{
@@ -404,6 +432,11 @@
/* 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);
@@ -502,12 +535,30 @@
DPRINT("SrvWriteConsole\n");
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID)&WriteConsoleRequest->Buffer,
- WriteConsoleRequest->BufferSize,
- sizeof(BYTE)))
- {
- return STATUS_INVALID_PARAMETER;
+ /*
+ * 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;
+ }
+ else
+ {
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID)&WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NumBytes,
+ sizeof(BYTE)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
}
Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE);
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user…
==============================================================================
--- branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h [iso-8859-1]
(original)
+++ branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h [iso-8859-1]
Fri Aug 1 18:08:29 2014
@@ -331,11 +331,15 @@
/* coninput.c */
VOID NTAPI ConioProcessKey(PCONSOLE Console, MSG* msg);
-NTSTATUS ConioAddInputEvent(PCONSOLE Console,
- PINPUT_RECORD InputEvent,
- BOOLEAN AppendToEnd);
-NTSTATUS ConioProcessInputEvent(PCONSOLE Console,
- PINPUT_RECORD InputEvent);
+NTSTATUS
+ConioAddInputEvents(PCONSOLE Console,
+ PINPUT_RECORD InputRecords,
+ ULONG NumEventsToWrite,
+ PULONG NumEventsWritten,
+ BOOLEAN AppendToEnd);
+NTSTATUS
+ConioProcessInputEvent(PCONSOLE Console,
+ PINPUT_RECORD InputEvent);
/* conoutput.c */
#define ConioInitRect(Rect, top, left, bottom, right) \
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user…
==============================================================================
---
branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h [iso-8859-1]
(original)
+++
branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h [iso-8859-1]
Fri Aug 1 18:08:29 2014
@@ -140,11 +140,15 @@
/* coninput.c */
VOID NTAPI ConioProcessKey(PCONSOLE Console, MSG* msg);
-NTSTATUS ConioAddInputEvent(PCONSOLE Console,
- PINPUT_RECORD InputEvent,
- BOOLEAN AppendToEnd);
-NTSTATUS ConioProcessInputEvent(PCONSOLE Console,
- PINPUT_RECORD InputEvent);
+NTSTATUS
+ConioAddInputEvents(PCONSOLE Console,
+ PINPUT_RECORD InputRecords,
+ ULONG NumEventsToWrite,
+ PULONG NumEventsWritten,
+ BOOLEAN AppendToEnd);
+NTSTATUS
+ConioProcessInputEvent(PCONSOLE Console,
+ PINPUT_RECORD InputEvent);
/* conoutput.c */
#define ConioInitRect(Rect, top, left, bottom, right) \
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.c
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user…
==============================================================================
--- branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.c [iso-8859-1]
(original)
+++ branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.c [iso-8859-1] Fri
Aug 1 18:08:29 2014
@@ -43,22 +43,21 @@
/* PRIVATE FUNCTIONS **********************************************************/
static PHISTORY_BUFFER
-HistoryCurrentBuffer(PCONSOLE Console)
-{
- /* TODO: use actual EXE name sent from process that called ReadConsole */
- UNICODE_STRING ExeName = { 14, 14, L"cmd.exe" };
+HistoryCurrentBuffer(PCONSOLE Console,
+ PUNICODE_STRING ExeName)
+{
PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
PHISTORY_BUFFER Hist;
for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
{
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
- if (RtlEqualUnicodeString(&ExeName, &Hist->ExeName, FALSE))
+ if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE))
return Hist;
}
/* Couldn't find the buffer, create a new one */
- Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName.Length);
+ Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length);
if (!Hist) return NULL;
Hist->MaxEntries = Console->HistoryBufferSize;
Hist->NumEntries = 0;
@@ -68,18 +67,19 @@
ConsoleFreeHeap(Hist);
return NULL;
}
- Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName.Length;
+ Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length;
Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
- memcpy(Hist->ExeName.Buffer, ExeName.Buffer, ExeName.Length);
+ memcpy(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length);
InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
return Hist;
}
static VOID
-HistoryAddEntry(PCONSOLE Console)
+HistoryAddEntry(PCONSOLE Console,
+ PUNICODE_STRING ExeName)
{
UNICODE_STRING NewEntry;
- PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+ PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
INT i;
if (!Hist) return;
@@ -127,9 +127,11 @@
}
static VOID
-HistoryGetCurrentEntry(PCONSOLE Console, PUNICODE_STRING Entry)
-{
- PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+HistoryGetCurrentEntry(PCONSOLE Console,
+ PUNICODE_STRING ExeName,
+ PUNICODE_STRING Entry)
+{
+ PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
if (!Hist || Hist->NumEntries == 0)
Entry->Length = 0;
@@ -275,9 +277,11 @@
}
static VOID
-LineInputRecallHistory(PCONSOLE Console, INT Offset)
-{
- PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+LineInputRecallHistory(PCONSOLE Console,
+ PUNICODE_STRING ExeName,
+ INT Offset)
+{
+ PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
UINT Position = 0;
if (!Hist || Hist->NumEntries == 0) return;
@@ -293,7 +297,9 @@
}
VOID
-LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
+LineInputKeyDown(PCONSOLE Console,
+ PUNICODE_STRING ExeName,
+ KEY_EVENT_RECORD *KeyEvent)
{
UINT Pos = Console->LinePos;
PHISTORY_BUFFER Hist;
@@ -346,7 +352,7 @@
else
{
/* Recall one character (but don't overwrite current line) */
- HistoryGetCurrentEntry(Console, &Entry);
+ HistoryGetCurrentEntry(Console, ExeName, &Entry);
if (Pos < Console->LineSize)
LineInputSetPos(Console, Pos + 1);
else if (Pos * sizeof(WCHAR) < Entry.Length)
@@ -365,26 +371,26 @@
return;
case VK_PRIOR:
/* Recall first history entry */
- LineInputRecallHistory(Console, -((WORD)-1));
+ LineInputRecallHistory(Console, ExeName, -((WORD)-1));
return;
case VK_NEXT:
/* Recall last history entry */
- LineInputRecallHistory(Console, +((WORD)-1));
+ LineInputRecallHistory(Console, ExeName, +((WORD)-1));
return;
case VK_UP:
case VK_F5:
/* Recall previous history entry. On first time, actually recall the
* current (usually last) entry; on subsequent times go back. */
- LineInputRecallHistory(Console, Console->LineUpPressed ? -1 : 0);
+ LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0);
Console->LineUpPressed = TRUE;
return;
case VK_DOWN:
/* Recall next history entry */
- LineInputRecallHistory(Console, +1);
+ LineInputRecallHistory(Console, ExeName, +1);
return;
case VK_F3:
/* Recall remainder of current history entry */
- HistoryGetCurrentEntry(Console, &Entry);
+ HistoryGetCurrentEntry(Console, ExeName, &Entry);
if (Pos * sizeof(WCHAR) < Entry.Length)
{
UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos);
@@ -398,11 +404,11 @@
break;
case VK_F7:
if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
- HistoryDeleteBuffer(HistoryCurrentBuffer(Console));
+ HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName));
return;
case VK_F8:
/* Search for history entries starting with input. */
- Hist = HistoryCurrentBuffer(Console);
+ Hist = HistoryCurrentBuffer(Console, ExeName);
if (!Hist || Hist->NumEntries == 0) return;
/* Like Up/F5, on first time start from current (usually last) entry,
@@ -446,7 +452,7 @@
}
else if (KeyEvent->uChar.UnicodeChar == L'\r')
{
- HistoryAddEntry(Console);
+ HistoryAddEntry(Console, ExeName);
/* TODO: Expand aliases */
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.h
URL:
http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user…
==============================================================================
--- branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.h [iso-8859-1]
(original)
+++ branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.h [iso-8859-1] Fri
Aug 1 18:08:29 2014
@@ -9,4 +9,8 @@
#pragma once
VOID HistoryDeleteBuffers(PCONSOLE Console);
-VOID LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent);
+
+VOID
+LineInputKeyDown(PCONSOLE Console,
+ PUNICODE_STRING ExeName,
+ KEY_EVENT_RECORD *KeyEvent);