mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 19:42:57 +00:00
[CONSRV]
Commit my work that I've done during my trip from Albi back to Paris (part 1/2): - QuickEdit and InsertMode are input modes that are related to CONSRV terminal(s), therefore remove them from CONDRV that needs to be agnostic about terminal specificities. - Separate history helper functions from the line discipline functions to different files. svn path=/branches/condrv_restructure/; revision=63978
This commit is contained in:
parent
89524de4be
commit
742f7ebd4b
10 changed files with 764 additions and 543 deletions
|
@ -11,6 +11,7 @@ list(APPEND CONSRV_SOURCE
|
||||||
consrv/console.c
|
consrv/console.c
|
||||||
consrv/frontendctl.c
|
consrv/frontendctl.c
|
||||||
consrv/handle.c
|
consrv/handle.c
|
||||||
|
consrv/history.c
|
||||||
consrv/init.c
|
consrv/init.c
|
||||||
consrv/lineinput.c
|
consrv/lineinput.c
|
||||||
consrv/settings.c
|
consrv/settings.c
|
||||||
|
|
|
@ -18,16 +18,16 @@
|
||||||
|
|
||||||
typedef struct _ALIAS_ENTRY
|
typedef struct _ALIAS_ENTRY
|
||||||
{
|
{
|
||||||
|
struct _ALIAS_ENTRY* Next;
|
||||||
UNICODE_STRING Source;
|
UNICODE_STRING Source;
|
||||||
UNICODE_STRING Target;
|
UNICODE_STRING Target;
|
||||||
struct _ALIAS_ENTRY* Next;
|
|
||||||
} ALIAS_ENTRY, *PALIAS_ENTRY;
|
} ALIAS_ENTRY, *PALIAS_ENTRY;
|
||||||
|
|
||||||
typedef struct _ALIAS_HEADER
|
typedef struct _ALIAS_HEADER
|
||||||
{
|
{
|
||||||
|
struct _ALIAS_HEADER* Next;
|
||||||
UNICODE_STRING ExeName;
|
UNICODE_STRING ExeName;
|
||||||
PALIAS_ENTRY Data;
|
PALIAS_ENTRY Data;
|
||||||
struct _ALIAS_HEADER* Next;
|
|
||||||
} ALIAS_HEADER, *PALIAS_HEADER;
|
} ALIAS_HEADER, *PALIAS_HEADER;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -257,13 +257,6 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole,
|
||||||
Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
|
Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
|
||||||
ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
|
ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
|
||||||
|
|
||||||
Console->InsertMode = ConsoleInfo->InsertMode;
|
|
||||||
Console->LineBuffer = NULL;
|
|
||||||
Console->LinePos = Console->LineMaxSize = Console->LineSize = 0;
|
|
||||||
Console->LineComplete = Console->LineUpPressed = FALSE;
|
|
||||||
Console->LineInsertToggle = Console->InsertMode;
|
|
||||||
// LineWakeupMask
|
|
||||||
|
|
||||||
/* Set-up the code page */
|
/* Set-up the code page */
|
||||||
Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
|
Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
|
||||||
|
|
||||||
|
@ -518,17 +511,7 @@ ConDrvGetConsoleMode(IN PCONSOLE Console,
|
||||||
if (INPUT_BUFFER == Object->Type)
|
if (INPUT_BUFFER == Object->Type)
|
||||||
{
|
{
|
||||||
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
|
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
|
||||||
|
|
||||||
*ConsoleMode = InputBuffer->Mode;
|
*ConsoleMode = InputBuffer->Mode;
|
||||||
|
|
||||||
if (Console->QuickEdit || Console->InsertMode)
|
|
||||||
{
|
|
||||||
// Windows does this, even if it's not documented on MSDN
|
|
||||||
*ConsoleMode |= ENABLE_EXTENDED_FLAGS;
|
|
||||||
|
|
||||||
if (Console->QuickEdit ) *ConsoleMode |= ENABLE_QUICK_EDIT_MODE;
|
|
||||||
if (Console->InsertMode) *ConsoleMode |= ENABLE_INSERT_MODE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
|
else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
|
||||||
{
|
{
|
||||||
|
@ -548,8 +531,6 @@ ConDrvSetConsoleMode(IN PCONSOLE Console,
|
||||||
IN PCONSOLE_IO_OBJECT Object,
|
IN PCONSOLE_IO_OBJECT Object,
|
||||||
IN ULONG ConsoleMode)
|
IN ULONG ConsoleMode)
|
||||||
{
|
{
|
||||||
#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | \
|
|
||||||
ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE )
|
|
||||||
#define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
|
#define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
|
||||||
ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
|
ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
|
||||||
ENABLE_MOUSE_INPUT )
|
ENABLE_MOUSE_INPUT )
|
||||||
|
@ -567,45 +548,21 @@ ConDrvSetConsoleMode(IN PCONSOLE Console,
|
||||||
{
|
{
|
||||||
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
|
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
|
||||||
|
|
||||||
DPRINT("SetConsoleMode(Input, %d)\n", ConsoleMode);
|
/* Only the presence of valid mode flags is allowed */
|
||||||
|
if (ConsoleMode & ~CONSOLE_VALID_INPUT_MODES)
|
||||||
/*
|
|
||||||
* 1. Only the presence of valid mode flags is allowed.
|
|
||||||
*/
|
|
||||||
if (ConsoleMode & ~(CONSOLE_VALID_INPUT_MODES | CONSOLE_VALID_CONTROL_MODES))
|
|
||||||
{
|
{
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
goto Quit;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/*
|
|
||||||
* 2. If we use control mode flags without ENABLE_EXTENDED_FLAGS,
|
|
||||||
* then consider the flags invalid.
|
|
||||||
*
|
|
||||||
if ( (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) &&
|
|
||||||
(ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0 )
|
|
||||||
{
|
{
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
|
||||||
goto Quit;
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3. Now we can continue.
|
|
||||||
*/
|
|
||||||
if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
|
|
||||||
{
|
|
||||||
Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
|
|
||||||
Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
|
|
||||||
}
|
|
||||||
InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
|
|
||||||
}
|
}
|
||||||
else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
|
else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
|
||||||
{
|
{
|
||||||
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
|
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
|
||||||
|
|
||||||
DPRINT("SetConsoleMode(Output, %d)\n", ConsoleMode);
|
/* Only the presence of valid mode flags is allowed */
|
||||||
|
|
||||||
if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
|
if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
|
||||||
{
|
{
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
@ -620,7 +577,6 @@ ConDrvSetConsoleMode(IN PCONSOLE Console,
|
||||||
Status = STATUS_INVALID_HANDLE;
|
Status = STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quit:
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <ndk/psfuncs.h>
|
#include <ndk/psfuncs.h>
|
||||||
|
|
||||||
#include <alias.h>
|
#include <alias.h>
|
||||||
|
#include <history.h>
|
||||||
#include "procinit.h"
|
#include "procinit.h"
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
@ -427,7 +428,14 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
||||||
Console->NumberOfHistoryBuffers = ConsoleInfo.NumberOfHistoryBuffers;
|
Console->NumberOfHistoryBuffers = ConsoleInfo.NumberOfHistoryBuffers;
|
||||||
Console->HistoryNoDup = ConsoleInfo.HistoryNoDup;
|
Console->HistoryNoDup = ConsoleInfo.HistoryNoDup;
|
||||||
|
|
||||||
Console->QuickEdit = ConsoleInfo.QuickEdit;
|
/* Initialize the Input Line Discipline */
|
||||||
|
Console->LineBuffer = NULL;
|
||||||
|
Console->LinePos = Console->LineMaxSize = Console->LineSize = 0;
|
||||||
|
Console->LineComplete = Console->LineUpPressed = FALSE;
|
||||||
|
// LineWakeupMask
|
||||||
|
Console->LineInsertToggle =
|
||||||
|
Console->InsertMode = ConsoleInfo.InsertMode;
|
||||||
|
Console->QuickEdit = ConsoleInfo.QuickEdit;
|
||||||
|
|
||||||
/* Colour table */
|
/* Colour table */
|
||||||
memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors));
|
memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors));
|
||||||
|
@ -755,13 +763,34 @@ CSR_API(SrvGetConsoleMode)
|
||||||
PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
|
PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
|
||||||
PCONSOLE_IO_OBJECT Object;
|
PCONSOLE_IO_OBJECT Object;
|
||||||
|
|
||||||
|
PULONG ConsoleMode = &ConsoleModeRequest->Mode;
|
||||||
|
|
||||||
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||||
ConsoleModeRequest->Handle,
|
ConsoleModeRequest->Handle,
|
||||||
&Object, NULL, GENERIC_READ, TRUE, 0);
|
&Object, NULL, GENERIC_READ, TRUE, 0);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* Get the standard console modes */
|
||||||
Status = ConDrvGetConsoleMode(Object->Console, Object,
|
Status = ConDrvGetConsoleMode(Object->Console, Object,
|
||||||
&ConsoleModeRequest->Mode);
|
ConsoleMode);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If getting the console modes succeeds, then retrieve
|
||||||
|
* the extended CONSRV-specific input modes.
|
||||||
|
*/
|
||||||
|
if (INPUT_BUFFER == Object->Type)
|
||||||
|
{
|
||||||
|
if (Object->Console->InsertMode || Object->Console->QuickEdit)
|
||||||
|
{
|
||||||
|
/* Windows does this, even if it is not documented on MSDN */
|
||||||
|
*ConsoleMode |= ENABLE_EXTENDED_FLAGS;
|
||||||
|
|
||||||
|
if (Object->Console->InsertMode) *ConsoleMode |= ENABLE_INSERT_MODE;
|
||||||
|
if (Object->Console->QuickEdit ) *ConsoleMode |= ENABLE_QUICK_EDIT_MODE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConSrvReleaseObject(Object, TRUE);
|
ConSrvReleaseObject(Object, TRUE);
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -773,17 +802,52 @@ ConDrvSetConsoleMode(IN PCONSOLE Console,
|
||||||
IN ULONG ConsoleMode);
|
IN ULONG ConsoleMode);
|
||||||
CSR_API(SrvSetConsoleMode)
|
CSR_API(SrvSetConsoleMode)
|
||||||
{
|
{
|
||||||
|
#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | \
|
||||||
|
ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE )
|
||||||
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
|
PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
|
||||||
PCONSOLE_IO_OBJECT Object;
|
PCONSOLE_IO_OBJECT Object;
|
||||||
|
|
||||||
|
ULONG ConsoleMode = ConsoleModeRequest->Mode;
|
||||||
|
|
||||||
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||||
ConsoleModeRequest->Handle,
|
ConsoleModeRequest->Handle,
|
||||||
&Object, NULL, GENERIC_WRITE, TRUE, 0);
|
&Object, NULL, GENERIC_WRITE, TRUE, 0);
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* Set the standard console modes (without the CONSRV-specific input modes) */
|
||||||
|
ConsoleMode &= ~CONSOLE_VALID_CONTROL_MODES; // Remove CONSRV-specific input modes.
|
||||||
Status = ConDrvSetConsoleMode(Object->Console, Object,
|
Status = ConDrvSetConsoleMode(Object->Console, Object,
|
||||||
ConsoleModeRequest->Mode);
|
ConsoleMode);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If setting the console modes succeeds, then set
|
||||||
|
* the extended CONSRV-specific input modes.
|
||||||
|
*/
|
||||||
|
if (INPUT_BUFFER == Object->Type)
|
||||||
|
{
|
||||||
|
ConsoleMode = ConsoleModeRequest->Mode;
|
||||||
|
|
||||||
|
if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If we use control mode flags without ENABLE_EXTENDED_FLAGS,
|
||||||
|
* then consider the flags invalid.
|
||||||
|
*/
|
||||||
|
if ((ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0)
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Object->Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
|
||||||
|
Object->Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConSrvReleaseObject(Object, TRUE);
|
ConSrvReleaseObject(Object, TRUE);
|
||||||
return Status;
|
return Status;
|
||||||
|
|
561
win32ss/user/winsrv/consrv/history.c
Normal file
561
win32ss/user/winsrv/consrv/history.c
Normal file
|
@ -0,0 +1,561 @@
|
||||||
|
/*
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Console Server DLL
|
||||||
|
* FILE: win32ss/user/winsrv/consrv/history.c
|
||||||
|
* PURPOSE: Console line input functions
|
||||||
|
* PROGRAMMERS: Jeffrey Morlan
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#include "consrv.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
typedef struct _HISTORY_BUFFER
|
||||||
|
{
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
ULONG Position;
|
||||||
|
ULONG MaxEntries;
|
||||||
|
ULONG NumEntries;
|
||||||
|
UNICODE_STRING ExeName;
|
||||||
|
PUNICODE_STRING Entries;
|
||||||
|
} HISTORY_BUFFER, *PHISTORY_BUFFER;
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
ConvertInputAnsiToUnicode(PCONSOLE Console,
|
||||||
|
PVOID Source,
|
||||||
|
USHORT SourceLength,
|
||||||
|
// BOOLEAN IsUnicode,
|
||||||
|
PWCHAR* Target,
|
||||||
|
PUSHORT TargetLength);
|
||||||
|
BOOLEAN
|
||||||
|
ConvertInputUnicodeToAnsi(PCONSOLE Console,
|
||||||
|
PVOID Source,
|
||||||
|
USHORT SourceLength,
|
||||||
|
// BOOLEAN IsAnsi,
|
||||||
|
PCHAR/* * */ Target,
|
||||||
|
/*P*/USHORT TargetLength);
|
||||||
|
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
static PHISTORY_BUFFER
|
||||||
|
HistoryCurrentBuffer(PCONSRV_CONSOLE Console,
|
||||||
|
PUNICODE_STRING ExeName)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
|
||||||
|
PHISTORY_BUFFER Hist;
|
||||||
|
|
||||||
|
for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
|
||||||
|
{
|
||||||
|
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
|
||||||
|
if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE))
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ConsoleFreeHeap(Hist);
|
||||||
|
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
|
||||||
|
HistoryFindBuffer(PCONSRV_CONSOLE Console,
|
||||||
|
PVOID ExeName,
|
||||||
|
USHORT ExeLength,
|
||||||
|
BOOLEAN UnicodeExe)
|
||||||
|
{
|
||||||
|
UNICODE_STRING ExeNameU;
|
||||||
|
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PHISTORY_BUFFER Hist = NULL;
|
||||||
|
|
||||||
|
if (ExeName == NULL) return NULL;
|
||||||
|
|
||||||
|
if (UnicodeExe)
|
||||||
|
{
|
||||||
|
ExeNameU.Buffer = ExeName;
|
||||||
|
/* Length is in bytes */
|
||||||
|
ExeNameU.MaximumLength = ExeLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ConvertInputAnsiToUnicode(Console,
|
||||||
|
ExeName, ExeLength,
|
||||||
|
&ExeNameU.Buffer, &ExeNameU.MaximumLength))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExeNameU.Length = ExeNameU.MaximumLength;
|
||||||
|
|
||||||
|
Entry = Console->HistoryBuffers.Flink;
|
||||||
|
while (Entry != &Console->HistoryBuffers)
|
||||||
|
{
|
||||||
|
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
|
||||||
|
|
||||||
|
/* For the history APIs, the caller is allowed to give only part of the name */
|
||||||
|
if (RtlPrefixUnicodeString(&ExeNameU, &Hist->ExeName, TRUE))
|
||||||
|
{
|
||||||
|
if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
|
||||||
|
return Hist;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry = Entry->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
|
||||||
|
{
|
||||||
|
if (!Hist) return;
|
||||||
|
|
||||||
|
while (Hist->NumEntries != 0)
|
||||||
|
RtlFreeUnicodeString(&Hist->Entries[--Hist->NumEntries]);
|
||||||
|
|
||||||
|
ConsoleFreeHeap(Hist->Entries);
|
||||||
|
RemoveEntryList(&Hist->ListEntry);
|
||||||
|
ConsoleFreeHeap(Hist);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HistoryAddEntry(PCONSRV_CONSOLE Console,
|
||||||
|
PUNICODE_STRING ExeName,
|
||||||
|
PUNICODE_STRING Entry)
|
||||||
|
{
|
||||||
|
// UNICODE_STRING NewEntry;
|
||||||
|
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
|
||||||
|
|
||||||
|
if (!Hist) return;
|
||||||
|
|
||||||
|
// NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR);
|
||||||
|
// NewEntry.Buffer = Console->LineBuffer;
|
||||||
|
|
||||||
|
/* Don't add blank or duplicate entries */
|
||||||
|
if (Entry->Length == 0 || Hist->MaxEntries == 0 ||
|
||||||
|
(Hist->NumEntries > 0 &&
|
||||||
|
RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], Entry, FALSE)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Console->HistoryNoDup)
|
||||||
|
{
|
||||||
|
INT i;
|
||||||
|
|
||||||
|
/* Check if this line has been entered before */
|
||||||
|
for (i = Hist->NumEntries - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (RtlEqualUnicodeString(&Hist->Entries[i], Entry, FALSE))
|
||||||
|
{
|
||||||
|
UNICODE_STRING NewEntry;
|
||||||
|
|
||||||
|
/* 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));
|
||||||
|
Hist->Entries[Hist->NumEntries - 1] = NewEntry;
|
||||||
|
Hist->Position = Hist->NumEntries - 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Hist->NumEntries == Hist->MaxEntries)
|
||||||
|
{
|
||||||
|
/* List is full, remove oldest entry */
|
||||||
|
RtlFreeUnicodeString(&Hist->Entries[0]);
|
||||||
|
memmove(&Hist->Entries[0], &Hist->Entries[1],
|
||||||
|
--Hist->NumEntries * sizeof(UNICODE_STRING));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(RtlDuplicateUnicodeString(0, Entry, &Hist->Entries[Hist->NumEntries])))
|
||||||
|
Hist->NumEntries++;
|
||||||
|
Hist->Position = Hist->NumEntries - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HistoryGetCurrentEntry(PCONSRV_CONSOLE Console,
|
||||||
|
PUNICODE_STRING ExeName,
|
||||||
|
PUNICODE_STRING Entry)
|
||||||
|
{
|
||||||
|
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
|
||||||
|
|
||||||
|
if (!Hist || Hist->NumEntries == 0)
|
||||||
|
Entry->Length = 0;
|
||||||
|
else
|
||||||
|
*Entry = Hist->Entries[Hist->Position];
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
HistoryRecallHistory(PCONSRV_CONSOLE Console,
|
||||||
|
PUNICODE_STRING ExeName,
|
||||||
|
INT Offset,
|
||||||
|
PUNICODE_STRING Entry)
|
||||||
|
{
|
||||||
|
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
|
||||||
|
ULONG Position = 0;
|
||||||
|
|
||||||
|
if (!Hist || Hist->NumEntries == 0) return FALSE;
|
||||||
|
|
||||||
|
Position = Hist->Position + Offset;
|
||||||
|
Position = min(max(Position, 0), Hist->NumEntries - 1);
|
||||||
|
Hist->Position = Position;
|
||||||
|
|
||||||
|
*Entry = Hist->Entries[Hist->Position];
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
HistoryFindEntryByPrefix(PCONSRV_CONSOLE Console,
|
||||||
|
PUNICODE_STRING ExeName,
|
||||||
|
PUNICODE_STRING Prefix,
|
||||||
|
PUNICODE_STRING Entry)
|
||||||
|
{
|
||||||
|
INT HistPos;
|
||||||
|
|
||||||
|
/* Search for history entries starting with input. */
|
||||||
|
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
|
||||||
|
if (!Hist || Hist->NumEntries == 0) return FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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(Prefix, &Hist->Entries[HistPos], FALSE))
|
||||||
|
{
|
||||||
|
Hist->Position = HistPos;
|
||||||
|
*Entry = Hist->Entries[HistPos];
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (--HistPos < 0) HistPos += Hist->NumEntries;
|
||||||
|
} while (HistPos != Hist->Position);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HistoryDeleteCurrentBuffer(PCONSRV_CONSOLE Console,
|
||||||
|
PVOID ExeName)
|
||||||
|
{
|
||||||
|
HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName));
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HistoryDeleteBuffers(PCONSRV_CONSOLE Console)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY CurrentEntry;
|
||||||
|
PHISTORY_BUFFER HistoryBuffer;
|
||||||
|
|
||||||
|
while (!IsListEmpty(&Console->HistoryBuffers))
|
||||||
|
{
|
||||||
|
CurrentEntry = RemoveHeadList(&Console->HistoryBuffers);
|
||||||
|
HistoryBuffer = CONTAINING_RECORD(CurrentEntry, HISTORY_BUFFER, ListEntry);
|
||||||
|
HistoryDeleteBuffer(HistoryBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* PUBLIC SERVER APIS *********************************************************/
|
||||||
|
|
||||||
|
CSR_API(SrvGetConsoleCommandHistory)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest;
|
||||||
|
PCONSRV_CONSOLE Console;
|
||||||
|
ULONG BytesWritten = 0;
|
||||||
|
PHISTORY_BUFFER Hist;
|
||||||
|
|
||||||
|
DPRINT1("SrvGetConsoleCommandHistory entered\n");
|
||||||
|
|
||||||
|
if ( !CsrValidateMessageBuffer(ApiMessage,
|
||||||
|
(PVOID*)&GetCommandHistoryRequest->History,
|
||||||
|
GetCommandHistoryRequest->HistoryLength,
|
||||||
|
sizeof(BYTE)) ||
|
||||||
|
!CsrValidateMessageBuffer(ApiMessage,
|
||||||
|
(PVOID*)&GetCommandHistoryRequest->ExeName,
|
||||||
|
GetCommandHistoryRequest->ExeLength,
|
||||||
|
sizeof(BYTE)) )
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
Hist = HistoryFindBuffer(Console,
|
||||||
|
GetCommandHistoryRequest->ExeName,
|
||||||
|
GetCommandHistoryRequest->ExeLength,
|
||||||
|
GetCommandHistoryRequest->Unicode2);
|
||||||
|
if (Hist)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
LPSTR TargetBufferA;
|
||||||
|
LPWSTR TargetBufferW;
|
||||||
|
ULONG BufferSize = GetCommandHistoryRequest->HistoryLength;
|
||||||
|
|
||||||
|
ULONG Offset = 0;
|
||||||
|
ULONG SourceLength;
|
||||||
|
|
||||||
|
if (GetCommandHistoryRequest->Unicode)
|
||||||
|
{
|
||||||
|
TargetBufferW = GetCommandHistoryRequest->History;
|
||||||
|
BufferSize /= sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TargetBufferA = GetCommandHistoryRequest->History;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < Hist->NumEntries; i++)
|
||||||
|
{
|
||||||
|
SourceLength = Hist->Entries[i].Length / sizeof(WCHAR);
|
||||||
|
if (Offset + SourceLength + 1 > BufferSize)
|
||||||
|
{
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetCommandHistoryRequest->Unicode)
|
||||||
|
{
|
||||||
|
RtlCopyMemory(&TargetBufferW[Offset], Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR));
|
||||||
|
Offset += SourceLength;
|
||||||
|
TargetBufferW[Offset++] = L'\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConvertInputUnicodeToAnsi(Console,
|
||||||
|
Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR),
|
||||||
|
&TargetBufferA[Offset], SourceLength);
|
||||||
|
Offset += SourceLength;
|
||||||
|
TargetBufferA[Offset++] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetCommandHistoryRequest->Unicode)
|
||||||
|
BytesWritten = Offset * sizeof(WCHAR);
|
||||||
|
else
|
||||||
|
BytesWritten = Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCommandHistoryRequest->HistoryLength = TargetBuffer - (PBYTE)GetCommandHistoryRequest->History;
|
||||||
|
GetCommandHistoryRequest->HistoryLength = BytesWritten;
|
||||||
|
|
||||||
|
ConSrvReleaseConsole(Console, TRUE);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSR_API(SrvGetConsoleCommandHistoryLength)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryLengthRequest;
|
||||||
|
PCONSRV_CONSOLE Console;
|
||||||
|
PHISTORY_BUFFER Hist;
|
||||||
|
ULONG Length = 0;
|
||||||
|
|
||||||
|
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||||
|
(PVOID*)&GetCommandHistoryLengthRequest->ExeName,
|
||||||
|
GetCommandHistoryLengthRequest->ExeLength,
|
||||||
|
sizeof(BYTE)))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
Hist = HistoryFindBuffer(Console,
|
||||||
|
GetCommandHistoryLengthRequest->ExeName,
|
||||||
|
GetCommandHistoryLengthRequest->ExeLength,
|
||||||
|
GetCommandHistoryLengthRequest->Unicode2);
|
||||||
|
if (Hist)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
for (i = 0; i < Hist->NumEntries; i++)
|
||||||
|
Length += Hist->Entries[i].Length + sizeof(WCHAR); // Each entry is returned NULL-terminated
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Quick and dirty way of getting the number of bytes of the
|
||||||
|
* corresponding ANSI string from the one in UNICODE.
|
||||||
|
*/
|
||||||
|
if (!GetCommandHistoryLengthRequest->Unicode)
|
||||||
|
Length /= sizeof(WCHAR);
|
||||||
|
|
||||||
|
GetCommandHistoryLengthRequest->HistoryLength = Length;
|
||||||
|
|
||||||
|
ConSrvReleaseConsole(Console, TRUE);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSR_API(SrvExpungeConsoleCommandHistory)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ExpungeCommandHistoryRequest;
|
||||||
|
PCONSRV_CONSOLE Console;
|
||||||
|
PHISTORY_BUFFER Hist;
|
||||||
|
|
||||||
|
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||||
|
(PVOID*)&ExpungeCommandHistoryRequest->ExeName,
|
||||||
|
ExpungeCommandHistoryRequest->ExeLength,
|
||||||
|
sizeof(BYTE)))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
Hist = HistoryFindBuffer(Console,
|
||||||
|
ExpungeCommandHistoryRequest->ExeName,
|
||||||
|
ExpungeCommandHistoryRequest->ExeLength,
|
||||||
|
ExpungeCommandHistoryRequest->Unicode2);
|
||||||
|
HistoryDeleteBuffer(Hist);
|
||||||
|
|
||||||
|
ConSrvReleaseConsole(Console, TRUE);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSR_API(SrvSetConsoleNumberOfCommands)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryNumberCommandsRequest;
|
||||||
|
PCONSRV_CONSOLE Console;
|
||||||
|
PHISTORY_BUFFER Hist;
|
||||||
|
|
||||||
|
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||||
|
(PVOID*)&SetHistoryNumberCommandsRequest->ExeName,
|
||||||
|
SetHistoryNumberCommandsRequest->ExeLength,
|
||||||
|
sizeof(BYTE)))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
Hist = HistoryFindBuffer(Console,
|
||||||
|
SetHistoryNumberCommandsRequest->ExeName,
|
||||||
|
SetHistoryNumberCommandsRequest->ExeLength,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConSrvReleaseConsole(Console, TRUE);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSR_API(SrvGetConsoleHistory)
|
||||||
|
{
|
||||||
|
#if 0 // Vista+
|
||||||
|
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;
|
||||||
|
ConSrvReleaseConsole(Console, TRUE);
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
#else
|
||||||
|
DPRINT1("%s not yet implemented\n", __FUNCTION__);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
CSR_API(SrvSetConsoleHistory)
|
||||||
|
{
|
||||||
|
#if 0 // Vista+
|
||||||
|
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;
|
||||||
|
#else
|
||||||
|
DPRINT1("%s not yet implemented\n", __FUNCTION__);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
CSR_API(SrvSetConsoleCommandHistoryMode)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCONSOLE_SETHISTORYMODE SetHistoryModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryModeRequest;
|
||||||
|
PCONSRV_CONSOLE Console;
|
||||||
|
|
||||||
|
DPRINT1("SrvSetConsoleCommandHistoryMode(Mode = %d) is not yet implemented\n",
|
||||||
|
SetHistoryModeRequest->Mode);
|
||||||
|
|
||||||
|
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* This API is not yet implemented */
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
ConSrvReleaseConsole(Console, TRUE);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
11
win32ss/user/winsrv/consrv/history.h
Normal file
11
win32ss/user/winsrv/consrv/history.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Console Server DLL
|
||||||
|
* FILE: win32ss/user/winsrv/consrv/history.h
|
||||||
|
* PURPOSE: Console line input functions
|
||||||
|
* PROGRAMMERS: Jeffrey Morlan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
VOID HistoryDeleteBuffers(PCONSRV_CONSOLE Console);
|
|
@ -279,24 +279,12 @@ typedef struct _CONSOLE
|
||||||
ULONG ConsoleID; /* The ID of the console */
|
ULONG ConsoleID; /* The ID of the console */
|
||||||
LIST_ENTRY ListEntry; /* Entry in the list of consoles */
|
LIST_ENTRY ListEntry; /* Entry in the list of consoles */
|
||||||
|
|
||||||
/**************************** Input buffer and data ***************************/
|
HANDLE UnpauseEvent; /* When != NULL, event for pausing the console */
|
||||||
|
|
||||||
|
/******************************** Input buffer ********************************/
|
||||||
CONSOLE_INPUT_BUFFER InputBuffer; /* Input buffer of the console */
|
CONSOLE_INPUT_BUFFER InputBuffer; /* Input buffer of the console */
|
||||||
UINT InputCodePage;
|
UINT InputCodePage;
|
||||||
|
|
||||||
/** Put those things in CONSOLE_INPUT_BUFFER in PWINSRV_CONSOLE ?? **/
|
|
||||||
PWCHAR LineBuffer; /* Current line being input, in line buffered mode */
|
|
||||||
ULONG LineMaxSize; /* Maximum size of line in characters (including CR+LF) */
|
|
||||||
ULONG LineSize; /* Current size of line */
|
|
||||||
ULONG LinePos; /* Current position within line */
|
|
||||||
BOOLEAN LineComplete; /* User pressed enter, ready to send back to client */
|
|
||||||
BOOLEAN LineUpPressed;
|
|
||||||
BOOLEAN LineInsertToggle; /* Replace character over cursor instead of inserting */
|
|
||||||
ULONG LineWakeupMask; /* Bitmap of which control characters will end line input */
|
|
||||||
|
|
||||||
/** In PWINSRV_CONSOLE ?? **/
|
|
||||||
BOOLEAN InsertMode;
|
|
||||||
/*************************************************/
|
|
||||||
|
|
||||||
/******************************* Screen buffers *******************************/
|
/******************************* Screen buffers *******************************/
|
||||||
LIST_ENTRY BufferList; /* List of all screen buffers for this console */
|
LIST_ENTRY BufferList; /* List of all screen buffers for this console */
|
||||||
PCONSOLE_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
|
PCONSOLE_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
|
||||||
|
@ -306,8 +294,6 @@ typedef struct _CONSOLE
|
||||||
UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */
|
UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */
|
||||||
UNICODE_STRING Title; /* Title of console. Always NULL-terminated */
|
UNICODE_STRING Title; /* Title of console. Always NULL-terminated */
|
||||||
|
|
||||||
HANDLE UnpauseEvent; /* When != NULL, event for pausing the console */
|
|
||||||
|
|
||||||
COORD ConsoleSize; /* The current size of the console, for text-mode only */
|
COORD ConsoleSize; /* The current size of the console, for text-mode only */
|
||||||
BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
|
BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,6 @@ typedef struct _WINSRV_CONSOLE
|
||||||
PCONSOLE_PROCESS_DATA NotifiedLastCloseProcess; /* Pointer to the unique process that needs to be notified when the console leader process is killed */
|
PCONSOLE_PROCESS_DATA NotifiedLastCloseProcess; /* Pointer to the unique process that needs to be notified when the console leader process is killed */
|
||||||
BOOLEAN NotifyLastClose; /* TRUE if the console should send a control event when the console leader process is killed */
|
BOOLEAN NotifyLastClose; /* TRUE if the console should send a control event when the console leader process is killed */
|
||||||
|
|
||||||
BOOLEAN QuickEdit;
|
|
||||||
|
|
||||||
/******************************* Pausing support ******************************/
|
/******************************* Pausing support ******************************/
|
||||||
BYTE PauseFlags;
|
BYTE PauseFlags;
|
||||||
LIST_ENTRY ReadWaitQueue; /* List head for the queue of unique input buffer read wait blocks */
|
LIST_ENTRY ReadWaitQueue; /* List head for the queue of unique input buffer read wait blocks */
|
||||||
|
@ -145,6 +143,19 @@ typedef struct _WINSRV_CONSOLE
|
||||||
ULONG NumberOfHistoryBuffers; /* Maximum number of history buffers allowed */
|
ULONG NumberOfHistoryBuffers; /* Maximum number of history buffers allowed */
|
||||||
BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */
|
BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */
|
||||||
|
|
||||||
|
/**************************** Input Line Discipline ***************************/
|
||||||
|
PWCHAR LineBuffer; /* Current line being input, in line buffered mode */
|
||||||
|
ULONG LineMaxSize; /* Maximum size of line in characters (including CR+LF) */
|
||||||
|
ULONG LineSize; /* Current size of line */
|
||||||
|
ULONG LinePos; /* Current position within line */
|
||||||
|
BOOLEAN LineComplete; /* User pressed enter, ready to send back to client */
|
||||||
|
BOOLEAN LineUpPressed;
|
||||||
|
BOOLEAN LineInsertToggle; /* Replace character over cursor instead of inserting */
|
||||||
|
ULONG LineWakeupMask; /* Bitmap of which control characters will end line input */
|
||||||
|
|
||||||
|
BOOLEAN InsertMode;
|
||||||
|
BOOLEAN QuickEdit;
|
||||||
|
|
||||||
/************************ Virtual DOS Machine support *************************/
|
/************************ Virtual DOS Machine support *************************/
|
||||||
COORD VDMBufferSize; /* Real size of the VDM buffer, in units of ??? */
|
COORD VDMBufferSize; /* Real size of the VDM buffer, in units of ??? */
|
||||||
HANDLE VDMBufferSection; /* Handle to the memory shared section for the VDM buffer */
|
HANDLE VDMBufferSection; /* Handle to the memory shared section for the VDM buffer */
|
||||||
|
|
|
@ -13,16 +13,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
typedef struct _HISTORY_BUFFER
|
|
||||||
{
|
|
||||||
LIST_ENTRY ListEntry;
|
|
||||||
UINT Position;
|
|
||||||
UINT MaxEntries;
|
|
||||||
UINT NumEntries;
|
|
||||||
UNICODE_STRING ExeName;
|
|
||||||
PUNICODE_STRING Entries;
|
|
||||||
} HISTORY_BUFFER, *PHISTORY_BUFFER;
|
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
ConvertInputAnsiToUnicode(PCONSOLE Console,
|
ConvertInputAnsiToUnicode(PCONSOLE Console,
|
||||||
|
@ -40,183 +30,35 @@ ConvertInputUnicodeToAnsi(PCONSOLE Console,
|
||||||
/*P*/USHORT TargetLength);
|
/*P*/USHORT TargetLength);
|
||||||
|
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
VOID
|
||||||
|
|
||||||
static PHISTORY_BUFFER
|
|
||||||
HistoryCurrentBuffer(PCONSRV_CONSOLE Console,
|
|
||||||
PUNICODE_STRING ExeName)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
|
|
||||||
PHISTORY_BUFFER Hist;
|
|
||||||
|
|
||||||
for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
|
|
||||||
{
|
|
||||||
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
|
|
||||||
if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE))
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
ConsoleFreeHeap(Hist);
|
|
||||||
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 VOID
|
|
||||||
HistoryAddEntry(PCONSRV_CONSOLE Console,
|
HistoryAddEntry(PCONSRV_CONSOLE Console,
|
||||||
PUNICODE_STRING ExeName)
|
PUNICODE_STRING ExeName,
|
||||||
{
|
PUNICODE_STRING Entry);
|
||||||
UNICODE_STRING NewEntry;
|
BOOL
|
||||||
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
|
HistoryRecallHistory(PCONSRV_CONSOLE Console,
|
||||||
INT i;
|
PUNICODE_STRING ExeName,
|
||||||
|
INT Offset,
|
||||||
if (!Hist) return;
|
PUNICODE_STRING Entry);
|
||||||
|
VOID
|
||||||
NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR);
|
|
||||||
NewEntry.Buffer = Console->LineBuffer;
|
|
||||||
|
|
||||||
/* Don't add blank or duplicate entries */
|
|
||||||
if (NewEntry.Length == 0 || Hist->MaxEntries == 0 ||
|
|
||||||
(Hist->NumEntries > 0 &&
|
|
||||||
RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], &NewEntry, FALSE)))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Console->HistoryNoDup)
|
|
||||||
{
|
|
||||||
/* Check if this line has been entered before */
|
|
||||||
for (i = Hist->NumEntries - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (RtlEqualUnicodeString(&Hist->Entries[i], &NewEntry, FALSE))
|
|
||||||
{
|
|
||||||
/* 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));
|
|
||||||
Hist->Entries[Hist->NumEntries - 1] = NewEntry;
|
|
||||||
Hist->Position = Hist->NumEntries - 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Hist->NumEntries == Hist->MaxEntries)
|
|
||||||
{
|
|
||||||
/* List is full, remove oldest entry */
|
|
||||||
RtlFreeUnicodeString(&Hist->Entries[0]);
|
|
||||||
memmove(&Hist->Entries[0], &Hist->Entries[1],
|
|
||||||
--Hist->NumEntries * sizeof(UNICODE_STRING));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NT_SUCCESS(RtlDuplicateUnicodeString(0, &NewEntry, &Hist->Entries[Hist->NumEntries])))
|
|
||||||
Hist->NumEntries++;
|
|
||||||
Hist->Position = Hist->NumEntries - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
HistoryGetCurrentEntry(PCONSRV_CONSOLE Console,
|
HistoryGetCurrentEntry(PCONSRV_CONSOLE Console,
|
||||||
PUNICODE_STRING ExeName,
|
PUNICODE_STRING ExeName,
|
||||||
PUNICODE_STRING Entry)
|
PUNICODE_STRING Entry);
|
||||||
{
|
|
||||||
PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
|
|
||||||
|
|
||||||
if (!Hist || Hist->NumEntries == 0)
|
|
||||||
Entry->Length = 0;
|
|
||||||
else
|
|
||||||
*Entry = Hist->Entries[Hist->Position];
|
|
||||||
}
|
|
||||||
|
|
||||||
static PHISTORY_BUFFER
|
|
||||||
HistoryFindBuffer(PCONSRV_CONSOLE Console,
|
|
||||||
PVOID ExeName,
|
|
||||||
USHORT ExeLength,
|
|
||||||
BOOLEAN UnicodeExe)
|
|
||||||
{
|
|
||||||
UNICODE_STRING ExeNameU;
|
|
||||||
|
|
||||||
PLIST_ENTRY Entry;
|
|
||||||
PHISTORY_BUFFER Hist = NULL;
|
|
||||||
|
|
||||||
if (ExeName == NULL) return NULL;
|
|
||||||
|
|
||||||
if (UnicodeExe)
|
|
||||||
{
|
|
||||||
ExeNameU.Buffer = ExeName;
|
|
||||||
/* Length is in bytes */
|
|
||||||
ExeNameU.MaximumLength = ExeLength;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!ConvertInputAnsiToUnicode(Console,
|
|
||||||
ExeName, ExeLength,
|
|
||||||
&ExeNameU.Buffer, &ExeNameU.MaximumLength))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExeNameU.Length = ExeNameU.MaximumLength;
|
|
||||||
|
|
||||||
Entry = Console->HistoryBuffers.Flink;
|
|
||||||
while (Entry != &Console->HistoryBuffers)
|
|
||||||
{
|
|
||||||
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
|
|
||||||
|
|
||||||
/* For the history APIs, the caller is allowed to give only part of the name */
|
|
||||||
if (RtlPrefixUnicodeString(&ExeNameU, &Hist->ExeName, TRUE))
|
|
||||||
{
|
|
||||||
if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
|
|
||||||
return Hist;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry = Entry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
|
|
||||||
{
|
|
||||||
if (!Hist) return;
|
|
||||||
|
|
||||||
while (Hist->NumEntries != 0)
|
|
||||||
RtlFreeUnicodeString(&Hist->Entries[--Hist->NumEntries]);
|
|
||||||
|
|
||||||
ConsoleFreeHeap(Hist->Entries);
|
|
||||||
RemoveEntryList(&Hist->ListEntry);
|
|
||||||
ConsoleFreeHeap(Hist);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
HistoryDeleteBuffers(PCONSRV_CONSOLE Console)
|
HistoryDeleteCurrentBuffer(PCONSRV_CONSOLE Console,
|
||||||
{
|
PVOID ExeName);
|
||||||
PLIST_ENTRY CurrentEntry;
|
BOOL
|
||||||
PHISTORY_BUFFER HistoryBuffer;
|
HistoryFindEntryByPrefix(PCONSRV_CONSOLE Console,
|
||||||
|
PUNICODE_STRING ExeName,
|
||||||
|
PUNICODE_STRING Prefix,
|
||||||
|
PUNICODE_STRING Entry);
|
||||||
|
|
||||||
while (!IsListEmpty(&Console->HistoryBuffers))
|
|
||||||
{
|
|
||||||
CurrentEntry = RemoveHeadList(&Console->HistoryBuffers);
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
HistoryBuffer = CONTAINING_RECORD(CurrentEntry, HISTORY_BUFFER, ListEntry);
|
|
||||||
HistoryDeleteBuffer(HistoryBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
LineInputSetPos(PCONSRV_CONSOLE Console, UINT Pos)
|
LineInputSetPos(PCONSRV_CONSOLE Console,
|
||||||
|
UINT Pos)
|
||||||
{
|
{
|
||||||
if (Pos != Console->LinePos && Console->InputBuffer.Mode & ENABLE_ECHO_INPUT)
|
if (Pos != Console->LinePos && Console->InputBuffer.Mode & ENABLE_ECHO_INPUT)
|
||||||
{
|
{
|
||||||
|
@ -240,7 +82,10 @@ LineInputSetPos(PCONSRV_CONSOLE Console, UINT Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
LineInputEdit(PCONSRV_CONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHAR Insertion)
|
LineInputEdit(PCONSRV_CONSOLE Console,
|
||||||
|
UINT NumToDelete,
|
||||||
|
UINT NumToInsert,
|
||||||
|
PWCHAR Insertion)
|
||||||
{
|
{
|
||||||
PTEXTMODE_SCREEN_BUFFER ActiveBuffer;
|
PTEXTMODE_SCREEN_BUFFER ActiveBuffer;
|
||||||
UINT Pos = Console->LinePos;
|
UINT Pos = Console->LinePos;
|
||||||
|
@ -276,6 +121,7 @@ LineInputEdit(PCONSRV_CONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHA
|
||||||
LineInputSetPos(Console, Pos + NumToInsert);
|
LineInputSetPos(Console, Pos + NumToInsert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static VOID
|
static VOID
|
||||||
LineInputRecallHistory(PCONSRV_CONSOLE Console,
|
LineInputRecallHistory(PCONSRV_CONSOLE Console,
|
||||||
PUNICODE_STRING ExeName,
|
PUNICODE_STRING ExeName,
|
||||||
|
@ -295,6 +141,22 @@ LineInputRecallHistory(PCONSRV_CONSOLE Console,
|
||||||
Hist->Entries[Hist->Position].Length / sizeof(WCHAR),
|
Hist->Entries[Hist->Position].Length / sizeof(WCHAR),
|
||||||
Hist->Entries[Hist->Position].Buffer);
|
Hist->Entries[Hist->Position].Buffer);
|
||||||
}
|
}
|
||||||
|
#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
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
LineInputKeyDown(PCONSRV_CONSOLE Console,
|
LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
|
@ -302,9 +164,12 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
KEY_EVENT_RECORD *KeyEvent)
|
KEY_EVENT_RECORD *KeyEvent)
|
||||||
{
|
{
|
||||||
UINT Pos = Console->LinePos;
|
UINT Pos = Console->LinePos;
|
||||||
PHISTORY_BUFFER Hist;
|
|
||||||
UNICODE_STRING Entry;
|
UNICODE_STRING Entry;
|
||||||
INT HistPos;
|
// INT HistPos;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, deal with control keys...
|
||||||
|
*/
|
||||||
|
|
||||||
switch (KeyEvent->wVirtualKeyCode)
|
switch (KeyEvent->wVirtualKeyCode)
|
||||||
{
|
{
|
||||||
|
@ -314,20 +179,20 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
LineInputEdit(Console, Console->LineSize, 0, NULL);
|
LineInputEdit(Console, Console->LineSize, 0, NULL);
|
||||||
return;
|
return;
|
||||||
case VK_HOME:
|
case VK_HOME:
|
||||||
/* Move to start of line. With ctrl, erase everything left of cursor */
|
/* Move to start of line. With CTRL, erase everything left of cursor */
|
||||||
LineInputSetPos(Console, 0);
|
LineInputSetPos(Console, 0);
|
||||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||||
LineInputEdit(Console, Pos, 0, NULL);
|
LineInputEdit(Console, Pos, 0, NULL);
|
||||||
return;
|
return;
|
||||||
case VK_END:
|
case VK_END:
|
||||||
/* Move to end of line. With ctrl, erase everything right of cursor */
|
/* Move to end of line. With CTRL, erase everything right of cursor */
|
||||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||||
LineInputEdit(Console, Console->LineSize - Pos, 0, NULL);
|
LineInputEdit(Console, Console->LineSize - Pos, 0, NULL);
|
||||||
else
|
else
|
||||||
LineInputSetPos(Console, Console->LineSize);
|
LineInputSetPos(Console, Console->LineSize);
|
||||||
return;
|
return;
|
||||||
case VK_LEFT:
|
case VK_LEFT:
|
||||||
/* Move left. With ctrl, move to beginning of previous word */
|
/* Move left. With CTRL, move to beginning of previous word */
|
||||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
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--;
|
||||||
|
@ -341,13 +206,12 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
return;
|
return;
|
||||||
case VK_RIGHT:
|
case VK_RIGHT:
|
||||||
case VK_F1:
|
case VK_F1:
|
||||||
/* Move right. With ctrl, move to beginning of next word */
|
/* Move right. With CTRL, move to beginning of next word */
|
||||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
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++;
|
||||||
while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++;
|
while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++;
|
||||||
LineInputSetPos(Console, Pos);
|
LineInputSetPos(Console, Pos);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -379,8 +243,10 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
return;
|
return;
|
||||||
case VK_UP:
|
case VK_UP:
|
||||||
case VK_F5:
|
case VK_F5:
|
||||||
/* Recall previous history entry. On first time, actually recall the
|
/*
|
||||||
* current (usually last) entry; on subsequent times go back. */
|
* Recall previous history entry. On first time, actually recall the
|
||||||
|
* current (usually last) entry; on subsequent times go back.
|
||||||
|
*/
|
||||||
LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0);
|
LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0);
|
||||||
Console->LineUpPressed = TRUE;
|
Console->LineUpPressed = TRUE;
|
||||||
return;
|
return;
|
||||||
|
@ -404,24 +270,47 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
break;
|
break;
|
||||||
case VK_F7:
|
case VK_F7:
|
||||||
if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
|
if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
|
||||||
HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName));
|
HistoryDeleteCurrentBuffer(Console, ExeName);
|
||||||
return;
|
return;
|
||||||
case VK_F8:
|
case VK_F8:
|
||||||
|
|
||||||
|
{
|
||||||
|
UNICODE_STRING EntryFound;
|
||||||
|
|
||||||
|
Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR)
|
||||||
|
Entry.Buffer = Console->LineBuffer;
|
||||||
|
|
||||||
|
if (HistoryFindEntryByPrefix(Console, ExeName, &Entry, &EntryFound))
|
||||||
|
{
|
||||||
|
LineInputEdit(Console, Console->LineSize - Pos,
|
||||||
|
EntryFound.Length / sizeof(WCHAR) - Pos,
|
||||||
|
&EntryFound.Buffer[Pos]);
|
||||||
|
/* Cursor stays where it was */
|
||||||
|
LineInputSetPos(Console, Pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
PHISTORY_BUFFER Hist;
|
||||||
|
|
||||||
/* Search for history entries starting with input. */
|
/* Search for history entries starting with input. */
|
||||||
Hist = HistoryCurrentBuffer(Console, ExeName);
|
Hist = HistoryCurrentBuffer(Console, ExeName);
|
||||||
if (!Hist || Hist->NumEntries == 0) return;
|
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. */
|
* Like Up/F5, on first time start from current (usually last) entry,
|
||||||
|
* but on subsequent times start at previous entry.
|
||||||
|
*/
|
||||||
if (Console->LineUpPressed)
|
if (Console->LineUpPressed)
|
||||||
Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1;
|
Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1;
|
||||||
Console->LineUpPressed = TRUE;
|
Console->LineUpPressed = TRUE;
|
||||||
|
|
||||||
Entry.Length = Console->LinePos * sizeof(WCHAR);
|
Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR)
|
||||||
Entry.Buffer = Console->LineBuffer;
|
Entry.Buffer = Console->LineBuffer;
|
||||||
|
|
||||||
/* Keep going backwards, even wrapping around to the end,
|
/*
|
||||||
* until we get back to starting point */
|
* Keep going backwards, even wrapping around to the end,
|
||||||
|
* until we get back to starting point.
|
||||||
|
*/
|
||||||
HistPos = Hist->Position;
|
HistPos = Hist->Position;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -437,9 +326,16 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
}
|
}
|
||||||
if (--HistPos < 0) HistPos += Hist->NumEntries;
|
if (--HistPos < 0) HistPos += Hist->NumEntries;
|
||||||
} while (HistPos != Hist->Position);
|
} while (HistPos != Hist->Position);
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OK, we can continue...
|
||||||
|
*/
|
||||||
|
|
||||||
if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT)
|
if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT)
|
||||||
{
|
{
|
||||||
/* backspace handling - if processed input enabled then we handle it here
|
/* backspace handling - if processed input enabled then we handle it here
|
||||||
|
@ -452,9 +348,12 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
}
|
}
|
||||||
else if (KeyEvent->uChar.UnicodeChar == L'\r')
|
else if (KeyEvent->uChar.UnicodeChar == L'\r')
|
||||||
{
|
{
|
||||||
HistoryAddEntry(Console, ExeName);
|
Entry.Length = Entry.MaximumLength = Console->LineSize * sizeof(WCHAR);
|
||||||
|
Entry.Buffer = Console->LineBuffer;
|
||||||
|
HistoryAddEntry(Console, ExeName, &Entry);
|
||||||
|
|
||||||
/* TODO: Expand aliases */
|
/* TODO: Expand aliases */
|
||||||
|
DPRINT1("TODO: Expand aliases\n");
|
||||||
|
|
||||||
LineInputSetPos(Console, Console->LineSize);
|
LineInputSetPos(Console, Console->LineSize);
|
||||||
Console->LineBuffer[Console->LineSize++] = L'\r';
|
Console->LineBuffer[Console->LineSize++] = L'\r';
|
||||||
|
@ -466,9 +365,11 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add \n if processed input. There should usually be room for it,
|
/*
|
||||||
|
* Add \n if processed input. There should usually be room for it,
|
||||||
* but an exception to the rule exists: the buffer could have been
|
* but an exception to the rule exists: the buffer could have been
|
||||||
* pre-filled with LineMaxSize - 1 characters. */
|
* pre-filled with LineMaxSize - 1 characters.
|
||||||
|
*/
|
||||||
if (Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT &&
|
if (Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT &&
|
||||||
Console->LineSize < Console->LineMaxSize)
|
Console->LineSize < Console->LineMaxSize)
|
||||||
{
|
{
|
||||||
|
@ -507,272 +408,4 @@ LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
|
|
||||||
/* PUBLIC SERVER APIS *********************************************************/
|
/* PUBLIC SERVER APIS *********************************************************/
|
||||||
|
|
||||||
CSR_API(SrvGetConsoleCommandHistory)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest;
|
|
||||||
PCONSRV_CONSOLE Console;
|
|
||||||
ULONG BytesWritten = 0;
|
|
||||||
PHISTORY_BUFFER Hist;
|
|
||||||
|
|
||||||
DPRINT1("SrvGetConsoleCommandHistory entered\n");
|
|
||||||
|
|
||||||
if ( !CsrValidateMessageBuffer(ApiMessage,
|
|
||||||
(PVOID*)&GetCommandHistoryRequest->History,
|
|
||||||
GetCommandHistoryRequest->HistoryLength,
|
|
||||||
sizeof(BYTE)) ||
|
|
||||||
!CsrValidateMessageBuffer(ApiMessage,
|
|
||||||
(PVOID*)&GetCommandHistoryRequest->ExeName,
|
|
||||||
GetCommandHistoryRequest->ExeLength,
|
|
||||||
sizeof(BYTE)) )
|
|
||||||
{
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
|
||||||
Hist = HistoryFindBuffer(Console,
|
|
||||||
GetCommandHistoryRequest->ExeName,
|
|
||||||
GetCommandHistoryRequest->ExeLength,
|
|
||||||
GetCommandHistoryRequest->Unicode2);
|
|
||||||
if (Hist)
|
|
||||||
{
|
|
||||||
UINT i;
|
|
||||||
|
|
||||||
LPSTR TargetBufferA;
|
|
||||||
LPWSTR TargetBufferW;
|
|
||||||
ULONG BufferSize = GetCommandHistoryRequest->HistoryLength;
|
|
||||||
|
|
||||||
UINT Offset = 0;
|
|
||||||
UINT SourceLength;
|
|
||||||
|
|
||||||
if (GetCommandHistoryRequest->Unicode)
|
|
||||||
{
|
|
||||||
TargetBufferW = GetCommandHistoryRequest->History;
|
|
||||||
BufferSize /= sizeof(WCHAR);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TargetBufferA = GetCommandHistoryRequest->History;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < Hist->NumEntries; i++)
|
|
||||||
{
|
|
||||||
SourceLength = Hist->Entries[i].Length / sizeof(WCHAR);
|
|
||||||
if (Offset + SourceLength + 1 > BufferSize)
|
|
||||||
{
|
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetCommandHistoryRequest->Unicode)
|
|
||||||
{
|
|
||||||
RtlCopyMemory(&TargetBufferW[Offset], Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR));
|
|
||||||
Offset += SourceLength;
|
|
||||||
TargetBufferW[Offset++] = L'\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ConvertInputUnicodeToAnsi(Console,
|
|
||||||
Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR),
|
|
||||||
&TargetBufferA[Offset], SourceLength);
|
|
||||||
Offset += SourceLength;
|
|
||||||
TargetBufferA[Offset++] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetCommandHistoryRequest->Unicode)
|
|
||||||
BytesWritten = Offset * sizeof(WCHAR);
|
|
||||||
else
|
|
||||||
BytesWritten = Offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCommandHistoryRequest->HistoryLength = TargetBuffer - (PBYTE)GetCommandHistoryRequest->History;
|
|
||||||
GetCommandHistoryRequest->HistoryLength = BytesWritten;
|
|
||||||
|
|
||||||
ConSrvReleaseConsole(Console, TRUE);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSR_API(SrvGetConsoleCommandHistoryLength)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryLengthRequest;
|
|
||||||
PCONSRV_CONSOLE Console;
|
|
||||||
PHISTORY_BUFFER Hist;
|
|
||||||
ULONG Length = 0;
|
|
||||||
UINT i;
|
|
||||||
|
|
||||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
|
||||||
(PVOID*)&GetCommandHistoryLengthRequest->ExeName,
|
|
||||||
GetCommandHistoryLengthRequest->ExeLength,
|
|
||||||
sizeof(BYTE)))
|
|
||||||
{
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
|
||||||
Hist = HistoryFindBuffer(Console,
|
|
||||||
GetCommandHistoryLengthRequest->ExeName,
|
|
||||||
GetCommandHistoryLengthRequest->ExeLength,
|
|
||||||
GetCommandHistoryLengthRequest->Unicode2);
|
|
||||||
if (Hist)
|
|
||||||
{
|
|
||||||
for (i = 0; i < Hist->NumEntries; i++)
|
|
||||||
Length += Hist->Entries[i].Length + sizeof(WCHAR); // Each entry is returned NULL-terminated
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Quick and dirty way of getting the number of bytes of the
|
|
||||||
* corresponding ANSI string from the one in UNICODE.
|
|
||||||
*/
|
|
||||||
if (!GetCommandHistoryLengthRequest->Unicode)
|
|
||||||
Length /= sizeof(WCHAR);
|
|
||||||
|
|
||||||
GetCommandHistoryLengthRequest->HistoryLength = Length;
|
|
||||||
|
|
||||||
ConSrvReleaseConsole(Console, TRUE);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSR_API(SrvExpungeConsoleCommandHistory)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ExpungeCommandHistoryRequest;
|
|
||||||
PCONSRV_CONSOLE Console;
|
|
||||||
PHISTORY_BUFFER Hist;
|
|
||||||
|
|
||||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
|
||||||
(PVOID*)&ExpungeCommandHistoryRequest->ExeName,
|
|
||||||
ExpungeCommandHistoryRequest->ExeLength,
|
|
||||||
sizeof(BYTE)))
|
|
||||||
{
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
|
||||||
Hist = HistoryFindBuffer(Console,
|
|
||||||
ExpungeCommandHistoryRequest->ExeName,
|
|
||||||
ExpungeCommandHistoryRequest->ExeLength,
|
|
||||||
ExpungeCommandHistoryRequest->Unicode2);
|
|
||||||
HistoryDeleteBuffer(Hist);
|
|
||||||
|
|
||||||
ConSrvReleaseConsole(Console, TRUE);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSR_API(SrvSetConsoleNumberOfCommands)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryNumberCommandsRequest;
|
|
||||||
PCONSRV_CONSOLE Console;
|
|
||||||
PHISTORY_BUFFER Hist;
|
|
||||||
|
|
||||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
|
||||||
(PVOID*)&SetHistoryNumberCommandsRequest->ExeName,
|
|
||||||
SetHistoryNumberCommandsRequest->ExeLength,
|
|
||||||
sizeof(BYTE)))
|
|
||||||
{
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
|
||||||
Hist = HistoryFindBuffer(Console,
|
|
||||||
SetHistoryNumberCommandsRequest->ExeName,
|
|
||||||
SetHistoryNumberCommandsRequest->ExeLength,
|
|
||||||
SetHistoryNumberCommandsRequest->Unicode2);
|
|
||||||
if (Hist)
|
|
||||||
{
|
|
||||||
UINT 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConSrvReleaseConsole(Console, TRUE);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSR_API(SrvGetConsoleHistory)
|
|
||||||
{
|
|
||||||
#if 0 // Vista+
|
|
||||||
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;
|
|
||||||
ConSrvReleaseConsole(Console, TRUE);
|
|
||||||
}
|
|
||||||
return Status;
|
|
||||||
#else
|
|
||||||
DPRINT1("%s not yet implemented\n", __FUNCTION__);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
CSR_API(SrvSetConsoleHistory)
|
|
||||||
{
|
|
||||||
#if 0 // Vista+
|
|
||||||
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;
|
|
||||||
#else
|
|
||||||
DPRINT1("%s not yet implemented\n", __FUNCTION__);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
CSR_API(SrvSetConsoleCommandHistoryMode)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PCONSOLE_SETHISTORYMODE SetHistoryModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryModeRequest;
|
|
||||||
PCONSRV_CONSOLE Console;
|
|
||||||
|
|
||||||
DPRINT1("SrvSetConsoleCommandHistoryMode(Mode = %d) is not yet implemented\n",
|
|
||||||
SetHistoryModeRequest->Mode);
|
|
||||||
|
|
||||||
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
|
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
|
||||||
/* This API is not yet implemented */
|
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
ConSrvReleaseConsole(Console, TRUE);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS Console Server DLL
|
* PROJECT: ReactOS Console Server DLL
|
||||||
* FILE: win32ss/user/winsrv/consrv/lineinput.c
|
* FILE: win32ss/user/winsrv/consrv/lineinput.h
|
||||||
* PURPOSE: Console line input functions
|
* PURPOSE: Console line input functions
|
||||||
* PROGRAMMERS: Jeffrey Morlan
|
* PROGRAMMERS: Jeffrey Morlan
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
VOID HistoryDeleteBuffers(PCONSRV_CONSOLE Console);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
LineInputKeyDown(PCONSRV_CONSOLE Console,
|
LineInputKeyDown(PCONSRV_CONSOLE Console,
|
||||||
PUNICODE_STRING ExeName,
|
PUNICODE_STRING ExeName,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue