Sync to trunk head (r47736)
[reactos.git] / dll / win32 / kernel32 / misc / console.c
index aaf48ac..d1e8a97 100644 (file)
@@ -178,6 +178,37 @@ ConsoleControlDispatcher(DWORD CodeAndFlag)
     ExitThread(nExitCode);
 }
 
+/* Get the size needed to copy a string to a capture buffer, including alignment */
+static ULONG
+IntStringSize(LPCVOID String,
+              BOOL Unicode)
+{
+    ULONG Size = (Unicode ? wcslen(String) : strlen(String)) * sizeof(WCHAR);
+    return (Size + 3) & -4;
+}
+
+/* Copy a string to a capture buffer */
+static VOID
+IntCaptureMessageString(PCSR_CAPTURE_BUFFER CaptureBuffer,
+                        LPCVOID String,
+                        BOOL Unicode,
+                        PUNICODE_STRING RequestString)
+{
+    ULONG Size;
+    if (Unicode)
+    {
+        Size = wcslen(String) * sizeof(WCHAR);
+        CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)String, Size, (PVOID *)&RequestString->Buffer);
+    }
+    else
+    {
+        Size = strlen(String);
+        CsrAllocateMessagePointer(CaptureBuffer, Size * sizeof(WCHAR), (PVOID *)&RequestString->Buffer);
+        Size = MultiByteToWideChar(CP_ACP, 0, String, Size, RequestString->Buffer, Size * sizeof(WCHAR))
+               * sizeof(WCHAR);
+    }
+    RequestString->Length = RequestString->MaximumLength = Size;
+}
 
 /* FUNCTIONS *****************************************************************/
 
@@ -336,29 +367,56 @@ DuplicateConsoleHandle(HANDLE hConsole,
 }
 
 
+static BOOL
+IntExpungeConsoleCommandHistory(LPCVOID lpExeName, BOOL bUnicode)
+{
+    CSR_API_MESSAGE Request;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    ULONG CsrRequest = MAKE_CSR_API(EXPUNGE_COMMAND_HISTORY, CSR_CONSOLE);
+    NTSTATUS Status;
+
+    if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode));
+    if (!CaptureBuffer)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+    IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode,
+                            &Request.Data.ExpungeCommandHistory.ExeName);
+    Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE));
+    CsrFreeCaptureBuffer(CaptureBuffer);
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
+    {
+        SetLastErrorByStatus(Status);
+        return FALSE;
+    }
+    return TRUE;
+}
+
 /*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
  */
-DWORD
+BOOL
 WINAPI
-ExpungeConsoleCommandHistoryW(DWORD Unknown0)
+ExpungeConsoleCommandHistoryW(LPCWSTR lpExeName)
 {
-    DPRINT1("ExpungeConsoleCommandHistoryW(0x%x) UNIMPLEMENTED!\n", Unknown0);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
+    return IntExpungeConsoleCommandHistory(lpExeName, TRUE);
 }
 
-
 /*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
  */
-DWORD
+BOOL
 WINAPI
-ExpungeConsoleCommandHistoryA (DWORD Unknown0)
+ExpungeConsoleCommandHistoryA(LPCSTR lpExeName)
 {
-    DPRINT1("ExpungeConsoleCommandHistoryW(0x%x) UNIMPLEMENTED!\n", Unknown0);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
+    return IntExpungeConsoleCommandHistory(lpExeName, FALSE);
 }
 
 
@@ -772,61 +830,139 @@ GetConsoleAliasesLengthA(LPSTR lpExeName)
 }
 
 
