[KERNEL32][CONSRV]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 1 Aug 2014 18:08:29 +0000 (18:08 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 1 Aug 2014 18:08:29 +0000 (18:08 +0000)
- 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 .

svn path=/branches/condrv_restructure/; revision=63793

dll/win32/kernel32/client/console/readwrite.c
include/reactos/subsys/win/conmsg.h
win32ss/user/winsrv/consrv/condrv/coninput.c
win32ss/user/winsrv/consrv/coninput.c
win32ss/user/winsrv/consrv/conoutput.c
win32ss/user/winsrv/consrv/include/conio.h
win32ss/user/winsrv/consrv/include/conio_winsrv.h
win32ss/user/winsrv/consrv/lineinput.c
win32ss/user/winsrv/consrv/lineinput.h

index e3d7f28..bb9fa5d 100644 (file)
  * Read functions *
  ******************/
 
  * Read functions *
  ******************/
 
+DWORD
+WINAPI
+GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer);
+
 static
 BOOL
 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;
     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 */
 
     /* 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,
     /* Call the server */
     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
                         CaptureBuffer,
@@ -84,35 +180,49 @@ IntReadConsole(HANDLE hConsoleInput,
                         sizeof(*ReadConsoleRequest));
 
     /* Check for success */
                         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
     {
     }
     else
     {
-        DPRINT1("CSR returned error in ReadConsole\n");
-
-        if (lpNumberOfCharsRead != NULL)
-            *lpNumberOfCharsRead = 0;
-
-        /* Error out */
         BaseSetLastNTError(ApiMessage.Status);
     }
 
         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;
 }
 
 
 }
 
 
@@ -228,12 +338,12 @@ IntGetConsoleInput(IN HANDLE hConsoleInput,
 
 static
 BOOL
 
 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;
 {
     CONSOLE_API_MESSAGE ApiMessage;
     PCONSOLE_READOUTPUT ReadOutputRequest = &ApiMessage.Data.ReadOutputRequest;
@@ -292,7 +402,6 @@ IntReadConsoleOutput(HANDLE hConsoleOutput,
     }
     else
     {
     }
     else
     {
-        /* Error out */
         BaseSetLastNTError(ApiMessage.Status);
     }
 
         BaseSetLastNTError(ApiMessage.Status);
     }
 
@@ -321,7 +430,7 @@ IntReadConsoleOutputCode(IN HANDLE hConsoleOutput,
     CONSOLE_API_MESSAGE ApiMessage;
     PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest;
     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
     CONSOLE_API_MESSAGE ApiMessage;
     PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest;
     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
-    ULONG SizeBytes, CodeSize;
+    ULONG CodeSize, SizeBytes;
 
     DPRINT("IntReadConsoleOutputCode\n");
 
 
     DPRINT("IntReadConsoleOutputCode\n");
 
@@ -431,42 +540,79 @@ IntReadConsoleOutputCode(IN HANDLE hConsoleOutput,
 
 static
 BOOL
 
 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,
                 LPVOID lpReserved,
-                BOOL bUnicode)
+                IN BOOLEAN bUnicode)
 {
 {
-    BOOL bRet = TRUE;
+    BOOL Success;
     CONSOLE_API_MESSAGE ApiMessage;
     PCONSOLE_WRITECONSOLE WriteConsoleRequest = &ApiMessage.Data.WriteConsoleRequest;
     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 */
 
     /* 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,
 
     /* Call the server */
     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
@@ -475,26 +621,32 @@ IntWriteConsole(HANDLE hConsoleOutput,
                         sizeof(*WriteConsoleRequest));
 
     /* Check for success */
                         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
     {
     }
     else
     {
-        if (lpNumberOfCharsWritten != NULL)
-            *lpNumberOfCharsWritten = 0;
-
-        /* Error out */
         BaseSetLastNTError(ApiMessage.Status);
         BaseSetLastNTError(ApiMessage.Status);
-        bRet = FALSE;
     }
 
     }
 
-    CsrFreeCaptureBuffer(CaptureBuffer);
-
-    return bRet;
+    /* Return success status */
+    return Success;
 }
 
 
 }
 
 
