[KERNEL32][CONSRV]
[reactos.git] / win32ss / user / winsrv / consrv / lineinput.c
index b19082c..c3ae65e 100644 (file)
@@ -4,16 +4,11 @@
  * FILE:            win32ss/user/winsrv/consrv/lineinput.c
  * PURPOSE:         Console line input functions
  * PROGRAMMERS:     Jeffrey Morlan
- *
- * NOTE: It's something frontend-related... (--> read my mind... ;) )
  */
 
 /* INCLUDES *******************************************************************/
 
 #include "consrv.h"
-#include "console.h"
-#include "include/conio.h"
-#include "include/term.h"
 
 #define NDEBUG
 #include <debug.h>
@@ -24,30 +19,45 @@ typedef struct _HISTORY_BUFFER
     UINT Position;
     UINT MaxEntries;
     UINT NumEntries;
-    PUNICODE_STRING Entries;
     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(PCONSOLE Console)
+HistoryCurrentBuffer(PCONSOLE Console,
+                     PUNICODE_STRING ExeName)
 {
-    /* TODO: use actual EXE name sent from process that called ReadConsole */
-    UNICODE_STRING ExeName = { 14, 14, L"cmd.exe" };
     PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
     PHISTORY_BUFFER Hist;
 
     for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
     {
         Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
-        if (RtlEqualUnicodeString(&ExeName, &Hist->ExeName, FALSE))
+        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);
+    Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length);
     if (!Hist) return NULL;
     Hist->MaxEntries = Console->HistoryBufferSize;
     Hist->NumEntries = 0;
@@ -57,18 +67,19 @@ HistoryCurrentBuffer(PCONSOLE Console)
         ConsoleFreeHeap(Hist);
         return NULL;
     }
-    Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName.Length;
+    Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length;
     Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
-    memcpy(Hist->ExeName.Buffer, ExeName.Buffer, ExeName.Length);
+    memcpy(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length);
     InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
     return Hist;
 }
 
 static VOID
-HistoryAddEntry(PCONSOLE Console)
+HistoryAddEntry(PCONSOLE Console,
+                PUNICODE_STRING ExeName)
 {
     UNICODE_STRING NewEntry;
-    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
     INT i;
 
     if (!Hist) return;
@@ -116,9 +127,11 @@ HistoryAddEntry(PCONSOLE Console)
 }
 
 static VOID
-HistoryGetCurrentEntry(PCONSOLE Console, PUNICODE_STRING Entry)
+HistoryGetCurrentEntry(PCONSOLE Console,
+                       PUNICODE_STRING ExeName,
+                       PUNICODE_STRING Entry)
 {
-    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
 
     if (!Hist || Hist->NumEntries == 0)
         Entry->Length = 0;
@@ -127,17 +140,51 @@ HistoryGetCurrentEntry(PCONSOLE Console, PUNICODE_STRING Entry)
 }
 
 static PHISTORY_BUFFER
-HistoryFindBuffer(PCONSOLE Console, PUNICODE_STRING ExeName)
+HistoryFindBuffer(PCONSOLE Console,
+                  PVOID    ExeName,
+                  USHORT   ExeLength,
+                  BOOLEAN  UnicodeExe)
 {
-    PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
+    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 */
-        PHISTORY_BUFFER Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
-        if (RtlPrefixUnicodeString(ExeName, &Hist->ExeName, TRUE))
+        if (RtlPrefixUnicodeString(&ExeNameU, &Hist->ExeName, TRUE))
+        {
+            if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
             return Hist;
+        }
+
         Entry = Entry->Flink;
     }
+
+    if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
     return NULL;
 }
 
@@ -154,7 +201,7 @@ HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
     ConsoleFreeHeap(Hist);
 }
 
-VOID FASTCALL
+VOID
 HistoryDeleteBuffers(PCONSOLE Console)
 {
     PLIST_ENTRY CurrentEntry;
@@ -193,7 +240,7 @@ LineInputSetPos(PCONSOLE Console, UINT Pos)
 }
 
 static VOID
-LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Insertion)
+LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHAR Insertion)
 {
     PTEXTMODE_SCREEN_BUFFER ActiveBuffer;
     UINT Pos = Console->LinePos;
@@ -230,9 +277,11 @@ LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Inser
 }
 
 static VOID
-LineInputRecallHistory(PCONSOLE Console, INT Offset)
+LineInputRecallHistory(PCONSOLE Console,
+                       PUNICODE_STRING ExeName,
+                       INT Offset)
 {
-    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+    PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
     UINT Position = 0;
 
     if (!Hist || Hist->NumEntries == 0) return;
@@ -247,8 +296,10 @@ LineInputRecallHistory(PCONSOLE Console, INT Offset)
                   Hist->Entries[Hist->Position].Buffer);
 }
 
-VOID FASTCALL
-LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
+VOID
+LineInputKeyDown(PCONSOLE Console,
+                 PUNICODE_STRING ExeName,
+                 KEY_EVENT_RECORD *KeyEvent)
 {
     UINT Pos = Console->LinePos;
     PHISTORY_BUFFER Hist;
@@ -301,7 +352,7 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
         else
         {
             /* Recall one character (but don't overwrite current line) */
-            HistoryGetCurrentEntry(Console, &Entry);
+            HistoryGetCurrentEntry(Console, ExeName, &Entry);
             if (Pos < Console->LineSize)
                 LineInputSetPos(Console, Pos + 1);
             else if (Pos * sizeof(WCHAR) < Entry.Length)
@@ -320,26 +371,26 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
         return;
     case VK_PRIOR:
         /* Recall first history entry */
-        LineInputRecallHistory(Console, -((WORD)-1));
+        LineInputRecallHistory(Console, ExeName, -((WORD)-1));
         return;
     case VK_NEXT:
         /* Recall last history entry */
-        LineInputRecallHistory(Console, +((WORD)-1));
+        LineInputRecallHistory(Console, ExeName, +((WORD)-1));
         return;
     case VK_UP:
     case VK_F5:
         /* Recall previous history entry. On first time, actually recall the
          * current (usually last) entry; on subsequent times go back. */
-        LineInputRecallHistory(Console, Console->LineUpPressed ? -1 : 0);
+        LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0);
         Console->LineUpPressed = TRUE;
         return;
     case VK_DOWN:
         /* Recall next history entry */
-        LineInputRecallHistory(Console, +1);
+        LineInputRecallHistory(Console, ExeName, +1);
         return;
     case VK_F3:
         /* Recall remainder of current history entry */
-        HistoryGetCurrentEntry(Console, &Entry);
+        HistoryGetCurrentEntry(Console, ExeName, &Entry);
         if (Pos * sizeof(WCHAR) < Entry.Length)
         {
             UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos);
@@ -353,11 +404,11 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
         break;
     case VK_F7:
         if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
-            HistoryDeleteBuffer(HistoryCurrentBuffer(Console));
+            HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName));
         return;
     case VK_F8:
         /* Search for history entries starting with input. */
-        Hist = HistoryCurrentBuffer(Console);
+        Hist = HistoryCurrentBuffer(Console, ExeName);
         if (!Hist || Hist->NumEntries == 0) return;
 
         /* Like Up/F5, on first time start from current (usually last) entry,
@@ -401,7 +452,7 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
     }
     else if (KeyEvent->uChar.UnicodeChar == L'\r')
     {
-        HistoryAddEntry(Console);
+        HistoryAddEntry(Console, ExeName);
 
         /* TODO: Expand aliases */
 
@@ -447,8 +498,8 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
         else
         {
             /* Normal character */
-            BOOL Overstrike = Console->LineInsertToggle && Console->LinePos != Console->LineSize;
-            LineInputEdit(Console, Overstrike, 1, &KeyEvent->uChar.UnicodeChar);
+            BOOL Overstrike = !Console->LineInsertToggle && (Console->LinePos != Console->LineSize);
+            LineInputEdit(Console, (Overstrike ? 1 : 0), 1, &KeyEvent->uChar.UnicodeChar);
         }
     }
 }