+static DWORD
+IntGetConsoleCommandHistory(LPVOID lpHistory, DWORD cbHistory, LPCVOID lpExeName, BOOL bUnicode)
+{
+    CSR_API_MESSAGE Request;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    ULONG CsrRequest = MAKE_CSR_API(GET_COMMAND_HISTORY, CSR_CONSOLE);
+    NTSTATUS Status;
+    DWORD HistoryLength = cbHistory * (bUnicode ? 1 : sizeof(WCHAR));
+
+    if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+
+    CaptureBuffer = CsrAllocateCaptureBuffer(2, IntStringSize(lpExeName, bUnicode) +
+                                                HistoryLength);
+    if (!CaptureBuffer)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return 0;
+    }
+    IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode,
+                            &Request.Data.GetCommandHistory.ExeName);
+    Request.Data.GetCommandHistory.Length = HistoryLength;
+    CsrAllocateMessagePointer(CaptureBuffer, HistoryLength,
+                              (PVOID*)&Request.Data.GetCommandHistory.History);
+
+    Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
+    {
+        CsrFreeCaptureBuffer(CaptureBuffer);
+        SetLastErrorByStatus(Status);
+        return 0;
+    }
+
+    if (bUnicode)
+    {
+        memcpy(lpHistory,
+               Request.Data.GetCommandHistory.History,
+               Request.Data.GetCommandHistory.Length);
+    }
+    else
+    {
+        WideCharToMultiByte(CP_ACP, 0,
+                            Request.Data.GetCommandHistory.History,
+                            Request.Data.GetCommandHistory.Length / sizeof(WCHAR),
+                            lpHistory,
+                            cbHistory,
+                            NULL, NULL);
+    }
+    CsrFreeCaptureBuffer(CaptureBuffer);
+    return Request.Data.GetCommandHistory.Length;
+}
+
 /*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
  */
 DWORD
 WINAPI
-GetConsoleCommandHistoryW(DWORD Unknown0,
-                          DWORD Unknown1,
-                          DWORD Unknown2)
+GetConsoleCommandHistoryW(LPWSTR lpHistory,
+                          DWORD cbHistory,
+                          LPCWSTR lpExeName)
 {
-    DPRINT1("GetConsoleCommandHistoryW(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
+    return IntGetConsoleCommandHistory(lpHistory, cbHistory, lpExeName, TRUE);
 }
 
-
 /*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
  */
 DWORD
 WINAPI
-GetConsoleCommandHistoryA(DWORD Unknown0,
-                          DWORD Unknown1,
-                          DWORD Unknown2)
+GetConsoleCommandHistoryA(LPSTR lpHistory,
+                          DWORD cbHistory,
+                          LPCSTR lpExeName)
 {
-    DPRINT1("GetConsoleCommandHistoryA(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
+    return IntGetConsoleCommandHistory(lpHistory, cbHistory, lpExeName, FALSE);
 }
 
 
+static DWORD
+IntGetConsoleCommandHistoryLength(LPCVOID lpExeName, BOOL bUnicode)
+{
+    CSR_API_MESSAGE Request;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    ULONG CsrRequest = MAKE_CSR_API(GET_COMMAND_HISTORY_LENGTH, CSR_CONSOLE);
+    NTSTATUS Status;
+
+    if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode));
+    if (!CaptureBuffer)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return 0;
+    }
+    IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode,
+                            &Request.Data.GetCommandHistoryLength.ExeName);
+    Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE));
+    CsrFreeCaptureBuffer(CaptureBuffer);
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
+    {
+        SetLastErrorByStatus(Status);
+        return 0;
+    }
+    return Request.Data.GetCommandHistoryLength.Length;
+}
+
 /*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
  */
 DWORD
 WINAPI
-GetConsoleCommandHistoryLengthW(DWORD Unknown0)
+GetConsoleCommandHistoryLengthW(LPCWSTR lpExeName)
 {
-    DPRINT1("GetConsoleCommandHistoryLengthW(0x%x) UNIMPLEMENTED!\n", Unknown0);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
+    return IntGetConsoleCommandHistoryLength(lpExeName, TRUE);
 }
 
-
 /*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
  */
 DWORD
 WINAPI
-GetConsoleCommandHistoryLengthA(DWORD Unknown0)
+GetConsoleCommandHistoryLengthA(LPCSTR lpExeName)
 {
-    DPRINT1("GetConsoleCommandHistoryLengthA(0x%x) UNIMPLEMENTED!\n", Unknown0);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
+    return IntGetConsoleCommandHistoryLength(lpExeName, FALSE) / sizeof(WCHAR);
 }
 