@@ -600,12 +752,12 @@ IntWriteConsoleInput(IN HANDLE hConsoleInput,
 
 static
 BOOL
 
 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;
 {
     CONSOLE_API_MESSAGE ApiMessage;
     PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest;
@@ -660,7 +812,6 @@ IntWriteConsoleOutput(HANDLE hConsoleOutput,
     /* Check for success */
     if (!NT_SUCCESS(ApiMessage.Status))
     {
     /* Check for success */
     if (!NT_SUCCESS(ApiMessage.Status))
     {
-        /* Error out */
         BaseSetLastNTError(ApiMessage.Status);
     }
 
         BaseSetLastNTError(ApiMessage.Status);
     }
 
@@ -689,7 +840,7 @@ IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput,
     CONSOLE_API_MESSAGE ApiMessage;
     PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest;
     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
     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  ) &&
 
     if ( (CodeType != CODE_ASCII    ) &&
          (CodeType != CODE_UNICODE  ) &&
@@ -872,11 +1023,11 @@ IntFillConsoleOutputCode(IN HANDLE hConsoleOutput,
  */
 BOOL
 WINAPI
  */
 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,
 {
     return IntReadConsole(hConsoleInput,
                           lpBuffer,
@@ -894,11 +1045,11 @@ ReadConsoleW(HANDLE hConsoleInput,
  */
 BOOL
 WINAPI
  */
 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,
 {
     return IntReadConsole(hConsoleInput,
                           lpBuffer,
@@ -1044,11 +1195,11 @@ ReadConsoleInputExA(IN HANDLE hConsoleInput,
  */
 BOOL
 WINAPI
  */
 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,
 {
     return IntReadConsoleOutput(hConsoleOutput,
                                 lpBuffer,
@@ -1066,11 +1217,11 @@ ReadConsoleOutputW(HANDLE hConsoleOutput,
  */
 BOOL
 WINAPI
  */
 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,
 {
     return IntReadConsoleOutput(hConsoleOutput,
                                 lpBuffer,
@@ -1158,10 +1309,10 @@ ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput,
  */
 BOOL
 WINAPI
  */
 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,
               LPVOID lpReserved)
 {
     return IntWriteConsole(hConsoleOutput,
@@ -1180,10 +1331,10 @@ WriteConsoleW(HANDLE hConsoleOutput,
  */
 BOOL
 WINAPI
  */
 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,
               LPVOID lpReserved)
 {
     return IntWriteConsole(hConsoleOutput,
@@ -1286,11 +1437,11 @@ WriteConsoleInputVDMA(IN HANDLE hConsoleInput,
  */
 BOOL
 WINAPI
  */
 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,
 {
     return IntWriteConsoleOutput(hConsoleOutput,
                                  lpBuffer,
@@ -1308,11 +1459,11 @@ WriteConsoleOutputW(HANDLE hConsoleOutput,
  */
 BOOL
 WINAPI
  */
 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,
 {
     return IntWriteConsoleOutput(hConsoleOutput,
                                  lpBuffer,
index a16e9a4..5a4f595 100644 (file)
@@ -218,30 +218,40 @@ typedef struct
 
 typedef struct
 {
 
 typedef struct
 {
+    HANDLE ConsoleHandle;
     HANDLE OutputHandle;
 
     HANDLE OutputHandle;
 
-    BOOL Unicode;
-    ULONG NrCharactersToWrite;
-    ULONG NrCharactersWritten;
+    CHAR  StaticBuffer[80];
+    PVOID Buffer; // BufPtr
+    ULONG NumBytes;
+
+    // On Windows, the client never uses this member
+    ULONG Reserved1;
+
+    BOOLEAN UsingStaticBuffer;
+    BOOLEAN Unicode;
 
 
-    ULONG BufferSize;
-    PVOID Buffer;
+    // On Windows, the client never uses this member
+    CHAR Reserved2[6];
 } CONSOLE_WRITECONSOLE, *PCONSOLE_WRITECONSOLE;
 
 typedef struct
 {
 } CONSOLE_WRITECONSOLE, *PCONSOLE_WRITECONSOLE;
 
 typedef struct
 {
+    HANDLE ConsoleHandle;
     HANDLE InputHandle;
 
     HANDLE InputHandle;
 
-    BOOL Unicode;
-    ULONG NrCharactersToRead;
-    ULONG NrCharactersRead;
+    USHORT ExeLength;
 
 
-    UNICODE_STRING ExeName;
-    DWORD CtrlWakeupMask;
-    DWORD ControlKeyState;
+    CHAR  StaticBuffer[80];
+    PVOID Buffer; // BufPtr
+    ULONG NumBytes;
 
 
-    ULONG BufferSize;
-    PVOID Buffer;
+    ULONG CaptureBufferSize;
+
+    ULONG   InitialNumBytes;
+    ULONG   CtrlWakeupMask;
+    ULONG   ControlKeyState;
+    BOOLEAN Unicode;
 } CONSOLE_READCONSOLE, *PCONSOLE_READCONSOLE;
 
 typedef struct
 } CONSOLE_READCONSOLE, *PCONSOLE_READCONSOLE;
 
 typedef struct
index 83428a9..c19b601 100644 (file)
@@ -65,67 +65,248 @@ ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent)
     }
 }
 
     }
 }
 
-NTSTATUS
-ConioAddInputEvent(PCONSOLE Console,
-                   PINPUT_RECORD InputEvent,
-                   BOOLEAN AppendToEnd)
+
+/*
+ * This pre-processing code MUST be IN consrv ONLY
+ */
+static ULONG
+PreprocessInput(PCONSOLE Console,
+                PINPUT_RECORD InputEvent,
+                ULONG NumEventsToWrite)
 {
 {
-    ConsoleInput *ConInRec;
+    ULONG NumEvents;
 
 
-    /* Check for pause or unpause */
-    if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown)
+    /*
+     * Loop each event, and for each, check for pause or unpause
+     * and perform adequate behaviour.
+     */
+    for (NumEvents = NumEventsToWrite; NumEvents > 0; --NumEvents)
     {
     {
-        WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
-        if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
+        /* Check for pause or unpause */
+        if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown)
         {
         {
-            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)))))
+            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
             {
             {
-                ConioPause(Console, PAUSED_FROM_KEYBOARD);
-                return STATUS_SUCCESS;
+                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,
+                  NULL);
+    if (!IsListEmpty(&Console->ReadWaitQueue))
+    {
+        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
         {
         else
         {
-            if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN &&
-                vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL)
+            /* 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) )
             {
             {
-                ConioUnpause(Console, PAUSED_FROM_KEYBOARD);
-                return STATUS_SUCCESS;
+                /* Update the repeat count */
+                LastInputRecord->Event.KeyEvent.wRepeatCount +=
+                    InputRecord->Event.KeyEvent.wRepeatCount;
+
+                i = 1;
+                // return STATUS_SUCCESS;
+                Status = STATUS_SUCCESS;
             }
         }
     }
 
             }
         }
     }
 
-    /* Add event to the queue */
-    ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput));
-    if (ConInRec == NULL) return STATUS_INSUFFICIENT_RESOURCES;
+    /* If we coalesced the only one element, we can quit */
+    if (i == 1 && Status == STATUS_SUCCESS /* && NumEventsToWrite == 1 */)
+        goto Done;
 
 
-    ConInRec->InputEvent = *InputEvent;
+    /*
+     * No event coalesced, add them in the usual way.
+     */
 
     if (AppendToEnd)
     {
 
     if (AppendToEnd)
     {
-        /* Append the event to the end of the queue */
-        InsertTailList(&Console->InputBuffer.InputEvents, &ConInRec->ListEntry);
+        /* Go to the beginning of the list */
+        // InputRecords = InputRecords;
     }
     else
     {
     }
     else
     {
-        /* Append the event to the beginning of the queue */
-        InsertHeadList(&Console->InputBuffer.InputEvents, &ConInRec->ListEntry);
+        /* Go to the end of the list */
+        InputRecords = &InputRecords[NumEventsToWrite - 1];
     }
 
     }
 
-    SetEvent(Console->InputBuffer.ActiveEvent);
-    CsrNotifyWait(&Console->ReadWaitQueue,
-                  FALSE,
-                  NULL,
-                  NULL);
-    if (!IsListEmpty(&Console->ReadWaitQueue))
+    /* 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)
     {
     {
-        CsrDereferenceWait(&Console->ReadWaitQueue);
+        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;
 }
 
     return STATUS_SUCCESS;
 }
 
@@ -133,9 +314,15 @@ NTSTATUS
 ConioProcessInputEvent(PCONSOLE Console,
                        PINPUT_RECORD InputEvent)
 {
 ConioProcessInputEvent(PCONSOLE Console,
                        PINPUT_RECORD InputEvent)
 {
-    return ConioAddInputEvent(Console, InputEvent, TRUE);
+    ULONG NumEventsWritten;
+    return ConioAddInputEvents(Console,
+                               InputEvent,
+                               1,
+                               &NumEventsWritten,
+                               TRUE);
 }
 
 }
 
+
 VOID
 PurgeInputBuffer(PCONSOLE Console)
 {
 VOID
 PurgeInputBuffer(PCONSOLE Console)
 {
@@ -158,6 +345,7 @@ PurgeInputBuffer(PCONSOLE Console)
 NTSTATUS NTAPI
 ConDrvReadConsole(IN PCONSOLE Console,
                   IN PCONSOLE_INPUT_BUFFER InputBuffer,
 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,
                   IN BOOLEAN Unicode,
                   OUT PVOID Buffer,
                   IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
@@ -228,7 +416,8 @@ ConDrvReadConsole(IN PCONSOLE Console,
             if (Input->InputEvent.EventType == KEY_EVENT &&
                 Input->InputEvent.Event.KeyEvent.bKeyDown)
             {
             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);
                 ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
             }
             ConsoleFreeHeap(Input);
@@ -299,6 +488,7 @@ ConDrvReadConsole(IN PCONSOLE Console,
         }
     }
 
         }
     }
 
+    // FIXME: Only set if Status == STATUS_SUCCESS ???
     if (NumCharsRead) *NumCharsRead = i;
 
     return Status;
     if (NumCharsRead) *NumCharsRead = i;
 
     return Status;
@@ -345,11 +535,6 @@ ConDrvGetConsoleInput(IN PCONSOLE Console,
 
         *InputRecord = Input->InputEvent;
 
 
         *InputRecord = Input->InputEvent;
 
-        if (!Unicode)
-        {
-            ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord);
-        }
-
         ++InputRecord;
         ++i;
         CurrentInput = CurrentInput->Flink;
         ++InputRecord;
         ++i;
         CurrentInput = CurrentInput->Flink;
@@ -364,6 +549,15 @@ ConDrvGetConsoleInput(IN PCONSOLE Console,
 
     if (NumEventsRead) *NumEventsRead = i;
 
 
     if (NumEventsRead) *NumEventsRead = i;
 
+    /* Now translate everything to ANSI */
+    if (!Unicode)
+    {
+        for (; i > 0; --i)
+        {
+            ConioInputEventToAnsi(InputBuffer->Header.Console, --InputRecord);
+        }
+    }
+
     if (IsListEmpty(&InputBuffer->InputEvents))
     {
         ResetEvent(InputBuffer->ActiveEvent);
     if (IsListEmpty(&InputBuffer->InputEvents))
     {
         ResetEvent(InputBuffer->ActiveEvent);
@@ -392,20 +586,23 @@ ConDrvWriteConsoleInput(IN PCONSOLE Console,
     ASSERT(Console == InputBuffer->Header.Console);
     ASSERT((InputRecord != NULL) || (InputRecord == NULL && NumEventsToWrite == 0));
 
     ASSERT(Console == InputBuffer->Header.Console);
     ASSERT((InputRecord != NULL) || (InputRecord == NULL && NumEventsToWrite == 0));
 
-    // if (NumEventsWritten) *NumEventsWritten = 0;
-    // Status = ConioAddInputEvents(Console, InputRecord, NumEventsToWrite, NumEventsWritten, AppendToEnd);
-
-    for (i = 0; i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
+    /* First translate everything to UNICODE */
+    if (!Unicode)
     {
     {
-        if (!Unicode)
+        for (i = 0; i < NumEventsToWrite; ++i)
         {
         {
-            ConioInputEventToUnicode(Console, InputRecord);
+            ConioInputEventToUnicode(Console, &InputRecord[i]);
         }
         }
-
-        Status = ConioAddInputEvent(Console, InputRecord++, AppendToEnd);
     }
 
     }
 
-    if (NumEventsWritten) *NumEventsWritten = i;
+    /* Now, add the events */
+    // if (NumEventsWritten) *NumEventsWritten = 0;
+    Status = ConioAddInputEvents(Console,
+                                 InputRecord,
+                                 NumEventsToWrite,
+                                 NumEventsWritten,
+                                 AppendToEnd);
+    // if (NumEventsWritten) *NumEventsWritten = i;
 
     return Status;
 }
 
     return Status;
 }
index 5bcd8f6..ba76ea7 100644 (file)
@@ -133,6 +133,7 @@ Quit:
 NTSTATUS NTAPI
 ConDrvReadConsole(IN PCONSOLE Console,
                   IN PCONSOLE_INPUT_BUFFER InputBuffer,
 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,
                   IN BOOLEAN Unicode,
                   OUT PVOID Buffer,
                   IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
@@ -148,20 +149,64 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
     PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
     CONSOLE_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.nLength           = sizeof(CONSOLE_READCONSOLE_CONTROL);
-    ReadControl.nInitialChars     = ReadConsoleRequest->NrCharactersRead;
+    ReadControl.nInitialChars     = ReadConsoleRequest->InitialNumBytes / CharSize;
     ReadControl.dwCtrlWakeupMask  = ReadConsoleRequest->CtrlWakeupMask;
     ReadControl.dwControlKeyState = ReadConsoleRequest->ControlKeyState;
 
     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,
     Status = ConDrvReadConsole(InputBuffer->Header.Console,
                                InputBuffer,
+                               &ExeName,
                                ReadConsoleRequest->Unicode,
                                ReadConsoleRequest->Unicode,
-                               ReadConsoleRequest->Buffer,
+                               Buffer,
                                &ReadControl,
                                &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)
     {
 
     if (Status == STATUS_PENDING)
     {
@@ -173,7 +218,13 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
     }
     else
     {
     }
     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;
     }
         return Status;
         // return STATUS_SUCCESS;
     }
@@ -304,8 +355,12 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
     }
     else
     {
     }
     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;
         GetInputRequest->NumRecords = NumEventsRead;
+
         return Status;
         // return STATUS_SUCCESS;
     }
         return Status;
         // return STATUS_SUCCESS;
     }
@@ -325,15 +380,32 @@ CSR_API(SrvReadConsole)
 
     DPRINT("SrvReadConsole\n");
 
 
     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;
     }
     {
         return STATUS_INVALID_PARAMETER;
     }
@@ -341,9 +413,6 @@ CSR_API(SrvReadConsole)
     Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
     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;
     InputInfo.CallingThread = CsrGetClientThread();
     InputInfo.HandleEntry   = HandleEntry;
     InputInfo.InputBuffer   = InputBuffer;
@@ -462,7 +531,11 @@ CSR_API(SrvWriteConsoleInput)
     Status = ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
                                   WriteInputRequest->InputHandle,
                                   &InputBuffer, GENERIC_WRITE, TRUE);
     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,
 
     NumEventsWritten = 0;
     Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,
index 7df379a..acf2ca1 100644 (file)
@@ -373,17 +373,45 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
     PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
     PTEXTMODE_SCREEN_BUFFER ScreenBuffer;
 
     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;
 
     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,
     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)
     {
 
     if (Status == STATUS_PENDING)
     {
@@ -404,6 +432,11 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
         /* Wait until we un-pause the console */
         // 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);
 
 Quit:
     ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE);
@@ -502,12 +535,30 @@ CSR_API(SrvWriteConsole)
 
     DPRINT("SrvWriteConsole\n");
 
 
     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 = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE);
index 5e8399e..46e3b41 100644 (file)
@@ -331,11 +331,15 @@ ConSrvConsoleProcessCtrlEvent(IN PCONSOLE Console,
 
 /* coninput.c */
 VOID NTAPI ConioProcessKey(PCONSOLE Console, MSG* msg);
 
 /* 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) \
 
 /* conoutput.c */
 #define ConioInitRect(Rect, top, left, bottom, right) \
index 957a8ee..d239db7 100644 (file)
@@ -140,11 +140,15 @@ ConSrvConsoleProcessCtrlEvent(IN PCONSOLE Console,
 
 /* coninput.c */
 VOID NTAPI ConioProcessKey(PCONSOLE Console, MSG* msg);
 
 /* 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) \
 
 /* conoutput.c */
 #define ConioInitRect(Rect, top, left, bottom, right) \
index 63d5003..c3ae65e 100644 (file)
@@ -43,22 +43,21 @@ ConvertInputUnicodeToAnsi(PCONSOLE Console,
 /* PRIVATE FUNCTIONS **********************************************************/
 
 static PHISTORY_BUFFER
 /* PRIVATE FUNCTIONS **********************************************************/
 
 static PHISTORY_BUFFER
-HistoryCurrentBuffer(PCONSOLE Console)
+HistoryCurrentBuffer(PCONSOLE Console,
+                     PUNICODE_STRING ExeName)
 {
 {
-    /* TODO: use actual EXE name sent from process that called ReadConsole */
-    UNICODE_STRING ExeName = { 14, 14, L"cmd.exe" };
     PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
     PHISTORY_BUFFER Hist;
 
     for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
     {
         Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
     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 */
             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;
     if (!Hist) return NULL;
     Hist->MaxEntries = Console->HistoryBufferSize;
     Hist->NumEntries = 0;
@@ -68,18 +67,19 @@ HistoryCurrentBuffer(PCONSOLE Console)
         ConsoleFreeHeap(Hist);
         return NULL;
     }
         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);
     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
     InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
     return Hist;
 }
 
 static VOID
-HistoryAddEntry(PCONSOLE Console)
+HistoryAddEntry(PCONSOLE Console,
+                PUNICODE_STRING ExeName)
 {
     UNICODE_STRING NewEntry;
 {
     UNICODE_STRING NewEntry;
-    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
     INT i;
 
     if (!Hist) return;
     INT i;
 
     if (!Hist) return;
@@ -127,9 +127,11 @@ HistoryAddEntry(PCONSOLE Console)
 }
 
 static VOID
 }
 
 static VOID
-HistoryGetCurrentEntry(PCONSOLE Console, PUNICODE_STRING Entry)
+HistoryGetCurrentEntry(PCONSOLE Console,
+                       PUNICODE_STRING ExeName,
+                       PUNICODE_STRING Entry)
 {
 {
-    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
 
     if (!Hist || Hist->NumEntries == 0)
         Entry->Length = 0;
 
     if (!Hist || Hist->NumEntries == 0)
         Entry->Length = 0;
@@ -275,9 +277,11 @@ LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHAR Inser
 }
 
 static VOID
 }
 
 static VOID
-LineInputRecallHistory(PCONSOLE Console, INT Offset)
+LineInputRecallHistory(PCONSOLE Console,
+                       PUNICODE_STRING ExeName,
+                       INT Offset)
 {
 {
-    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
     UINT Position = 0;
 
     if (!Hist || Hist->NumEntries == 0) return;
     UINT Position = 0;
 
     if (!Hist || Hist->NumEntries == 0) return;
@@ -293,7 +297,9 @@ LineInputRecallHistory(PCONSOLE Console, INT Offset)
 }
 
 VOID
 }
 
 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;
 {
     UINT Pos = Console->LinePos;
     PHISTORY_BUFFER Hist;
@@ -346,7 +352,7 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
         else
         {
             /* Recall one character (but don't overwrite current line) */
         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)
             if (Pos < Console->LineSize)
                 LineInputSetPos(Console, Pos + 1);
             else if (Pos * sizeof(WCHAR) < Entry.Length)
@@ -365,26 +371,26 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
         return;
     case VK_PRIOR:
         /* Recall first history entry */
         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 */
         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. */
         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 */
         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 */
         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);
         if (Pos * sizeof(WCHAR) < Entry.Length)
         {
             UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos);
@@ -398,11 +404,11 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
         break;
     case VK_F7:
         if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
         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. */
         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,
         if (!Hist || Hist->NumEntries == 0) return;
 
         /* Like Up/F5, on first time start from current (usually last) entry,
@@ -446,7 +452,7 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
     }
     else if (KeyEvent->uChar.UnicodeChar == L'\r')
     {
     }
     else if (KeyEvent->uChar.UnicodeChar == L'\r')
     {
-        HistoryAddEntry(Console);
+        HistoryAddEntry(Console, ExeName);
 
         /* TODO: Expand aliases */
 
 
         /* TODO: Expand aliases */
 
index e5fbec2..afb6d25 100644 (file)
@@ -9,4 +9,8 @@
 #pragma once
 
 VOID HistoryDeleteBuffers(PCONSOLE Console);
 #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);