2010-06-05 18:17:42 +00:00
|
|
|
/*
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2012-10-25 20:40:41 +00:00
|
|
|
* PROJECT: ReactOS Console Server DLL
|
2015-10-05 12:21:25 +00:00
|
|
|
* FILE: win32ss/user/winsrv/consrv/lineinput.c
|
2010-06-05 18:17:42 +00:00
|
|
|
* PURPOSE: Console line input functions
|
|
|
|
* PROGRAMMERS: Jeffrey Morlan
|
|
|
|
*/
|
|
|
|
|
2013-03-19 22:05:38 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2012-10-23 22:31:36 +00:00
|
|
|
#include "consrv.h"
|
2014-09-07 20:05:39 +00:00
|
|
|
#include "popup.h"
|
2012-10-23 22:31:36 +00:00
|
|
|
|
2010-06-05 18:17:42 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2013-03-19 22:05:38 +00:00
|
|
|
|
2014-07-28 13:20:54 +00:00
|
|
|
BOOLEAN
|
2014-09-07 20:05:39 +00:00
|
|
|
ConvertInputAnsiToUnicode(PCONSRV_CONSOLE Console,
|
2014-07-28 13:20:54 +00:00
|
|
|
PVOID Source,
|
|
|
|
USHORT SourceLength,
|
|
|
|
// BOOLEAN IsUnicode,
|
|
|
|
PWCHAR* Target,
|
|
|
|
PUSHORT TargetLength);
|
|
|
|
BOOLEAN
|
2014-09-07 20:05:39 +00:00
|
|
|
ConvertInputUnicodeToAnsi(PCONSRV_CONSOLE Console,
|
2014-07-28 13:20:54 +00:00
|
|
|
PVOID Source,
|
|
|
|
USHORT SourceLength,
|
|
|
|
// BOOLEAN IsAnsi,
|
|
|
|
PCHAR/* * */ Target,
|
|
|
|
/*P*/USHORT TargetLength);
|
|
|
|
|
|
|
|
|
2014-08-29 19:45:45 +00:00
|
|
|
VOID
|
2014-08-11 20:39:06 +00:00
|
|
|
HistoryAddEntry(PCONSRV_CONSOLE Console,
|
2014-08-29 19:45:45 +00:00
|
|
|
PUNICODE_STRING ExeName,
|
|
|
|
PUNICODE_STRING Entry);
|
|
|
|
BOOL
|
|
|
|
HistoryRecallHistory(PCONSRV_CONSOLE Console,
|
|
|
|
PUNICODE_STRING ExeName,
|
|
|
|
INT Offset,
|
|
|
|
PUNICODE_STRING Entry);
|
|
|
|
VOID
|
2014-08-11 20:39:06 +00:00
|
|
|
HistoryGetCurrentEntry(PCONSRV_CONSOLE Console,
|
[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 .
svn path=/branches/condrv_restructure/; revision=63793
2014-08-01 18:08:29 +00:00
|
|
|
PUNICODE_STRING ExeName,
|
2014-08-29 19:45:45 +00:00
|
|
|
PUNICODE_STRING Entry);
|
|
|
|
VOID
|
|
|
|
HistoryDeleteCurrentBuffer(PCONSRV_CONSOLE Console,
|
2014-09-07 20:05:39 +00:00
|
|
|
PUNICODE_STRING ExeName);
|
2014-08-29 19:45:45 +00:00
|
|
|
BOOL
|
|
|
|
HistoryFindEntryByPrefix(PCONSRV_CONSOLE Console,
|
|
|
|
PUNICODE_STRING ExeName,
|
|
|
|
PUNICODE_STRING Prefix,
|
|
|
|
PUNICODE_STRING Entry);
|
2013-03-19 22:05:38 +00:00
|
|
|
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2014-08-29 19:45:45 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
2013-03-30 21:25:27 +00:00
|
|
|
|
2010-06-05 18:17:42 +00:00
|
|
|
static VOID
|
2014-08-29 19:45:45 +00:00
|
|
|
LineInputSetPos(PCONSRV_CONSOLE Console,
|
|
|
|
UINT Pos)
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
if (Pos != Console->LinePos && (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT))
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2013-01-05 23:37:04 +00:00
|
|
|
PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
|
2013-04-14 16:04:46 +00:00
|
|
|
SHORT OldCursorX = Buffer->CursorPosition.X;
|
|
|
|
SHORT OldCursorY = Buffer->CursorPosition.Y;
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
INT XY = OldCursorY * Buffer->ScreenBufferSize.X + OldCursorX;
|
2010-06-05 18:17:42 +00:00
|
|
|
|
|
|
|
XY += (Pos - Console->LinePos);
|
|
|
|
if (XY < 0)
|
|
|
|
XY = 0;
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
else if (XY >= Buffer->ScreenBufferSize.Y * Buffer->ScreenBufferSize.X)
|
|
|
|
XY = Buffer->ScreenBufferSize.Y * Buffer->ScreenBufferSize.X - 1;
|
2010-06-05 18:17:42 +00:00
|
|
|
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
Buffer->CursorPosition.X = XY % Buffer->ScreenBufferSize.X;
|
|
|
|
Buffer->CursorPosition.Y = XY / Buffer->ScreenBufferSize.X;
|
2013-10-10 01:16:02 +00:00
|
|
|
TermSetScreenInfo(Console, Buffer, OldCursorX, OldCursorY);
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Console->LinePos = Pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VOID
|
2014-08-29 19:45:45 +00:00
|
|
|
LineInputEdit(PCONSRV_CONSOLE Console,
|
|
|
|
UINT NumToDelete,
|
|
|
|
UINT NumToInsert,
|
|
|
|
PWCHAR Insertion)
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2013-05-29 00:29:07 +00:00
|
|
|
PTEXTMODE_SCREEN_BUFFER ActiveBuffer;
|
2010-06-05 18:17:42 +00:00
|
|
|
UINT Pos = Console->LinePos;
|
|
|
|
UINT NewSize = Console->LineSize - NumToDelete + NumToInsert;
|
2013-04-14 16:04:46 +00:00
|
|
|
UINT i;
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2013-05-29 00:29:07 +00:00
|
|
|
if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER) return;
|
|
|
|
ActiveBuffer = (PTEXTMODE_SCREEN_BUFFER)Console->ActiveBuffer;
|
|
|
|
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Make sure there is always enough room for ending \r\n */
|
2010-06-05 18:17:42 +00:00
|
|
|
if (NewSize + 2 > Console->LineMaxSize)
|
|
|
|
return;
|
|
|
|
|
|
|
|
memmove(&Console->LineBuffer[Pos + NumToInsert],
|
|
|
|
&Console->LineBuffer[Pos + NumToDelete],
|
|
|
|
(Console->LineSize - (Pos + NumToDelete)) * sizeof(WCHAR));
|
|
|
|
memcpy(&Console->LineBuffer[Pos], Insertion, NumToInsert * sizeof(WCHAR));
|
|
|
|
|
2014-09-07 20:05:39 +00:00
|
|
|
if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT)
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
|
|
|
for (i = Pos; i < NewSize; i++)
|
|
|
|
{
|
2014-08-29 19:54:10 +00:00
|
|
|
TermWriteStream(Console, ActiveBuffer, &Console->LineBuffer[i], 1, TRUE);
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
|
|
|
for (; i < Console->LineSize; i++)
|
|
|
|
{
|
2014-08-29 19:54:10 +00:00
|
|
|
TermWriteStream(Console, ActiveBuffer, L" ", 1, TRUE);
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
|
|
|
Console->LinePos = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
Console->LineSize = NewSize;
|
|
|
|
LineInputSetPos(Console, Pos + NumToInsert);
|
|
|
|
}
|
|
|
|
|
2014-08-29 19:45:45 +00:00
|
|
|
#if 0
|
2010-06-05 18:17:42 +00:00
|
|
|
static VOID
|
2014-08-11 20:39:06 +00:00
|
|
|
LineInputRecallHistory(PCONSRV_CONSOLE Console,
|
[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 .
svn path=/branches/condrv_restructure/; revision=63793
2014-08-01 18:08:29 +00:00
|
|
|
PUNICODE_STRING ExeName,
|
|
|
|
INT Offset)
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
[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 .
svn path=/branches/condrv_restructure/; revision=63793
2014-08-01 18:08:29 +00:00
|
|
|
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
|
2013-04-14 16:04:46 +00:00
|
|
|
UINT Position = 0;
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2013-04-14 16:04:46 +00:00
|
|
|
if (!Hist || Hist->NumEntries == 0) return;
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2013-04-14 16:04:46 +00:00
|
|
|
Position = Hist->Position + Offset;
|
|
|
|
Position = min(max(Position, 0), Hist->NumEntries - 1);
|
|
|
|
Hist->Position = Position;
|
2010-06-05 18:17:42 +00:00
|
|
|
|
|
|
|
LineInputSetPos(Console, 0);
|
|
|
|
LineInputEdit(Console, Console->LineSize,
|
2013-04-14 16:04:46 +00:00
|
|
|
Hist->Entries[Hist->Position].Length / sizeof(WCHAR),
|
|
|
|
Hist->Entries[Hist->Position].Buffer);
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
2014-08-29 19:45:45 +00:00
|
|
|
#else
|
|
|
|
static VOID
|
|
|
|
LineInputRecallHistory(PCONSRV_CONSOLE Console,
|
|
|
|
PUNICODE_STRING ExeName,
|
|
|
|
INT Offset)
|
|
|
|
{
|
|
|
|
UNICODE_STRING Entry;
|
|
|
|
|
|
|
|
if (!HistoryRecallHistory(Console, ExeName, Offset, &Entry)) return;
|
|
|
|
|
|
|
|
LineInputSetPos(Console, 0);
|
|
|
|
LineInputEdit(Console, Console->LineSize,
|
|
|
|
Entry.Length / sizeof(WCHAR),
|
|
|
|
Entry.Buffer);
|
|
|
|
}
|
|
|
|
#endif
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2014-09-07 20:05:39 +00:00
|
|
|
|
|
|
|
// TESTS!!
|
|
|
|
PPOPUP_WINDOW Popup = NULL;
|
|
|
|
|
|
|
|
PPOPUP_WINDOW
|
|
|
|
HistoryDisplayCurrentHistory(PCONSRV_CONSOLE Console,
|
|
|
|
PUNICODE_STRING ExeName);
|
|
|
|
|
2014-05-02 16:46:13 +00:00
|
|
|
VOID
|
2014-08-11 20:39:06 +00:00
|
|
|
LineInputKeyDown(PCONSRV_CONSOLE Console,
|
[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 .
svn path=/branches/condrv_restructure/; revision=63793
2014-08-01 18:08:29 +00:00
|
|
|
PUNICODE_STRING ExeName,
|
|
|
|
KEY_EVENT_RECORD *KeyEvent)
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
|
|
|
UINT Pos = Console->LinePos;
|
|
|
|
UNICODE_STRING Entry;
|
2014-08-29 19:45:45 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* First, deal with control keys...
|
|
|
|
*/
|
2010-06-05 18:17:42 +00:00
|
|
|
|
|
|
|
switch (KeyEvent->wVirtualKeyCode)
|
|
|
|
{
|
2014-08-30 15:59:35 +00:00
|
|
|
case VK_ESCAPE:
|
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Clear the entire line */
|
2014-08-30 15:59:35 +00:00
|
|
|
LineInputSetPos(Console, 0);
|
|
|
|
LineInputEdit(Console, Console->LineSize, 0, NULL);
|
2014-09-07 20:05:39 +00:00
|
|
|
|
|
|
|
// TESTS!!
|
|
|
|
if (Popup)
|
|
|
|
{
|
|
|
|
DestroyPopupWindow(Popup);
|
|
|
|
Popup = NULL;
|
|
|
|
}
|
2014-08-30 15:59:35 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_HOME:
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Move to start of line. With CTRL, erase everything left of cursor. */
|
2014-08-30 15:59:35 +00:00
|
|
|
LineInputSetPos(Console, 0);
|
|
|
|
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
|
|
|
LineInputEdit(Console, Pos, 0, NULL);
|
|
|
|
return;
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
2014-08-30 15:59:35 +00:00
|
|
|
|
|
|
|
case VK_END:
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Move to end of line. With CTRL, erase everything right of cursor. */
|
2014-08-30 15:59:35 +00:00
|
|
|
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
|
|
|
LineInputEdit(Console, Console->LineSize - Pos, 0, NULL);
|
|
|
|
else
|
|
|
|
LineInputSetPos(Console, Console->LineSize);
|
|
|
|
return;
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
2014-08-30 15:59:35 +00:00
|
|
|
|
|
|
|
case VK_LEFT:
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Move to the left. With CTRL, move to beginning of previous word. */
|
2014-08-30 15:59:35 +00:00
|
|
|
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
|
|
|
{
|
|
|
|
while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--;
|
|
|
|
while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pos -= (Pos > 0);
|
|
|
|
}
|
2010-06-05 18:17:42 +00:00
|
|
|
LineInputSetPos(Console, Pos);
|
2014-08-30 15:59:35 +00:00
|
|
|
return;
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
2014-08-30 15:59:35 +00:00
|
|
|
|
|
|
|
case VK_RIGHT:
|
|
|
|
case VK_F1:
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Move to the right. With CTRL, move to beginning of next word. */
|
2014-08-30 15:59:35 +00:00
|
|
|
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
|
|
|
{
|
|
|
|
while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++;
|
|
|
|
while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++;
|
|
|
|
LineInputSetPos(Console, Pos);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Recall one character (but don't overwrite current line) */
|
|
|
|
HistoryGetCurrentEntry(Console, ExeName, &Entry);
|
|
|
|
if (Pos < Console->LineSize)
|
|
|
|
LineInputSetPos(Console, Pos + 1);
|
|
|
|
else if (Pos * sizeof(WCHAR) < Entry.Length)
|
|
|
|
LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]);
|
|
|
|
}
|
|
|
|
return;
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
2014-08-30 15:59:35 +00:00
|
|
|
|
|
|
|
case VK_INSERT:
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2014-08-30 15:59:35 +00:00
|
|
|
/* Toggle between insert and overstrike */
|
|
|
|
Console->LineInsertToggle = !Console->LineInsertToggle;
|
|
|
|
TermSetCursorInfo(Console, Console->ActiveBuffer);
|
|
|
|
return;
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
2014-08-29 19:45:45 +00:00
|
|
|
|
2014-08-30 15:59:35 +00:00
|
|
|
case VK_DELETE:
|
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Remove one character to right of cursor */
|
2014-08-30 15:59:35 +00:00
|
|
|
if (Pos != Console->LineSize)
|
|
|
|
LineInputEdit(Console, 1, 0, NULL);
|
|
|
|
return;
|
|
|
|
}
|
2014-08-29 19:45:45 +00:00
|
|
|
|
2014-08-30 15:59:35 +00:00
|
|
|
case VK_PRIOR:
|
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Recall the first history entry */
|
2014-08-30 15:59:35 +00:00
|
|
|
LineInputRecallHistory(Console, ExeName, -((WORD)-1));
|
|
|
|
return;
|
|
|
|
}
|
2014-08-29 19:45:45 +00:00
|
|
|
|
2014-08-30 15:59:35 +00:00
|
|
|
case VK_NEXT:
|
2014-08-29 19:45:45 +00:00
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Recall the last history entry */
|
2014-08-30 15:59:35 +00:00
|
|
|
LineInputRecallHistory(Console, ExeName, +((WORD)-1));
|
|
|
|
return;
|
2014-08-29 19:45:45 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 15:59:35 +00:00
|
|
|
case VK_UP:
|
|
|
|
case VK_F5:
|
|
|
|
{
|
|
|
|
/*
|
2016-06-08 00:27:25 +00:00
|
|
|
* Recall the previous history entry. On first time, actually recall
|
|
|
|
* the current (usually last) entry; on subsequent times go back.
|
2014-08-30 15:59:35 +00:00
|
|
|
*/
|
|
|
|
LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0);
|
|
|
|
Console->LineUpPressed = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2014-08-30 15:59:35 +00:00
|
|
|
case VK_DOWN:
|
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Recall the next history entry */
|
2014-08-30 15:59:35 +00:00
|
|
|
LineInputRecallHistory(Console, ExeName, +1);
|
|
|
|
return;
|
|
|
|
}
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2014-08-30 15:59:35 +00:00
|
|
|
case VK_F3:
|
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Recall the remainder of the current history entry */
|
2014-08-30 15:59:35 +00:00
|
|
|
HistoryGetCurrentEntry(Console, ExeName, &Entry);
|
|
|
|
if (Pos * sizeof(WCHAR) < Entry.Length)
|
|
|
|
{
|
|
|
|
UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos);
|
|
|
|
UINT DeleteSize = min(Console->LineSize - Pos, InsertSize);
|
|
|
|
LineInputEdit(Console, DeleteSize, InsertSize, &Entry.Buffer[Pos]);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F6:
|
|
|
|
{
|
|
|
|
/* Insert a ^Z character */
|
|
|
|
KeyEvent->uChar.UnicodeChar = 26;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F7:
|
|
|
|
{
|
|
|
|
if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
|
|
|
|
HistoryDeleteCurrentBuffer(Console, ExeName);
|
2014-09-07 20:05:39 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Popup) DestroyPopupWindow(Popup);
|
|
|
|
Popup = HistoryDisplayCurrentHistory(Console, ExeName);
|
|
|
|
}
|
2014-08-30 15:59:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-06-05 18:17:42 +00:00
|
|
|
|
2014-08-30 15:59:35 +00:00
|
|
|
case VK_F8:
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2014-08-30 15:59:35 +00:00
|
|
|
UNICODE_STRING EntryFound;
|
|
|
|
|
|
|
|
Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR)
|
|
|
|
Entry.Buffer = Console->LineBuffer;
|
|
|
|
|
|
|
|
if (HistoryFindEntryByPrefix(Console, ExeName, &Entry, &EntryFound))
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
|
|
|
LineInputEdit(Console, Console->LineSize - Pos,
|
2014-08-30 15:59:35 +00:00
|
|
|
EntryFound.Length / sizeof(WCHAR) - Pos,
|
|
|
|
&EntryFound.Buffer[Pos]);
|
2010-06-05 18:17:42 +00:00
|
|
|
/* Cursor stays where it was */
|
|
|
|
LineInputSetPos(Console, Pos);
|
|
|
|
}
|
2014-08-30 15:59:35 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
{
|
|
|
|
PHISTORY_BUFFER Hist;
|
|
|
|
INT HistPos;
|
|
|
|
|
2016-06-08 00:27:25 +00:00
|
|
|
/* Search for history entries starting with input */
|
2014-08-30 15:59:35 +00:00
|
|
|
Hist = HistoryCurrentBuffer(Console, ExeName);
|
|
|
|
if (!Hist || Hist->NumEntries == 0) return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Like Up/F5, on first time start from current (usually last) entry,
|
|
|
|
* but on subsequent times start at previous entry.
|
|
|
|
*/
|
|
|
|
if (Console->LineUpPressed)
|
|
|
|
Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1;
|
|
|
|
Console->LineUpPressed = TRUE;
|
|
|
|
|
|
|
|
Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR)
|
|
|
|
Entry.Buffer = Console->LineBuffer;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Keep going backwards, even wrapping around to the end,
|
|
|
|
* until we get back to starting point.
|
|
|
|
*/
|
|
|
|
HistPos = Hist->Position;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (RtlPrefixUnicodeString(&Entry, &Hist->Entries[HistPos], FALSE))
|
|
|
|
{
|
|
|
|
Hist->Position = HistPos;
|
|
|
|
LineInputEdit(Console, Console->LineSize - Pos,
|
|
|
|
Hist->Entries[HistPos].Length / sizeof(WCHAR) - Pos,
|
|
|
|
&Hist->Entries[HistPos].Buffer[Pos]);
|
|
|
|
/* Cursor stays where it was */
|
|
|
|
LineInputSetPos(Console, Pos);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (--HistPos < 0) HistPos += Hist->NumEntries;
|
|
|
|
} while (HistPos != Hist->Position);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2014-08-29 19:45:45 +00:00
|
|
|
#endif
|
|
|
|
|
2010-06-05 18:17:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-08-29 19:45:45 +00:00
|
|
|
|
|
|
|
/*
|
2014-08-30 15:59:35 +00:00
|
|
|
* OK, we deal with normal keys, we can continue...
|
2014-08-29 19:45:45 +00:00
|
|
|
*/
|
|
|
|
|
2016-06-08 00:27:25 +00:00
|
|
|
if (KeyEvent->uChar.UnicodeChar == L'\b' && (GetConsoleInputBufferMode(Console) & ENABLE_PROCESSED_INPUT))
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/*
|
|
|
|
* Backspace handling - if processed input enabled then we handle it
|
|
|
|
* here, otherwise we treat it like a normal character.
|
|
|
|
*/
|
2010-06-05 18:17:42 +00:00
|
|
|
if (Pos > 0)
|
|
|
|
{
|
|
|
|
LineInputSetPos(Console, Pos - 1);
|
|
|
|
LineInputEdit(Console, 1, 0, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (KeyEvent->uChar.UnicodeChar == L'\r')
|
|
|
|
{
|
2016-06-08 00:27:25 +00:00
|
|
|
/*
|
|
|
|
* Only add a history entry if console echo is enabled. This ensures
|
|
|
|
* that anything sent to the console when echo is disabled (e.g.
|
|
|
|
* binary data, or secrets like passwords...) does not remain stored
|
|
|
|
* in memory.
|
|
|
|
*/
|
|
|
|
if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT)
|
|
|
|
{
|
|
|
|
Entry.Length = Entry.MaximumLength = Console->LineSize * sizeof(WCHAR);
|
|
|
|
Entry.Buffer = Console->LineBuffer;
|
|
|
|
HistoryAddEntry(Console, ExeName, &Entry);
|
|
|
|
}
|
2010-06-05 18:17:42 +00:00
|
|
|
|
|
|
|
/* TODO: Expand aliases */
|
2014-08-29 19:45:45 +00:00
|
|
|
DPRINT1("TODO: Expand aliases\n");
|
2010-06-05 18:17:42 +00:00
|
|
|
|
|
|
|
LineInputSetPos(Console, Console->LineSize);
|
|
|
|
Console->LineBuffer[Console->LineSize++] = L'\r';
|
2014-09-07 20:05:39 +00:00
|
|
|
if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT)
|
2013-05-29 00:29:07 +00:00
|
|
|
{
|
|
|
|
if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
|
|
|
|
{
|
2014-08-29 19:54:10 +00:00
|
|
|
TermWriteStream(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\r", 1, TRUE);
|
2013-05-29 00:29:07 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-08 06:38:14 +00:00
|
|
|
|
2014-08-29 19:45:45 +00:00
|
|
|
/*
|
|
|
|
* Add \n if processed input. There should usually be room for it,
|
2016-06-08 00:27:25 +00:00
|
|
|
* but an exception to the rule exists: the buffer could have been
|
2014-08-29 19:45:45 +00:00
|
|
|
* pre-filled with LineMaxSize - 1 characters.
|
|
|
|
*/
|
2016-06-08 00:27:25 +00:00
|
|
|
if ((GetConsoleInputBufferMode(Console) & ENABLE_PROCESSED_INPUT) &&
|
2010-06-08 06:38:14 +00:00
|
|
|
Console->LineSize < Console->LineMaxSize)
|
2010-06-05 18:17:42 +00:00
|
|
|
{
|
|
|
|
Console->LineBuffer[Console->LineSize++] = L'\n';
|
2014-09-07 20:05:39 +00:00
|
|
|
if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT)
|
2013-05-29 00:29:07 +00:00
|
|
|
{
|
|
|
|
if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
|
|
|
|
{
|
2014-08-29 19:54:10 +00:00
|
|
|
TermWriteStream(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\n", 1, TRUE);
|
2013-05-29 00:29:07 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
|
|
|
Console->LineComplete = TRUE;
|
|
|
|
Console->LinePos = 0;
|
|
|
|
}
|
|
|
|
else if (KeyEvent->uChar.UnicodeChar != L'\0')
|
|
|
|
{
|
2010-06-08 06:38:14 +00:00
|
|
|
if (KeyEvent->uChar.UnicodeChar < 0x20 &&
|
|
|
|
Console->LineWakeupMask & (1 << KeyEvent->uChar.UnicodeChar))
|
|
|
|
{
|
|
|
|
/* Control key client wants to handle itself (e.g. for tab completion) */
|
|
|
|
Console->LineBuffer[Console->LineSize++] = L' ';
|
|
|
|
Console->LineBuffer[Console->LinePos] = KeyEvent->uChar.UnicodeChar;
|
|
|
|
Console->LineComplete = TRUE;
|
|
|
|
Console->LinePos = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Normal character */
|
2014-04-10 20:24:49 +00:00
|
|
|
BOOL Overstrike = !Console->LineInsertToggle && (Console->LinePos != Console->LineSize);
|
2014-09-07 20:05:39 +00:00
|
|
|
DPRINT("Overstrike = %s\n", Overstrike ? "true" : "false");
|
2014-04-10 20:24:49 +00:00
|
|
|
LineInputEdit(Console, (Overstrike ? 1 : 0), 1, &KeyEvent->uChar.UnicodeChar);
|
2010-06-08 06:38:14 +00:00
|
|
|
}
|
2010-06-05 18:17:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-19 22:05:38 +00:00
|
|
|
|
|
|
|
/* PUBLIC SERVER APIS *********************************************************/
|
|
|
|
|
2010-06-05 18:17:42 +00:00
|
|
|
/* EOF */
|