+
 /*
  * @unimplemented
  */
@@ -1038,19 +1174,6 @@ OpenConsoleW(LPCWSTR wsName,
 }
 
 
-/*
- * @unimplemented (Undocumented)
- */
-BOOL
-WINAPI
-SetConsoleCommandHistoryMode(DWORD dwMode)
-{
-    DPRINT1("SetConsoleCommandHistoryMode(0x%x) UNIMPLEMENTED!\n", dwMode);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-
 /*
  * @unimplemented (Undocumented)
  */
@@ -1176,31 +1299,61 @@ SetConsoleMenuClose(DWORD Unknown0)
 }
 
 
+static BOOL
+IntSetConsoleNumberOfCommands(DWORD dwNumCommands,
+                              LPCVOID lpExeName,
+                              BOOL bUnicode)
+{
+    CSR_API_MESSAGE Request;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    ULONG CsrRequest = MAKE_CSR_API(SET_HISTORY_NUMBER_COMMANDS, CSR_CONSOLE);
+    NTSTATUS Status;
+
+    if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode));
+    if (!CaptureBuffer)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+    IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode,
+                            &Request.Data.SetHistoryNumberCommands.ExeName);
+    Request.Data.SetHistoryNumberCommands.NumCommands = dwNumCommands;
+    Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE));
+    CsrFreeCaptureBuffer(CaptureBuffer);
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
+    {
+        SetLastErrorByStatus(Status);
+        return FALSE;
+    }
+    return TRUE;
+}
+
 /*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
  */
 BOOL
 WINAPI
