https://git.reactos.org/?p=reactos.git;a=commitdiff;h=19596768cb12cfbf97937…
commit 19596768cb12cfbf97937497f6952f54e0e2c116
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sat Feb 29 17:35:57 2020 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon Mar 2 01:08:35 2020 +0100
[CONSRV] Support history resizing from console settings and from
SetConsoleHistoryInfo() server implementation.
In addition, honour the maximum number of history buffers allowed when
creating new ones.
Some implementation information has been obtained from
https://github.com/microsoft/terminal
(under MIT License).
---
win32ss/user/winsrv/consrv/console.c | 7 +-
.../user/winsrv/consrv/frontends/gui/guisettings.c | 14 +-
win32ss/user/winsrv/consrv/history.c | 215 ++++++++++++++-------
win32ss/user/winsrv/consrv/history.h | 7 +
win32ss/user/winsrv/consrv/include/conio_winsrv.h | 3 +-
win32ss/user/winsrv/consrv/lineinput.c | 2 +
win32ss/user/winsrv/consrv/settings.c | 8 +-
7 files changed, 174 insertions(+), 82 deletions(-)
diff --git a/win32ss/user/winsrv/consrv/console.c b/win32ss/user/winsrv/consrv/console.c
index ea39840cfdc..8b50465bfad 100644
--- a/win32ss/user/winsrv/consrv/console.c
+++ b/win32ss/user/winsrv/consrv/console.c
@@ -697,9 +697,10 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
/* Initialize the alias and history buffers */
Console->Aliases = NULL;
InitializeListHead(&Console->HistoryBuffers);
- Console->HistoryBufferSize = ConsoleInfo->HistoryBufferSize;
- Console->NumberOfHistoryBuffers = ConsoleInfo->NumberOfHistoryBuffers;
- Console->HistoryNoDup = ConsoleInfo->HistoryNoDup;
+ Console->NumberOfHistoryBuffers = 0;
+ Console->MaxNumberOfHistoryBuffers = ConsoleInfo->NumberOfHistoryBuffers;
+ Console->HistoryBufferSize = ConsoleInfo->HistoryBufferSize;
+ Console->HistoryNoDup = ConsoleInfo->HistoryNoDup;
/* Initialize the Input Line Discipline */
Console->LineBuffer = NULL;
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
b/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
index 912bc9d2f41..1ee89ed8a47 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
+++ b/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
@@ -132,11 +132,11 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
pSharedInfo->hWnd = GuiData->hWindow;
/* Console information */
- pSharedInfo->HistoryBufferSize = Console->HistoryBufferSize;
- pSharedInfo->NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
- pSharedInfo->HistoryNoDup = Console->HistoryNoDup;
pSharedInfo->QuickEdit = Console->QuickEdit;
pSharedInfo->InsertMode = Console->InsertMode;
+ pSharedInfo->NumberOfHistoryBuffers = Console->MaxNumberOfHistoryBuffers;
+ pSharedInfo->HistoryBufferSize = Console->HistoryBufferSize;
+ pSharedInfo->HistoryNoDup = Console->HistoryNoDup;
/// pSharedInfo->InputBufferSize = 0;
pSharedInfo->ScreenBufferSize = ActiveBuffer->ScreenBufferSize;
pSharedInfo->WindowSize = ActiveBuffer->ViewSize;
@@ -154,7 +154,7 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
// FIXME: Gather defaults from the registry ?
pSharedInfo->ScreenAttributes = DEFAULT_SCREEN_ATTRIB;
- pSharedInfo->PopupAttributes = DEFAULT_POPUP_ATTRIB ;
+ pSharedInfo->PopupAttributes = DEFAULT_POPUP_ATTRIB;
}
/* We display the output code page only */
@@ -315,12 +315,6 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
/* Retrieve terminal informations */
/* Console information */
-#if 0 // FIXME: Things not set
- ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize;
- ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers;
- ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup;
- ConInfo.CodePage = pConInfo->CodePage; // Done in ConSrvApplyUserSettings
-#endif
/*
* Apply the settings
diff --git a/win32ss/user/winsrv/consrv/history.c b/win32ss/user/winsrv/consrv/history.c
index 7e28aa83247..d9fd38e8dd9 100644
--- a/win32ss/user/winsrv/consrv/history.c
+++ b/win32ss/user/winsrv/consrv/history.c
@@ -44,35 +44,52 @@ ConvertInputUnicodeToAnsi(PCONSRV_CONSOLE Console,
/* PRIVATE FUNCTIONS **********************************************************/
static PHISTORY_BUFFER
-HistoryCurrentBuffer(PCONSRV_CONSOLE Console,
- PUNICODE_STRING ExeName)
+HistoryCurrentBuffer(
+ IN PCONSRV_CONSOLE Console,
+ IN PUNICODE_STRING ExeName)
{
- PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
+ PLIST_ENTRY Entry;
PHISTORY_BUFFER Hist;
- for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
+ for (Entry = Console->HistoryBuffers.Flink;
+ Entry != &Console->HistoryBuffers;
+ Entry = Entry->Flink)
{
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE))
return Hist;
}
- /* Couldn't find the buffer, create a new one */
- Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length);
- if (!Hist) return NULL;
- Hist->MaxEntries = Console->HistoryBufferSize;
- Hist->NumEntries = 0;
- Hist->Entries = ConsoleAllocHeap(0, Hist->MaxEntries *
sizeof(UNICODE_STRING));
- if (!Hist->Entries)
+ /* Could not find the buffer, create a new one */
+
+ if (Console->NumberOfHistoryBuffers < Console->MaxNumberOfHistoryBuffers)
+ {
+ Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length);
+ if (!Hist) return NULL;
+ Hist->MaxEntries = Console->HistoryBufferSize;
+ Hist->NumEntries = 0;
+ Hist->Entries = ConsoleAllocHeap(0, Hist->MaxEntries *
sizeof(UNICODE_STRING));
+ if (!Hist->Entries)
+ {
+ ConsoleFreeHeap(Hist);
+ return NULL;
+ }
+ Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length;
+ Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
+ RtlCopyMemory(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length);
+ InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
+ Console->NumberOfHistoryBuffers++;
+ return Hist;
+ }
+ else
{
- ConsoleFreeHeap(Hist);
+ // FIXME: TODO !!!!!!!
+ // Reuse an older history buffer, if possible with the same Exe name,
+ // otherwise take the oldest one and reset its contents.
+ // And move the history buffer back to the head of the list.
+ UNIMPLEMENTED;
return NULL;
}
- Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length;
- Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
- memcpy(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length);
- InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
- return Hist;
}
static PHISTORY_BUFFER
@@ -105,8 +122,9 @@ HistoryFindBuffer(PCONSRV_CONSOLE Console,
}
ExeNameU.Length = ExeNameU.MaximumLength;
- Entry = Console->HistoryBuffers.Flink;
- while (Entry != &Console->HistoryBuffers)
+ for (Entry = Console->HistoryBuffers.Flink;
+ Entry != &Console->HistoryBuffers;
+ Entry = Entry->Flink)
{
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
@@ -116,8 +134,6 @@ HistoryFindBuffer(PCONSRV_CONSOLE Console,
if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
return Hist;
}
-
- Entry = Entry->Flink;
}
if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
@@ -137,6 +153,34 @@ HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
ConsoleFreeHeap(Hist);
}
+static NTSTATUS
+HistoryResizeBuffer(
+ IN PHISTORY_BUFFER Hist,
+ IN ULONG NumCommands)
+{
+ PUNICODE_STRING OldEntryList = Hist->Entries;
+ PUNICODE_STRING NewEntryList;
+
+ NewEntryList = ConsoleAllocHeap(0, NumCommands * sizeof(UNICODE_STRING));
+ if (!NewEntryList)
+ return STATUS_NO_MEMORY;
+
+ /* If necessary, shrink by removing oldest entries */
+ for (; Hist->NumEntries > NumCommands; Hist->NumEntries--)
+ {
+ RtlFreeUnicodeString(Hist->Entries++);
+ Hist->Position += (Hist->Position == 0);
+ }
+
+ Hist->MaxEntries = NumCommands;
+ RtlCopyMemory(NewEntryList, Hist->Entries,
+ Hist->NumEntries * sizeof(UNICODE_STRING));
+ Hist->Entries = NewEntryList;
+ ConsoleFreeHeap(OldEntryList);
+
+ return STATUS_SUCCESS;
+}
+
VOID
HistoryAddEntry(PCONSRV_CONSOLE Console,
PUNICODE_STRING ExeName,
@@ -171,8 +215,8 @@ HistoryAddEntry(PCONSRV_CONSOLE Console,
/* Just rotate the list to bring this entry to the end */
NewEntry = Hist->Entries[i];
- memmove(&Hist->Entries[i], &Hist->Entries[i + 1],
- (Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING));
+ RtlMoveMemory(&Hist->Entries[i], &Hist->Entries[i + 1],
+ (Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING));
Hist->Entries[Hist->NumEntries - 1] = NewEntry;
Hist->Position = Hist->NumEntries - 1;
return;
@@ -184,8 +228,8 @@ HistoryAddEntry(PCONSRV_CONSOLE Console,
{
/* List is full, remove oldest entry */
RtlFreeUnicodeString(&Hist->Entries[0]);
- memmove(&Hist->Entries[0], &Hist->Entries[1],
- --Hist->NumEntries * sizeof(UNICODE_STRING));
+ RtlMoveMemory(&Hist->Entries[0], &Hist->Entries[1],
+ --Hist->NumEntries * sizeof(UNICODE_STRING));
}
if (NT_SUCCESS(RtlDuplicateUnicodeString(0, Entry,
&Hist->Entries[Hist->NumEntries])))
@@ -323,6 +367,58 @@ HistoryDeleteBuffers(PCONSRV_CONSOLE Console)
}
}
+VOID
+HistoryReshapeAllBuffers(
+ IN PCONSRV_CONSOLE Console,
+ IN ULONG HistoryBufferSize,
+ IN ULONG MaxNumberOfHistoryBuffers,
+ IN BOOLEAN HistoryNoDup)
+{
+ PLIST_ENTRY Entry;
+ PHISTORY_BUFFER Hist;
+ NTSTATUS Status;
+
+ // ASSERT(Console->NumberOfHistoryBuffers <=
Console->MaxNumberOfHistoryBuffers);
+ if (MaxNumberOfHistoryBuffers < Console->NumberOfHistoryBuffers)
+ {
+ /*
+ * Trim the history buffers list and reduce it up to MaxNumberOfHistoryBuffers.
+ * We loop the history buffers list backwards so as to trim the oldest
+ * buffers first.
+ */
+ while (!IsListEmpty(&Console->HistoryBuffers) &&
+ (Console->NumberOfHistoryBuffers > MaxNumberOfHistoryBuffers))
+ {
+ Entry = RemoveTailList(&Console->HistoryBuffers);
+ Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
+ HistoryDeleteBuffer(Hist);
+ Console->NumberOfHistoryBuffers--;
+ }
+ ASSERT(Console->NumberOfHistoryBuffers == MaxNumberOfHistoryBuffers);
+ ASSERT(((Console->NumberOfHistoryBuffers == 0) &&
IsListEmpty(&Console->HistoryBuffers)) ||
+ ((Console->NumberOfHistoryBuffers > 0) &&
!IsListEmpty(&Console->HistoryBuffers)));
+ }
+ Console->MaxNumberOfHistoryBuffers = MaxNumberOfHistoryBuffers;
+
+ /* Resize each history buffer */
+ for (Entry = Console->HistoryBuffers.Flink;
+ Entry != &Console->HistoryBuffers;
+ Entry = Entry->Flink)
+ {
+ Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
+ Status = HistoryResizeBuffer(Hist, HistoryBufferSize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("HistoryResizeBuffer(0x%p, %lu) failed, Status 0x%08lx\n",
+ Hist, HistoryBufferSize, Status);
+ }
+ }
+ Console->HistoryBufferSize = HistoryBufferSize;
+
+ /* No duplicates */
+ Console->HistoryNoDup = !!HistoryNoDup;
+}
+
/* PUBLIC SERVER APIS *********************************************************/
@@ -516,27 +612,7 @@ CSR_API(SrvSetConsoleNumberOfCommands)
SetHistoryNumberCommandsRequest->Unicode2);
if (Hist)
{
- ULONG MaxEntries = SetHistoryNumberCommandsRequest->NumCommands;
- PUNICODE_STRING OldEntryList = Hist->Entries;
- PUNICODE_STRING NewEntryList = ConsoleAllocHeap(0, MaxEntries *
sizeof(UNICODE_STRING));
- if (!NewEntryList)
- {
- Status = STATUS_NO_MEMORY;
- }
- else
- {
- /* If necessary, shrink by removing oldest entries */
- for (; Hist->NumEntries > MaxEntries; Hist->NumEntries--)
- {
- RtlFreeUnicodeString(Hist->Entries++);
- Hist->Position += (Hist->Position == 0);
- }
-
- Hist->MaxEntries = MaxEntries;
- Hist->Entries = memcpy(NewEntryList, Hist->Entries,
- Hist->NumEntries * sizeof(UNICODE_STRING));
- ConsoleFreeHeap(OldEntryList);
- }
+ Status = HistoryResizeBuffer(Hist,
SetHistoryNumberCommandsRequest->NumCommands);
}
ConSrvReleaseConsole(Console, TRUE);
@@ -546,18 +622,20 @@ CSR_API(SrvSetConsoleNumberOfCommands)
/* API_NUMBER: ConsolepGetHistory */
CSR_API(SrvGetConsoleHistory)
{
-#if 0 // Vista+
+#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+ NTSTATUS Status;
PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest;
PCONSRV_CONSOLE Console;
- NTSTATUS Status =
ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- &Console, TRUE);
- if (NT_SUCCESS(Status))
- {
- HistoryInfoRequest->HistoryBufferSize = Console->HistoryBufferSize;
- HistoryInfoRequest->NumberOfHistoryBuffers =
Console->NumberOfHistoryBuffers;
- HistoryInfoRequest->dwFlags = (Console->HistoryNoDup ?
HISTORY_NO_DUP_FLAG : 0);
- ConSrvReleaseConsole(Console, TRUE);
- }
+
+ Status =
ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ HistoryInfoRequest->HistoryBufferSize = Console->HistoryBufferSize;
+ HistoryInfoRequest->NumberOfHistoryBuffers =
Console->MaxNumberOfHistoryBuffers;
+ HistoryInfoRequest->dwFlags = (Console->HistoryNoDup ?
HISTORY_NO_DUP_FLAG : 0);
+
+ ConSrvReleaseConsole(Console, TRUE);
return Status;
#else
DPRINT1("%s not yet implemented\n", __FUNCTION__);
@@ -568,19 +646,22 @@ CSR_API(SrvGetConsoleHistory)
/* API_NUMBER: ConsolepSetHistory */
CSR_API(SrvSetConsoleHistory)
{
-#if 0 // Vista+
+#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+ NTSTATUS Status;
PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest;
PCONSRV_CONSOLE Console;
- NTSTATUS Status =
ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- &Console, TRUE);
- if (NT_SUCCESS(Status))
- {
- Console->HistoryBufferSize = HistoryInfoRequest->HistoryBufferSize;
- Console->NumberOfHistoryBuffers =
HistoryInfoRequest->NumberOfHistoryBuffers;
- Console->HistoryNoDup = !!(HistoryInfoRequest->dwFlags &
HISTORY_NO_DUP_FLAG);
- ConSrvReleaseConsole(Console, TRUE);
- }
- return Status;
+
+ Status =
ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ HistoryReshapeAllBuffers(Console,
+ HistoryInfoRequest->HistoryBufferSize,
+ HistoryInfoRequest->NumberOfHistoryBuffers,
+ !!(HistoryInfoRequest->dwFlags &
HISTORY_NO_DUP_FLAG));
+
+ ConSrvReleaseConsole(Console, TRUE);
+ return STATUS_SUCCESS;
#else
DPRINT1("%s not yet implemented\n", __FUNCTION__);
return STATUS_NOT_IMPLEMENTED;
diff --git a/win32ss/user/winsrv/consrv/history.h b/win32ss/user/winsrv/consrv/history.h
index 1b3833f23c0..c3ee78a4a7e 100644
--- a/win32ss/user/winsrv/consrv/history.h
+++ b/win32ss/user/winsrv/consrv/history.h
@@ -9,3 +9,10 @@
#pragma once
VOID HistoryDeleteBuffers(PCONSRV_CONSOLE Console);
+
+VOID
+HistoryReshapeAllBuffers(
+ IN PCONSRV_CONSOLE Console,
+ IN ULONG HistoryBufferSize,
+ IN ULONG MaxNumberOfHistoryBuffers,
+ IN BOOLEAN HistoryNoDup);
diff --git a/win32ss/user/winsrv/consrv/include/conio_winsrv.h
b/win32ss/user/winsrv/consrv/include/conio_winsrv.h
index 79e0c042774..5057a31e4ad 100644
--- a/win32ss/user/winsrv/consrv/include/conio_winsrv.h
+++ b/win32ss/user/winsrv/consrv/include/conio_winsrv.h
@@ -159,8 +159,9 @@ typedef struct _WINSRV_CONSOLE
/**************************** Aliases and Histories ***************************/
struct _ALIAS_HEADER *Aliases;
LIST_ENTRY HistoryBuffers;
+ ULONG NumberOfHistoryBuffers; /* Number of history buffers */
+ ULONG MaxNumberOfHistoryBuffers; /* Maximum number of history buffers allowed
*/
ULONG HistoryBufferSize; /* Size for newly created history buffers */
- ULONG NumberOfHistoryBuffers; /* Maximum number of history buffers allowed
*/
BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */
/**************************** Input Line Discipline ***************************/
diff --git a/win32ss/user/winsrv/consrv/lineinput.c
b/win32ss/user/winsrv/consrv/lineinput.c
index 2aab09254ef..32d799531f6 100644
--- a/win32ss/user/winsrv/consrv/lineinput.c
+++ b/win32ss/user/winsrv/consrv/lineinput.c
@@ -323,7 +323,9 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
case VK_F7:
{
if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED |
RIGHT_ALT_PRESSED))
+ {
HistoryDeleteCurrentBuffer(Console, ExeName);
+ }
else
{
if (Popup) DestroyPopupWindow(Popup);
diff --git a/win32ss/user/winsrv/consrv/settings.c
b/win32ss/user/winsrv/consrv/settings.c
index 879c152d4d1..fdfc4cb9468 100644
--- a/win32ss/user/winsrv/consrv/settings.c
+++ b/win32ss/user/winsrv/consrv/settings.c
@@ -10,6 +10,7 @@
/* INCLUDES *******************************************************************/
#include "consrv.h"
+#include "history.h"
#include "../concfg/font.h"
#define NDEBUG
@@ -40,10 +41,15 @@ ConSrvApplyUserSettings(IN PCONSOLE Console,
/*
* Apply terminal-edition settings:
* - QuickEdit and Insert modes,
- * - history settings.
+ * - History settings.
*/
Console->QuickEdit = !!ConsoleInfo->QuickEdit;
Console->InsertMode = !!ConsoleInfo->InsertMode;
+ /// Console->InputBufferSize = 0;
+ HistoryReshapeAllBuffers(Console,
+ ConsoleInfo->HistoryBufferSize,
+ ConsoleInfo->NumberOfHistoryBuffers,
+ ConsoleInfo->HistoryNoDup);
/* Copy the new console palette */
// FIXME: Possible buffer overflow if s_colors is bigger than
ConsoleInfo->ColorTable.