Author: hbelusca Date: Fri Aug 29 19:45:45 2014 New Revision: 63978
URL: http://svn.reactos.org/svn/reactos?rev=63978&view=rev Log: [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.
Added: branches/condrv_restructure/win32ss/user/winsrv/consrv/history.c (with props) branches/condrv_restructure/win32ss/user/winsrv/consrv/history.h (with props) Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv.cmake branches/condrv_restructure/win32ss/user/winsrv/consrv/alias.c branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/console.c branches/condrv_restructure/win32ss/user/winsrv/consrv/console.c branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.c branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.h
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv.cmake URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv.cmake [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv.cmake [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -11,6 +11,7 @@ consrv/console.c consrv/frontendctl.c consrv/handle.c + consrv/history.c consrv/init.c consrv/lineinput.c consrv/settings.c
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/alias.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/alias.c [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/alias.c [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -18,16 +18,16 @@
typedef struct _ALIAS_ENTRY { + struct _ALIAS_ENTRY* Next; UNICODE_STRING Source; UNICODE_STRING Target; - struct _ALIAS_ENTRY* Next; } ALIAS_ENTRY, *PALIAS_ENTRY;
typedef struct _ALIAS_HEADER { + struct _ALIAS_HEADER* Next; UNICODE_STRING ExeName; PALIAS_ENTRY Data; - struct _ALIAS_HEADER* Next; } ALIAS_HEADER, *PALIAS_HEADER;
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/console.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/console.c [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/console.c [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -257,13 +257,6 @@ Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_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 */ Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
@@ -518,17 +511,7 @@ if (INPUT_BUFFER == Object->Type) { PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object; - *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) { @@ -548,8 +531,6 @@ IN PCONSOLE_IO_OBJECT Object, 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 | \ ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \ ENABLE_MOUSE_INPUT ) @@ -567,48 +548,24 @@ { PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
- DPRINT("SetConsoleMode(Input, %d)\n", ConsoleMode); - - /* - * 1. Only the presence of valid mode flags is allowed. - */ - if (ConsoleMode & ~(CONSOLE_VALID_INPUT_MODES | CONSOLE_VALID_CONTROL_MODES)) + /* Only the presence of valid mode flags is allowed */ + if (ConsoleMode & ~CONSOLE_VALID_INPUT_MODES) { Status = STATUS_INVALID_PARAMETER; - goto Quit; - } - - /* - * 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 ) + } + else + { + InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES); + } + } + else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type) + { + PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object; + + /* Only the presence of valid mode flags is allowed */ + if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES) { Status = STATUS_INVALID_PARAMETER; - 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) - { - PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object; - - DPRINT("SetConsoleMode(Output, %d)\n", ConsoleMode); - - if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES) - { - Status = STATUS_INVALID_PARAMETER; } else { @@ -620,7 +577,6 @@ Status = STATUS_INVALID_HANDLE; }
-Quit: return Status; }
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/console.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/console.c [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/console.c [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -15,6 +15,7 @@ #include <ndk/psfuncs.h>
#include <alias.h> +#include <history.h> #include "procinit.h"
#define NDEBUG @@ -427,7 +428,14 @@ Console->NumberOfHistoryBuffers = ConsoleInfo.NumberOfHistoryBuffers; 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 */ memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors)); @@ -755,13 +763,34 @@ PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest; PCONSOLE_IO_OBJECT Object;
+ PULONG ConsoleMode = &ConsoleModeRequest->Mode; + Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ConsoleModeRequest->Handle, &Object, NULL, GENERIC_READ, TRUE, 0); if (!NT_SUCCESS(Status)) return Status;
+ /* Get the standard console modes */ 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); return Status; @@ -773,17 +802,52 @@ IN ULONG ConsoleMode); CSR_API(SrvSetConsoleMode) { +#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | \ + ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE ) + NTSTATUS Status; PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest; PCONSOLE_IO_OBJECT Object; + + ULONG ConsoleMode = ConsoleModeRequest->Mode;
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ConsoleModeRequest->Handle, &Object, NULL, GENERIC_WRITE, TRUE, 0); 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, - 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); return Status;
Added: branches/condrv_restructure/win32ss/user/winsrv/consrv/history.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/history.c (added) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/history.c [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -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 */
Propchange: branches/condrv_restructure/win32ss/user/winsrv/consrv/history.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: branches/condrv_restructure/win32ss/user/winsrv/consrv/history.h URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/history.h (added) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/history.h [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -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);
Propchange: branches/condrv_restructure/win32ss/user/winsrv/consrv/history.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -279,23 +279,11 @@ ULONG ConsoleID; /* The ID of the console */ 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 */ 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 *******************************/ LIST_ENTRY BufferList; /* List of all screen buffers for this console */ @@ -305,8 +293,6 @@ /****************************** Other properties ******************************/ 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 */ - - HANDLE UnpauseEvent; /* When != NULL, event for pausing the console */
COORD ConsoleSize; /* The current size of the console, for text-mode only */ BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -131,8 +131,6 @@ 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 QuickEdit; - /******************************* Pausing support ******************************/ BYTE PauseFlags; LIST_ENTRY ReadWaitQueue; /* List head for the queue of unique input buffer read wait blocks */ @@ -144,6 +142,19 @@ 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 ***************************/ + 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 *************************/ COORD VDMBufferSize; /* Real size of the VDM buffer, in units of ??? */
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.c [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.c [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -12,16 +12,6 @@
#define NDEBUG #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 @@ -40,183 +30,35 @@ /*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 VOID +VOID HistoryAddEntry(PCONSRV_CONSOLE Console, - PUNICODE_STRING ExeName) -{ - UNICODE_STRING NewEntry; - PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); - INT i; - - if (!Hist) return; - - 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 + PUNICODE_STRING ExeName, + PUNICODE_STRING Entry); +BOOL +HistoryRecallHistory(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + INT Offset, + PUNICODE_STRING Entry); +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]; -} - -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; -} + PUNICODE_STRING Entry); +VOID +HistoryDeleteCurrentBuffer(PCONSRV_CONSOLE Console, + PVOID ExeName); +BOOL +HistoryFindEntryByPrefix(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + PUNICODE_STRING Prefix, + PUNICODE_STRING Entry); + + + +/* PRIVATE FUNCTIONS **********************************************************/
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 -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); - } -} - -static VOID -LineInputSetPos(PCONSRV_CONSOLE Console, UINT Pos) +LineInputSetPos(PCONSRV_CONSOLE Console, + UINT Pos) { if (Pos != Console->LinePos && Console->InputBuffer.Mode & ENABLE_ECHO_INPUT) { @@ -240,7 +82,10 @@ }
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; UINT Pos = Console->LinePos; @@ -276,6 +121,7 @@ LineInputSetPos(Console, Pos + NumToInsert); }
+#if 0 static VOID LineInputRecallHistory(PCONSRV_CONSOLE Console, PUNICODE_STRING ExeName, @@ -295,6 +141,22 @@ Hist->Entries[Hist->Position].Length / sizeof(WCHAR), 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 LineInputKeyDown(PCONSRV_CONSOLE Console, @@ -302,9 +164,12 @@ KEY_EVENT_RECORD *KeyEvent) { UINT Pos = Console->LinePos; - PHISTORY_BUFFER Hist; UNICODE_STRING Entry; - INT HistPos; + // INT HistPos; + + /* + * First, deal with control keys... + */
switch (KeyEvent->wVirtualKeyCode) { @@ -314,20 +179,20 @@ LineInputEdit(Console, Console->LineSize, 0, NULL); return; 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); if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) LineInputEdit(Console, Pos, 0, NULL); return; 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)) LineInputEdit(Console, Console->LineSize - Pos, 0, NULL); else LineInputSetPos(Console, Console->LineSize); return; 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)) { while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--; @@ -341,13 +206,12 @@ return; case VK_RIGHT: 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)) { while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++; while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++; LineInputSetPos(Console, Pos); - return; } else { @@ -379,8 +243,10 @@ return; case VK_UP: case VK_F5: - /* Recall previous history entry. On first time, actually recall the - * current (usually last) entry; on subsequent times go back. */ + /* + * 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); Console->LineUpPressed = TRUE; return; @@ -404,24 +270,47 @@ break; case VK_F7: if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) - HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName)); + HistoryDeleteCurrentBuffer(Console, ExeName); return; 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. */ 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. */ + /* + * 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); + 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 */ + /* + * Keep going backwards, even wrapping around to the end, + * until we get back to starting point. + */ HistPos = Hist->Position; do { @@ -437,8 +326,15 @@ } if (--HistPos < 0) HistPos += Hist->NumEntries; } while (HistPos != Hist->Position); - return; - } +#endif + + return; + } + + + /* + * OK, we can continue... + */
if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT) { @@ -452,9 +348,12 @@ } 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 */ + DPRINT1("TODO: Expand aliases\n");
LineInputSetPos(Console, Console->LineSize); Console->LineBuffer[Console->LineSize++] = L'\r'; @@ -466,9 +365,11 @@ } }
- /* 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 - * pre-filled with LineMaxSize - 1 characters. */ + * pre-filled with LineMaxSize - 1 characters. + */ if (Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && Console->LineSize < Console->LineMaxSize) { @@ -507,272 +408,4 @@
/* 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 */
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.h URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.h [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/lineinput.h [iso-8859-1] Fri Aug 29 19:45:45 2014 @@ -1,15 +1,13 @@ /* * LICENSE: GPL - See COPYING in the top level directory * PROJECT: ReactOS Console Server DLL - * FILE: win32ss/user/winsrv/consrv/lineinput.c + * FILE: win32ss/user/winsrv/consrv/lineinput.h * PURPOSE: Console line input functions * PROGRAMMERS: Jeffrey Morlan */
#pragma once
-VOID HistoryDeleteBuffers(PCONSRV_CONSOLE Console); - VOID LineInputKeyDown(PCONSRV_CONSOLE Console, PUNICODE_STRING ExeName,