-SetConsoleNumberOfCommandsA(DWORD Unknown0,
-                            DWORD Unknown1)
+SetConsoleNumberOfCommandsA(DWORD dwNumCommands,
+                            LPCWSTR lpExeName)
 {
-    DPRINT1("SetConsoleNumberOfCommandsA(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    return IntSetConsoleNumberOfCommands(dwNumCommands, lpExeName, FALSE);
 }
 
-
 /*
- * @unimplemented (Undocumented)
+ * @implemented (Undocumented)
  */
 BOOL
 WINAPI
-SetConsoleNumberOfCommandsW(DWORD Unknown0,
-                            DWORD Unknown1)
+SetConsoleNumberOfCommandsW(DWORD dwNumCommands,
+                            LPCSTR lpExeName)
 {
-    DPRINT1("SetConsoleNumberOfCommandsW(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    return IntSetConsoleNumberOfCommands(dwNumCommands, lpExeName, TRUE);
 }
 
 
@@ -1545,34 +1698,45 @@ IntReadConsole(HANDLE hConsoleInput,
                PVOID lpBuffer,
                DWORD nNumberOfCharsToRead,
                LPDWORD lpNumberOfCharsRead,
-               PCONSOLE_READCONSOLE_CONTROL lpReserved,
+               PCONSOLE_READCONSOLE_CONTROL pInputControl,
                BOOL bUnicode)
 {
-    PCSR_API_MESSAGE Request;
-    ULONG CsrRequest;
-    NTSTATUS Status;
-    ULONG CharSize, CharsRead = 0;
+    CSR_API_MESSAGE Request;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    ULONG CsrRequest = MAKE_CSR_API(READ_CONSOLE, CSR_CONSOLE);
+    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
 
-    CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
-    Request = RtlAllocateHeap(RtlGetProcessHeap(),
-                              0,
-                              max(sizeof(CSR_API_MESSAGE),
-                              CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + min(nNumberOfCharsToRead,
-                              CSRSS_MAX_READ_CONSOLE / CharSize) * CharSize));
-    if (Request == NULL)
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, nNumberOfCharsToRead * CharSize);
+    if (CaptureBuffer == NULL)
     {
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
-    Request->Status = STATUS_SUCCESS;
-    CsrRequest = MAKE_CSR_API(READ_CONSOLE, CSR_CONSOLE);
+    CsrAllocateMessagePointer(CaptureBuffer,
+                              nNumberOfCharsToRead * CharSize,
+                              &Request.Data.ReadConsoleRequest.Buffer);
+
+    Request.Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
+    Request.Data.ReadConsoleRequest.Unicode = bUnicode;
+    Request.Data.ReadConsoleRequest.NrCharactersToRead = (WORD)nNumberOfCharsToRead;
+    Request.Data.ReadConsoleRequest.NrCharactersRead = 0;
+    Request.Data.ReadConsoleRequest.CtrlWakeupMask = 0;
+    if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
+    {
+        Request.Data.ReadConsoleRequest.NrCharactersRead = pInputControl->nInitialChars;
+        memcpy(Request.Data.ReadConsoleRequest.Buffer,
+               lpBuffer,
+               pInputControl->nInitialChars * sizeof(WCHAR));
+        Request.Data.ReadConsoleRequest.CtrlWakeupMask = pInputControl->dwCtrlWakeupMask;
+    }
 
     do
     {
-        if (Request->Status == STATUS_PENDING)
+        if (Status == STATUS_PENDING)
         {
-            Status = NtWaitForSingleObject(Request->Data.ReadConsoleRequest.EventHandle,
+            Status = NtWaitForSingleObject(Request.Data.ReadConsoleRequest.EventHandle,
                                            FALSE,
                                            0);
             if (!NT_SUCCESS(Status))
@@ -1582,50 +1746,28 @@ IntReadConsole(HANDLE hConsoleInput,
             }
         }
 
-        Request->Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
-        Request->Data.ReadConsoleRequest.Unicode = bUnicode;
-        Request->Data.ReadConsoleRequest.NrCharactersToRead = (WORD)min(nNumberOfCharsToRead, CSRSS_MAX_READ_CONSOLE / CharSize);
-        Request->Data.ReadConsoleRequest.nCharsCanBeDeleted = (WORD)CharsRead;
-
-        Status = CsrClientCallServer(Request,
-                                     NULL,
-                                     CsrRequest,
-                                     max(sizeof(CSR_API_MESSAGE),
-                                     CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE)
-                                       + Request->Data.ReadConsoleRequest.NrCharactersToRead * CharSize));
-
-        if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
+        Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE));
+        if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
         {
             DPRINT1("CSR returned error in ReadConsole\n");
-            RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
+            CsrFreeCaptureBuffer(CaptureBuffer);
             SetLastErrorByStatus(Status);
             return FALSE;
         }
-
-        nNumberOfCharsToRead -= Request->Data.ReadConsoleRequest.NrCharactersRead;
-        memcpy((PVOID)((ULONG_PTR)lpBuffer + (ULONG_PTR)(CharsRead * CharSize)),
-               Request->Data.ReadConsoleRequest.Buffer,
-               Request->Data.ReadConsoleRequest.NrCharactersRead * CharSize);
-        CharsRead += Request->Data.ReadConsoleRequest.NrCharactersRead;
-
-        if (Request->Status == STATUS_NOTIFY_CLEANUP)
-        {
-            if(CharsRead > 0)
-            {
-                CharsRead--;
-                nNumberOfCharsToRead++;
-            }
-            Request->Status = STATUS_PENDING;
-        }
     }
-    while (Request->Status == STATUS_PENDING && nNumberOfCharsToRead > 0);
+    while (Status == STATUS_PENDING);
+
+    memcpy(lpBuffer,
+           Request.Data.ReadConsoleRequest.Buffer,
+           Request.Data.ReadConsoleRequest.NrCharactersRead * CharSize);
 
     if (lpNumberOfCharsRead != NULL)
-    {
-        *lpNumberOfCharsRead = CharsRead;
-    }
+        *lpNumberOfCharsRead = Request.Data.ReadConsoleRequest.NrCharactersRead;
 
-    RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
+    if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
+        pInputControl->dwControlKeyState = Request.Data.ReadConsoleRequest.ControlKeyState;
+
+    CsrFreeCaptureBuffer(CaptureBuffer);
 
     return TRUE;
 }