@@ -458,163 +509,216 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
 
 CSR_API(SrvGetConsoleCommandHistory)
 {
+    NTSTATUS Status;
     PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest;
-    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
     PCONSOLE Console;
-    NTSTATUS Status;
+    ULONG BytesWritten = 0;
     PHISTORY_BUFFER Hist;
-    PBYTE Buffer = (PBYTE)GetCommandHistoryRequest->History;
-    ULONG BufferSize = GetCommandHistoryRequest->Length;
-    UINT  i;
+
+    DPRINT1("SrvGetConsoleCommandHistory entered\n");
 
     if ( !CsrValidateMessageBuffer(ApiMessage,
                                    (PVOID*)&GetCommandHistoryRequest->History,
-                                   GetCommandHistoryRequest->Length,
+                                   GetCommandHistoryRequest->HistoryLength,
                                    sizeof(BYTE))                    ||
          !CsrValidateMessageBuffer(ApiMessage,
-                                   (PVOID*)&GetCommandHistoryRequest->ExeName.Buffer,
-                                   GetCommandHistoryRequest->ExeName.Length,
+                                   (PVOID*)&GetCommandHistoryRequest->ExeName,
+                                   GetCommandHistoryRequest->ExeLength,
                                    sizeof(BYTE)) )
     {
         return STATUS_INVALID_PARAMETER;
     }
 
-    Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
-    if (NT_SUCCESS(Status))
+    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Hist = HistoryFindBuffer(Console,
+                             GetCommandHistoryRequest->ExeName,
+                             GetCommandHistoryRequest->ExeLength,
+                             GetCommandHistoryRequest->Unicode2);
+    if (Hist)
     {
-        Hist = HistoryFindBuffer(Console, &GetCommandHistoryRequest->ExeName);
-        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
         {
-            for (i = 0; i < Hist->NumEntries; i++)
+            TargetBufferA = GetCommandHistoryRequest->History;
+        }
+
+        for (i = 0; i < Hist->NumEntries; i++)
+        {
+            SourceLength = Hist->Entries[i].Length / sizeof(WCHAR);
+            if (Offset + SourceLength + 1 > BufferSize)
             {
-                if (BufferSize < (Hist->Entries[i].Length + sizeof(WCHAR)))
-                {
-                    Status = STATUS_BUFFER_OVERFLOW;
-                    break;
-                }
-                memcpy(Buffer, Hist->Entries[i].Buffer, Hist->Entries[i].Length);
-                Buffer += Hist->Entries[i].Length;
-                *(PWCHAR)Buffer = L'\0';
-                Buffer += sizeof(WCHAR);
+                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';
             }
         }
-        GetCommandHistoryRequest->Length = Buffer - (PBYTE)GetCommandHistoryRequest->History;
-        ConSrvReleaseConsole(Console, TRUE);
+
+        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;
-    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
     PCONSOLE Console;
-    NTSTATUS Status;
     PHISTORY_BUFFER Hist;
     ULONG Length = 0;
     UINT  i;
 
     if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID*)&GetCommandHistoryLengthRequest->ExeName.Buffer,
-                                  GetCommandHistoryLengthRequest->ExeName.Length,
+                                  (PVOID*)&GetCommandHistoryLengthRequest->ExeName,
+                                  GetCommandHistoryLengthRequest->ExeLength,
                                   sizeof(BYTE)))
     {
         return STATUS_INVALID_PARAMETER;
     }
 
-    Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
-    if (NT_SUCCESS(Status))
+    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Hist = HistoryFindBuffer(Console,
+                             GetCommandHistoryLengthRequest->ExeName,
+                             GetCommandHistoryLengthRequest->ExeLength,
+                             GetCommandHistoryLengthRequest->Unicode2);
+    if (Hist)
     {
-        Hist = HistoryFindBuffer(Console, &GetCommandHistoryLengthRequest->ExeName);
-        if (Hist)
-        {
-            for (i = 0; i < Hist->NumEntries; i++)
-                Length += Hist->Entries[i].Length + sizeof(WCHAR);
-        }
-        GetCommandHistoryLengthRequest->Length = Length;
-        ConSrvReleaseConsole(Console, TRUE);
+        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;
-    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
     PCONSOLE Console;
     PHISTORY_BUFFER Hist;
-    NTSTATUS Status;
 
     if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID*)&ExpungeCommandHistoryRequest->ExeName.Buffer,