@@ -1648,7 +1790,7 @@ ReadConsoleA(HANDLE hConsoleInput,
                           lpBuffer,
                           nNumberOfCharsToRead,
                           lpNumberOfCharsRead,
-                          pInputControl,
+                          NULL,
                           FALSE);
 }
 
@@ -3418,58 +3560,76 @@ GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
 }
 
 
-/*--------------------------------------------------------------
- *    GetConsoleTitleW
- *
- * @implemented
- */
-DWORD
-WINAPI
-GetConsoleTitleW(LPWSTR lpConsoleTitle,
-                 DWORD nSize)
+static DWORD
+IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD nSize, BOOL bUnicode)
 {
-    PCSR_API_MESSAGE Request;
-    ULONG CsrRequest;
+    CSR_API_MESSAGE Request;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    ULONG CsrRequest = MAKE_CSR_API(GET_TITLE, CSR_CONSOLE);
     NTSTATUS Status;
 
-    Request = RtlAllocateHeap(RtlGetProcessHeap(),
-                              0,
-                              CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_TITLE) + CSRSS_MAX_TITLE_LENGTH * sizeof(WCHAR));
-    if (Request == NULL)
+    if (nSize == 0)
+        return 0;
+
+    Request.Data.GetTitleRequest.Length = nSize * (bUnicode ? 1 : sizeof(WCHAR));
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, Request.Data.GetTitleRequest.Length);
+    if (CaptureBuffer == NULL)
     {
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
+        return 0;
     }
 
-    CsrRequest = MAKE_CSR_API(GET_TITLE, CSR_CONSOLE);
+    CsrAllocateMessagePointer(CaptureBuffer,
+                              Request.Data.GetTitleRequest.Length,
+                              (PVOID*)&Request.Data.GetTitleRequest.Title);
 
-    Status = CsrClientCallServer(Request,
-                                 NULL,
-                                 CsrRequest,
-                                 CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_TITLE) + CSRSS_MAX_TITLE_LENGTH * sizeof(WCHAR));
-    if (!NT_SUCCESS(Status) || !(NT_SUCCESS(Status = Request->Status)))
+    Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE));
+    if (!NT_SUCCESS(Status) || !(NT_SUCCESS(Status = Request.Status)))
     {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
+        CsrFreeCaptureBuffer(CaptureBuffer);
         SetLastErrorByStatus(Status);
         return 0;
     }
 
-    if (nSize * sizeof(WCHAR) <= Request->Data.GetTitleRequest.Length)
+    if (bUnicode)
     {
-        nSize--;
+        if (nSize >= sizeof(WCHAR))
+            wcscpy((LPWSTR)lpConsoleTitle, Request.Data.GetTitleRequest.Title);
     }
     else
     {
-        nSize = Request->Data.GetTitleRequest.Length / sizeof (WCHAR);
+        if (nSize < Request.Data.GetTitleRequest.Length / sizeof(WCHAR) ||
+            !WideCharToMultiByte(CP_ACP, // ANSI code page
+                                 0, // performance and mapping flags
+                                 Request.Data.GetTitleRequest.Title, // address of wide-character string
+                                 -1, // number of characters in string
+                                 (LPSTR)lpConsoleTitle, // address of buffer for new string
+                                 nSize, // size of buffer
+                                 NULL, // FAST
+                                 NULL))
+        {
+            /* Yes, if the buffer isn't big enough, it returns 0... Bad API */
+            *(LPSTR)lpConsoleTitle = '\0';
+            Request.Data.GetTitleRequest.Length = 0;
+        }
     }
-    memcpy(lpConsoleTitle, Request->Data.GetTitleRequest.Title, nSize * sizeof(WCHAR));
-    lpConsoleTitle[nSize] = L'\0';
-
-    RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
+    CsrFreeCaptureBuffer(CaptureBuffer);
 
-    return nSize;
+    return Request.Data.GetTitleRequest.Length / sizeof(WCHAR);
 }
 
+/*--------------------------------------------------------------
+ *    GetConsoleTitleW
+ *
+ * @implemented
+ */
+DWORD
+WINAPI
+GetConsoleTitleW(LPWSTR lpConsoleTitle,
+                 DWORD nSize)
+{
+    return IntGetConsoleTitle(lpConsoleTitle, nSize, TRUE);
+}
 
 /*--------------------------------------------------------------
  *     GetConsoleTitleA
@@ -3483,28 +3643,7 @@ WINAPI
 GetConsoleTitleA(LPSTR lpConsoleTitle,
                  DWORD nSize)
 {
-    WCHAR WideTitle [CSRSS_MAX_TITLE_LENGTH + 1];
-    DWORD nWideTitle = CSRSS_MAX_TITLE_LENGTH + 1;
-    DWORD nWritten;
-
-    if (!lpConsoleTitle || !nSize) return 0;
-    nWideTitle = GetConsoleTitleW((LPWSTR) WideTitle, nWideTitle);
-    if (!nWideTitle) return 0;
-
-    if ((nWritten = WideCharToMultiByte(CP_ACP, // ANSI code page
-                                        0, // performance and mapping flags
-                                        (LPWSTR) WideTitle, // address of wide-character string
-                                        nWideTitle, // number of characters in string
-                                        lpConsoleTitle, // address of buffer for new string
-                                        nSize - 1, // size of buffer
-                                        NULL, // FAST
-                                        NULL))) // FAST
-    {
-        lpConsoleTitle[nWritten] = '\0';
-        return nWritten;
-    }
-
-    return 0;
+    return IntGetConsoleTitle(lpConsoleTitle, nSize, FALSE);
 }
 
 
@@ -3517,41 +3656,33 @@ BOOL
 WINAPI
 SetConsoleTitleW(LPCWSTR lpConsoleTitle)
 {
-    PCSR_API_MESSAGE Request;
-    ULONG CsrRequest;
+    CSR_API_MESSAGE Request;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    ULONG CsrRequest = MAKE_CSR_API(SET_TITLE, CSR_CONSOLE);
     NTSTATUS Status;
-    unsigned int c;
 
-    Request = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                              max(sizeof(CSR_API_MESSAGE),
-                              CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE) +
-                                 min(wcslen(lpConsoleTitle), CSRSS_MAX_TITLE_LENGTH) * sizeof(WCHAR)));
-    if (Request == NULL)
+    Request.Data.SetTitleRequest.Length = wcslen(lpConsoleTitle) * sizeof(WCHAR);
+
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, Request.Data.SetTitleRequest.Length);
+    if (CaptureBuffer == NULL)
     {
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
-    CsrRequest = MAKE_CSR_API(SET_TITLE, CSR_CONSOLE);
-
-    for (c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++)
-        Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
+    CsrCaptureMessageBuffer(CaptureBuffer,
+                            (PVOID)lpConsoleTitle,
+                            Request.Data.SetTitleRequest.Length,
+                            (PVOID*)&Request.Data.SetTitleRequest.Title);
 
-    Request->Data.SetTitleRequest.Length = c * sizeof(WCHAR);
-    Status = CsrClientCallServer(Request,
-                                 NULL,
-                                 CsrRequest,
-                                 max(sizeof(CSR_API_MESSAGE),
-                                 CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE) + c * sizeof(WCHAR)));
-    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
+    Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE));
+    CsrFreeCaptureBuffer(CaptureBuffer);
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
     {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
         SetLastErrorByStatus(Status);
-        return(FALSE);
+        return FALSE;
     }
 
-    RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
-
     return TRUE;
 }
 
@@ -3567,43 +3698,18 @@ BOOL
 WINAPI
 SetConsoleTitleA(LPCSTR lpConsoleTitle)
 {
-    PCSR_API_MESSAGE Request;
-    ULONG CsrRequest;
-    NTSTATUS Status;
-    unsigned int c;
-
-    Request = RtlAllocateHeap(RtlGetProcessHeap(),
-                              0,
-                              max(sizeof(CSR_API_MESSAGE),
-                              CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE) +
-                                min(strlen(lpConsoleTitle), CSRSS_MAX_TITLE_LENGTH) * sizeof(WCHAR)));
-    if (Request == NULL)
+    ULONG Length = strlen(lpConsoleTitle) + 1;
+    LPWSTR WideTitle = HeapAlloc(GetProcessHeap(), 0, Length * sizeof(WCHAR));
+    BOOL Ret;
+    if (!WideTitle)
     {
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
-
-    CsrRequest = MAKE_CSR_API(SET_TITLE, CSR_CONSOLE);
-
-    for (c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++)
-        Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
-
-    Request->Data.SetTitleRequest.Length = c * sizeof(WCHAR);
-    Status = CsrClientCallServer(Request,
-                                 NULL,
-                                 CsrRequest,
-                                 max(sizeof(CSR_API_MESSAGE),
-                                 CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE) + c * sizeof(WCHAR)));
-    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
-    {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
-        SetLastErrorByStatus(Status);
-        return(FALSE);
-    }
-
-    RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
-
-    return TRUE;
+    MultiByteToWideChar(CP_ACP, 0, lpConsoleTitle, -1, WideTitle, Length);
+    Ret = SetConsoleTitleW(WideTitle);
+    HeapFree(GetProcessHeap(), 0, WideTitle);
+    return Ret;
 }
 
 
@@ -4073,30 +4179,60 @@ GetConsoleInputExeNameA(DWORD nBufferLength, LPSTR lpBuffer)
 /*--------------------------------------------------------------
  *  GetConsoleHistoryInfo
  *
- * @unimplemented
+ * @implemented
  */
 BOOL
 WINAPI
 GetConsoleHistoryInfo(PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo)
 {
-    DPRINT1("GetConsoleHistoryInfo(0x%p) UNIMPLEMENTED!\n", lpConsoleHistoryInfo);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    CSR_API_MESSAGE Request;
+    ULONG CsrRequest = MAKE_CSR_API(GET_HISTORY_INFO, CSR_CONSOLE);
+    NTSTATUS Status;
+    if (lpConsoleHistoryInfo->cbSize != sizeof(CONSOLE_HISTORY_INFO))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
+    {
+        SetLastErrorByStatus(Status);
+        return FALSE;
+    }
+    lpConsoleHistoryInfo->HistoryBufferSize      = Request.Data.GetHistoryInfo.HistoryBufferSize;
+    lpConsoleHistoryInfo->NumberOfHistoryBuffers = Request.Data.GetHistoryInfo.NumberOfHistoryBuffers;
+    lpConsoleHistoryInfo->dwFlags                = Request.Data.GetHistoryInfo.dwFlags;
+    return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *  SetConsoleHistoryInfo
  *
- * @unimplemented
+ * @implemented
  */
 BOOL
 WINAPI
 SetConsoleHistoryInfo(IN PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo)
 {
-    DPRINT1("SetConsoleHistoryInfo(0x%p) UNIMPLEMENTED!\n", lpConsoleHistoryInfo);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    CSR_API_MESSAGE Request;
+    ULONG CsrRequest = MAKE_CSR_API(GET_HISTORY_INFO, CSR_CONSOLE);
+    NTSTATUS Status;
+    if (lpConsoleHistoryInfo->cbSize != sizeof(CONSOLE_HISTORY_INFO))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    Request.Data.SetHistoryInfo.HistoryBufferSize      = lpConsoleHistoryInfo->HistoryBufferSize;
+    Request.Data.SetHistoryInfo.NumberOfHistoryBuffers = lpConsoleHistoryInfo->NumberOfHistoryBuffers;
+    Request.Data.SetHistoryInfo.dwFlags                = lpConsoleHistoryInfo->dwFlags;
+    Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
+    {
+        SetLastErrorByStatus(Status);
+        return FALSE;
+    }
+    return TRUE;
 }