-                                  ExpungeCommandHistoryRequest->ExeName.Length,
+                                  (PVOID*)&ExpungeCommandHistoryRequest->ExeName,
+                                  ExpungeCommandHistoryRequest->ExeLength,
                                   sizeof(BYTE)))
     {
         return STATUS_INVALID_PARAMETER;
     }
 
-    Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
-    if (NT_SUCCESS(Status))
-    {
-        Hist = HistoryFindBuffer(Console, &ExpungeCommandHistoryRequest->ExeName);
-        HistoryDeleteBuffer(Hist);
-        ConSrvReleaseConsole(Console, TRUE);
-    }
+    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;
-    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
     PCONSOLE Console;
     PHISTORY_BUFFER Hist;
-    NTSTATUS Status;
-    UINT MaxEntries = SetHistoryNumberCommandsRequest->NumCommands;
-    PUNICODE_STRING OldEntryList, NewEntryList;
 
     if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID*)&SetHistoryNumberCommandsRequest->ExeName.Buffer,
-                                  SetHistoryNumberCommandsRequest->ExeName.Length,
+                                  (PVOID*)&SetHistoryNumberCommandsRequest->ExeName,
+                                  SetHistoryNumberCommandsRequest->ExeLength,
                                   sizeof(BYTE)))
     {
         return STATUS_INVALID_PARAMETER;
     }
 
-    Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
-    if (NT_SUCCESS(Status))
+    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Hist = HistoryFindBuffer(Console,
+                             SetHistoryNumberCommandsRequest->ExeName,
+                             SetHistoryNumberCommandsRequest->ExeLength,
+                             SetHistoryNumberCommandsRequest->Unicode2);
+    if (Hist)
     {
-        Hist = HistoryFindBuffer(Console, &SetHistoryNumberCommandsRequest->ExeName);
-        if (Hist)
+        UINT MaxEntries = SetHistoryNumberCommandsRequest->NumCommands;
+        PUNICODE_STRING OldEntryList = Hist->Entries;
+        PUNICODE_STRING NewEntryList = ConsoleAllocHeap(0, MaxEntries * sizeof(UNICODE_STRING));
+        if (!NewEntryList)
         {
-            OldEntryList = Hist->Entries;
-            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--)
             {
-                Status = STATUS_NO_MEMORY;
+                RtlFreeUnicodeString(Hist->Entries++);
+                Hist->Position += (Hist->Position == 0);
             }
-            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);
-            }
+            Hist->MaxEntries = MaxEntries;
+            Hist->Entries = memcpy(NewEntryList, Hist->Entries,
+                                   Hist->NumEntries * sizeof(UNICODE_STRING));
+            ConsoleFreeHeap(OldEntryList);
         }
-        ConSrvReleaseConsole(Console, TRUE);
     }
+
+    ConSrvReleaseConsole(Console, TRUE);
     return Status;
 }
 
 CSR_API(SrvGetConsoleHistory)
 {
+#if 0 // Vista+
     PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest;
     PCONSOLE Console;
     NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
@@ -626,10 +730,15 @@ CSR_API(SrvGetConsoleHistory)
         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;
     PCONSOLE Console;
     NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
@@ -641,12 +750,29 @@ CSR_API(SrvSetConsoleHistory)
         ConSrvReleaseConsole(Console, TRUE);
     }
     return Status;
+#else
+    DPRINT1("%s not yet implemented\n", __FUNCTION__);
+    return STATUS_NOT_IMPLEMENTED;
+#endif
 }
 
 CSR_API(SrvSetConsoleCommandHistoryMode)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PCONSOLE_SETHISTORYMODE SetHistoryModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryModeRequest;
+    PCONSOLE 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 */