[WIN32K:NTUSER] Make NtUserResolveDesktop() and IntResolveDesktop() work in a more...
[reactos.git] / win32ss / user / winsrv / consrv / frontends / gui / guiterm.c
index e01dbda..258b1e2 100644 (file)
 
 #include <consrv.h>
 
-#include <windowsx.h>
-#define COBJMACROS
-#include <shlobj.h>
-
 #define NDEBUG
 #include <debug.h>
 
 #include "guiterm.h"
 #include "resource.h"
 
-/* GUI Console Window Class name */
-#define GUI_CONSOLE_WINDOW_CLASS L"ConsoleWindowClass"
-
-#ifndef WM_APP
-    #define WM_APP 0x8000
-#endif
-#define PM_CREATE_CONSOLE       (WM_APP + 1)
-#define PM_DESTROY_CONSOLE      (WM_APP + 2)
-#define PM_RESIZE_TERMINAL      (WM_APP + 3)
-#define PM_CONSOLE_BEEP         (WM_APP + 4)
-#define PM_CONSOLE_SET_TITLE    (WM_APP + 5)
-
+// HACK!! Remove it when the hack in GuiWriteStream is fixed
+#define CONGUI_UPDATE_TIME    0
+#define CONGUI_UPDATE_TIMER   1
 
-/* Not defined in any header file */
-extern VOID NTAPI PrivateCsrssManualGuiCheck(LONG Check);
-// See winsrv/usersrv/init.c line 234
+#define PM_CREATE_CONSOLE     (WM_APP + 1)
+#define PM_DESTROY_CONSOLE    (WM_APP + 2)
 
 
 /* GLOBALS ********************************************************************/
 
 typedef struct _GUI_INIT_INFO
 {
-    PCONSOLE_INFO ConsoleInfo;
-    PCONSOLE_START_INFO ConsoleStartInfo;
-    ULONG ProcessId;
+    HANDLE GuiThreadStartupEvent;
+    ULONG_PTR InputThreadId;
+    HWINSTA WinSta;
+    HDESK Desktop;
+    HICON hIcon;
+    HICON hIconSm;
+    BOOLEAN IsWindowVisible;
+    GUI_CONSOLE_INFO TermInfo;
 } GUI_INIT_INFO, *PGUI_INIT_INFO;
 
-/**************************************************************\
-\** Define the Console Leader Process for the console window **/
-#define GWLP_CONSOLEWND_ALLOC  (2 * sizeof(LONG_PTR))
-#define GWLP_CONSOLE_LEADER_PID 0
-#define GWLP_CONSOLE_LEADER_TID 4
-
-#define SetConsoleWndConsoleLeaderCID(GuiData)                              \
-do {                                                                        \
-    PCONSOLE_PROCESS_DATA ProcessData;                                      \
-    CLIENT_ID ConsoleLeaderCID;                                             \
-    ProcessData = CONTAINING_RECORD((GuiData)->Console->ProcessList.Blink,  \
-                                    CONSOLE_PROCESS_DATA,                   \
-                                    ConsoleLink);                           \
-    ConsoleLeaderCID = ProcessData->Process->ClientId;                      \
-    SetWindowLongPtrW((GuiData)->hWindow, GWLP_CONSOLE_LEADER_PID,          \
-                      (LONG_PTR)(ConsoleLeaderCID.UniqueProcess));          \
-    SetWindowLongPtrW((GuiData)->hWindow, GWLP_CONSOLE_LEADER_TID,          \
-                      (LONG_PTR)(ConsoleLeaderCID.UniqueThread ));          \
-} while (0)
-/**************************************************************/
-
-static BOOL    ConsInitialized = FALSE;
-static HICON   ghDefaultIcon = NULL;
-static HICON   ghDefaultIconSm = NULL;
-static HCURSOR ghDefaultCursor = NULL;
-static HWND    NotifyWnd = NULL;
-
-typedef struct _GUICONSOLE_MENUITEM
-{
-    UINT uID;
-    const struct _GUICONSOLE_MENUITEM *SubMenu;
-    WORD wCmdID;
-} GUICONSOLE_MENUITEM, *PGUICONSOLE_MENUITEM;
-
-static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems[] =
-{
-    { IDS_MARK,         NULL, ID_SYSTEM_EDIT_MARK       },
-    { IDS_COPY,         NULL, ID_SYSTEM_EDIT_COPY       },
-    { IDS_PASTE,        NULL, ID_SYSTEM_EDIT_PASTE      },
-    { IDS_SELECTALL,    NULL, ID_SYSTEM_EDIT_SELECTALL  },
-    { IDS_SCROLL,       NULL, ID_SYSTEM_EDIT_SCROLL     },
-    { IDS_FIND,         NULL, ID_SYSTEM_EDIT_FIND       },
-
-    { 0, NULL, 0 } /* End of list */
-};
-
-static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems[] =
-{
-    { IDS_EDIT,         GuiConsoleEditMenuItems, 0 },
-    { IDS_DEFAULTS,     NULL, ID_SYSTEM_DEFAULTS   },
-    { IDS_PROPERTIES,   NULL, ID_SYSTEM_PROPERTIES },
+static BOOL ConsInitialized = FALSE;
 
-    { 0, NULL, 0 } /* End of list */
-};
+extern HICON   ghDefaultIcon;
+extern HICON   ghDefaultIconSm;
+extern HCURSOR ghDefaultCursor;
 
-/*
- * Default 16-color palette for foreground and background
- * (corresponding flags in comments).
- */
-const COLORREF s_Colors[16] =
-{
-    RGB(0, 0, 0),       // (Black)
-    RGB(0, 0, 128),     // BLUE
-    RGB(0, 128, 0),     // GREEN
-    RGB(0, 128, 128),   // BLUE  | GREEN
-    RGB(128, 0, 0),     // RED
-    RGB(128, 0, 128),   // BLUE  | RED
-    RGB(128, 128, 0),   // GREEN | RED
-    RGB(192, 192, 192), // BLUE  | GREEN | RED
-
-    RGB(128, 128, 128), // (Grey)  INTENSITY
-    RGB(0, 0, 255),     // BLUE  | INTENSITY
-    RGB(0, 255, 0),     // GREEN | INTENSITY
-    RGB(0, 255, 255),   // BLUE  | GREEN | INTENSITY
-    RGB(255, 0, 0),     // RED   | INTENSITY
-    RGB(255, 0, 255),   // BLUE  | RED   | INTENSITY
-    RGB(255, 255, 0),   // GREEN | RED   | INTENSITY
-    RGB(255, 255, 255)  // BLUE  | GREEN | RED | INTENSITY
-};
+VOID
+SetConWndConsoleLeaderCID(IN PGUI_CONSOLE_DATA GuiData);
+BOOLEAN
+RegisterConWndClass(IN HINSTANCE hInstance);
+BOOLEAN
+UnRegisterConWndClass(HINSTANCE hInstance);
 
 /* FUNCTIONS ******************************************************************/
 
-static VOID
-GetScreenBufferSizeUnits(IN PCONSOLE_SCREEN_BUFFER Buffer,
-                         IN PGUI_CONSOLE_DATA GuiData,
-                         OUT PUINT WidthUnit,
-                         OUT PUINT HeightUnit)
-{
-    if (Buffer == NULL || GuiData == NULL ||
-        WidthUnit == NULL || HeightUnit == NULL)
-    {
-        return;
-    }
-
-    if (GetType(Buffer) == TEXTMODE_BUFFER)
-    {
-        *WidthUnit  = GuiData->CharWidth ;
-        *HeightUnit = GuiData->CharHeight;
-    }
-    else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
-    {
-        *WidthUnit  = 1;
-        *HeightUnit = 1;
-    }
-}
-
-
-
-static VOID
-GuiConsoleAppendMenuItems(HMENU hMenu,
-                          const GUICONSOLE_MENUITEM *Items)
-{
-    UINT i = 0;
-    WCHAR szMenuString[255];
-    HMENU hSubMenu;
-
-    do
-    {
-        if (Items[i].uID != (UINT)-1)
-        {
-            if (LoadStringW(ConSrvDllInstance,
-                            Items[i].uID,
-                            szMenuString,
-                            sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
-            {
-                if (Items[i].SubMenu != NULL)
-                {
-                    hSubMenu = CreatePopupMenu();
-                    if (hSubMenu != NULL)
-                    {
-                        GuiConsoleAppendMenuItems(hSubMenu,
-                                                  Items[i].SubMenu);
-
-                        if (!AppendMenuW(hMenu,
-                                         MF_STRING | MF_POPUP,
-                                         (UINT_PTR)hSubMenu,
-                                         szMenuString))
-                        {
-                            DestroyMenu(hSubMenu);
-                        }
-                    }
-                }
-                else
-                {
-                    AppendMenuW(hMenu,
-                                MF_STRING,
-                                Items[i].wCmdID,
-                                szMenuString);
-                }
-            }
-        }
-        else
-        {
-            AppendMenuW(hMenu,
-                        MF_SEPARATOR,
-                        0,
-                        NULL);
-        }
-        i++;
-    } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
-}
-
-static VOID
-GuiConsoleCreateSysMenu(HWND hWnd)
-{
-    HMENU hMenu = GetSystemMenu(hWnd, FALSE);
-    if (hMenu != NULL)
-    {
-        GuiConsoleAppendMenuItems(hMenu, GuiConsoleMainMenuItems);
-        DrawMenuBar(hWnd);
-    }
-}
-
-static VOID
-GuiSendMenuEvent(PCONSOLE Console, UINT CmdId)
-{
-    INPUT_RECORD er;
-
-    er.EventType = MENU_EVENT;
-    er.Event.MenuEvent.dwCommandId = CmdId;
-
-    DPRINT("Menu item ID: %d\n", CmdId);
-    ConioProcessInputEvent(Console, &er);
-}
-
-static VOID
-GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData);
-static VOID
-GuiConsolePaste(PGUI_CONSOLE_DATA GuiData);
-static VOID
-GuiConsoleUpdateSelection(PCONSOLE Console, PCOORD coord);
-static VOID NTAPI
-GuiDrawRegion(IN OUT PFRONTEND This, SMALL_RECT* Region);
-static VOID
-GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData, DWORD WidthUnit, DWORD HeightUnit);
-
-
-static LRESULT
-GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
-{
-    LRESULT Ret = TRUE;
-    PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
-
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-    {
-        Ret = FALSE;
-        goto Quit;
-    }
-    ActiveBuffer = GuiData->ActiveBuffer;
-
-    /*
-     * In case the selected menu item belongs to the user-reserved menu id range,
-     * send to him a menu event and return directly. The user must handle those
-     * reserved menu commands...
-     */
-    if (GuiData->CmdIdLow <= (UINT)wParam && (UINT)wParam <= GuiData->CmdIdHigh)
-    {
-        GuiSendMenuEvent(Console, (UINT)wParam);
-        goto Unlock_Quit;
-    }
-
-    /* ... otherwise, perform actions. */
-    switch (wParam)
-    {
-        case ID_SYSTEM_EDIT_MARK:
-        {
-            LPWSTR WindowTitle = NULL;
-            SIZE_T Length = 0;
-
-            Console->dwSelectionCursor.X = ActiveBuffer->ViewOrigin.X;
-            Console->dwSelectionCursor.Y = ActiveBuffer->ViewOrigin.Y;
-            Console->Selection.dwSelectionAnchor = Console->dwSelectionCursor;
-            Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS;
-            GuiConsoleUpdateSelection(Console, &Console->Selection.dwSelectionAnchor);
-
-            Length = Console->Title.Length + sizeof(L"Mark - ")/sizeof(WCHAR) + 1;
-            WindowTitle = ConsoleAllocHeap(0, Length * sizeof(WCHAR));
-            wcscpy(WindowTitle, L"Mark - ");
-            wcscat(WindowTitle, Console->Title.Buffer);
-            SetWindowText(GuiData->hWindow, WindowTitle);
-            ConsoleFreeHeap(WindowTitle);
-
-            break;
-        }
-
-        case ID_SYSTEM_EDIT_COPY:
-            GuiConsoleCopy(GuiData);
-            break;
-
-        case ID_SYSTEM_EDIT_PASTE:
-            GuiConsolePaste(GuiData);
-            break;
-
-        case ID_SYSTEM_EDIT_SELECTALL:
-        {
-            LPWSTR WindowTitle = NULL;
-            SIZE_T Length = 0;
-
-            /*
-             * The selection area extends to the whole screen buffer's width.
-             */
-            Console->Selection.dwSelectionAnchor.X = 0;
-            Console->Selection.dwSelectionAnchor.Y = 0;
-            Console->dwSelectionCursor.X = ActiveBuffer->ScreenBufferSize.X - 1;
-
-            /*
-             * Determine whether the selection must extend to just some part
-             * (for text-mode screen buffers) or to all of the screen buffer's
-             * height (for graphics ones).
-             */
-            if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
-            {
-                /*
-                 * We select all the characters from the first line
-                 * to the line where the cursor is positioned.
-                 */
-                Console->dwSelectionCursor.Y = ActiveBuffer->CursorPosition.Y;
-            }
-            else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
-            {
-                /*
-                 * We select all the screen buffer area.
-                 */
-                Console->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
-            }
-
-            Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION;
-            GuiConsoleUpdateSelection(Console, &Console->dwSelectionCursor);
-
-            Length = Console->Title.Length + sizeof(L"Selection - ")/sizeof(WCHAR) + 1;
-            WindowTitle = ConsoleAllocHeap(0, Length * sizeof(WCHAR));
-            wcscpy(WindowTitle, L"Selection - ");
-            wcscat(WindowTitle, Console->Title.Buffer);
-            SetWindowText(GuiData->hWindow, WindowTitle);
-            ConsoleFreeHeap(WindowTitle);
-
-            break;
-        }
-
-        case ID_SYSTEM_EDIT_SCROLL:
-            DPRINT1("Scrolling is not handled yet\n");
-            break;
-
-        case ID_SYSTEM_EDIT_FIND:
-            DPRINT1("Finding is not handled yet\n");
-            break;
-
-        case ID_SYSTEM_DEFAULTS:
-            GuiConsoleShowConsoleProperties(GuiData, TRUE);
-            break;
-
-        case ID_SYSTEM_PROPERTIES:
-            GuiConsoleShowConsoleProperties(GuiData, FALSE);
-            break;
-
-        default:
-            Ret = FALSE;
-            break;
-    }
-
-Unlock_Quit:
-    LeaveCriticalSection(&Console->Lock);
-Quit:
-    if (!Ret)
-        Ret = DefWindowProcW(GuiData->hWindow, WM_SYSCOMMAND, wParam, lParam);
-
-    return Ret;
-}
-
-static PGUI_CONSOLE_DATA
-GuiGetGuiData(HWND hWnd)
-{
-    /* This function ensures that the console pointer is not NULL */
-    PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
-    return ( ((GuiData == NULL) || (GuiData->hWindow == hWnd && GuiData->Console != NULL)) ? GuiData : NULL );
-}
-
 VOID
 GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData)
 {
@@ -398,1929 +66,402 @@ GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData)
                      NULL,
                      GuiData->GuiInfo.WindowOrigin.x,
                      GuiData->GuiInfo.WindowOrigin.y,
-                     0,
-                     0,
+                     0, 0,
                      SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
     }
 }
 
 static VOID
-GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData, DWORD WidthUnit, DWORD HeightUnit)
+DrawRegion(PGUI_CONSOLE_DATA GuiData,
+           SMALL_RECT* Region)
 {
-    PCONSOLE_SCREEN_BUFFER Buff = GuiData->ActiveBuffer;
-    SCROLLINFO sInfo;
-
-    DWORD Width, Height;
-
-    Width  = Buff->ViewSize.X * WidthUnit  +
-             2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
-    Height = Buff->ViewSize.Y * HeightUnit +
-             2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
-
-    /* Set scrollbar sizes */
-    sInfo.cbSize = sizeof(SCROLLINFO);
-    sInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
-    sInfo.nMin = 0;
-    if (Buff->ScreenBufferSize.Y > Buff->ViewSize.Y)
-    {
-        sInfo.nMax  = Buff->ScreenBufferSize.Y - 1;
-        sInfo.nPage = Buff->ViewSize.Y;
-        sInfo.nPos  = Buff->ViewOrigin.Y;
-        SetScrollInfo(GuiData->hWindow, SB_VERT, &sInfo, TRUE);
-        Width += GetSystemMetrics(SM_CXVSCROLL);
-        ShowScrollBar(GuiData->hWindow, SB_VERT, TRUE);
-    }
-    else
-    {
-        ShowScrollBar(GuiData->hWindow, SB_VERT, FALSE);
-    }
-
-    if (Buff->ScreenBufferSize.X > Buff->ViewSize.X)
-    {
-        sInfo.nMax  = Buff->ScreenBufferSize.X - 1;
-        sInfo.nPage = Buff->ViewSize.X;
-        sInfo.nPos  = Buff->ViewOrigin.X;
-        SetScrollInfo(GuiData->hWindow, SB_HORZ, &sInfo, TRUE);
-        Height += GetSystemMetrics(SM_CYHSCROLL);
-        ShowScrollBar(GuiData->hWindow, SB_HORZ, TRUE);
-    }
-    else
-    {
-        ShowScrollBar(GuiData->hWindow, SB_HORZ, FALSE);
-    }
+    RECT RegionRect;
 
-    /* Resize the window  */
-    SetWindowPos(GuiData->hWindow, NULL, 0, 0, Width, Height,
-                 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS);
-    // NOTE: The SWP_NOCOPYBITS flag can be replaced by a subsequent call
-    // to: InvalidateRect(GuiData->hWindow, NULL, TRUE);
+    SmallRectToRect(GuiData, &RegionRect, Region);
+    /* Do not erase the background: it speeds up redrawing and reduce flickering */
+    InvalidateRect(GuiData->hWindow, &RegionRect, FALSE);
+    /**UpdateWindow(GuiData->hWindow);**/
 }
 
-static BOOL
-GuiConsoleHandleNcCreate(HWND hWnd, LPCREATESTRUCTW Create)
+VOID
+InvalidateCell(PGUI_CONSOLE_DATA GuiData,
+               SHORT x, SHORT y)
 {
-    PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)Create->lpCreateParams;
-    PCONSOLE Console;
-    HDC hDC;
-    HFONT OldFont;
-    TEXTMETRICW Metrics;
-    SIZE CharSize;
-
-    DPRINT("GuiConsoleHandleNcCreate\n");
-
-    if (NULL == GuiData)
-    {
-        DPRINT1("GuiConsoleNcCreate: No GUI data\n");
-        return FALSE;
-    }
-
-    Console = GuiData->Console;
-
-    GuiData->hWindow = hWnd;
-
-    GuiData->Font = CreateFontW(LOWORD(GuiData->GuiInfo.FontSize),
-                                0, // HIWORD(GuiData->GuiInfo.FontSize),
-                                0,
-                                TA_BASELINE,
-                                GuiData->GuiInfo.FontWeight,
-                                FALSE,
-                                FALSE,
-                                FALSE,
-                                OEM_CHARSET,
-                                OUT_DEFAULT_PRECIS,
-                                CLIP_DEFAULT_PRECIS,
-                                NONANTIALIASED_QUALITY,
-                                FIXED_PITCH | GuiData->GuiInfo.FontFamily /* FF_DONTCARE */,
-                                GuiData->GuiInfo.FaceName);
-
-    if (NULL == GuiData->Font)
-    {
-        DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
-        GuiData->hWindow = NULL;
-        SetEvent(GuiData->hGuiInitEvent);
-        return FALSE;
-    }
-    hDC = GetDC(GuiData->hWindow);
-    if (NULL == hDC)
-    {
-        DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
-        DeleteObject(GuiData->Font);
-        GuiData->hWindow = NULL;
-        SetEvent(GuiData->hGuiInitEvent);
-        return FALSE;
-    }
-    OldFont = SelectObject(hDC, GuiData->Font);
-    if (NULL == OldFont)
-    {
-        DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
-        ReleaseDC(GuiData->hWindow, hDC);
-        DeleteObject(GuiData->Font);
-        GuiData->hWindow = NULL;
-        SetEvent(GuiData->hGuiInitEvent);
-        return FALSE;
-    }
-    if (!GetTextMetricsW(hDC, &Metrics))
-    {
-        DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
-        SelectObject(hDC, OldFont);
-        ReleaseDC(GuiData->hWindow, hDC);
-        DeleteObject(GuiData->Font);
-        GuiData->hWindow = NULL;
-        SetEvent(GuiData->hGuiInitEvent);
-        return FALSE;
-    }
-    GuiData->CharWidth  = Metrics.tmMaxCharWidth;
-    GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
-
-    /* Measure real char width more precisely if possible. */
-    if (GetTextExtentPoint32W(hDC, L"R", 1, &CharSize))
-        GuiData->CharWidth = CharSize.cx;
-
-    SelectObject(hDC, OldFont);
-
-    ReleaseDC(GuiData->hWindow, hDC);
-
-    /* Initialize the terminal framebuffer */
-    GuiData->hMemDC  = CreateCompatibleDC(NULL);
-    GuiData->hBitmap = NULL;
-    GuiData->hSysPalette = NULL; /* Original system palette */
-
-    // FIXME: Keep these instructions here ? ///////////////////////////////////
-    Console->ActiveBuffer->CursorBlinkOn = TRUE;
-    Console->ActiveBuffer->ForceCursorOff = FALSE;
-    ////////////////////////////////////////////////////////////////////////////
-
-    SetWindowLongPtrW(GuiData->hWindow, GWLP_USERDATA, (DWORD_PTR)GuiData);
-
-    SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
-    GuiConsoleCreateSysMenu(GuiData->hWindow);
-
-    DPRINT("GuiConsoleHandleNcCreate - setting start event\n");
-    SetEvent(GuiData->hGuiInitEvent);
-
-    return (BOOL)DefWindowProcW(GuiData->hWindow, WM_NCCREATE, 0, (LPARAM)Create);
+    SMALL_RECT CellRect = { x, y, x, y };
+    DrawRegion(GuiData, &CellRect);
 }
 
-static VOID
-SmallRectToRect(PGUI_CONSOLE_DATA GuiData, PRECT Rect, PSMALL_RECT SmallRect)
-{
-    PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
-    UINT WidthUnit, HeightUnit;
 
-    GetScreenBufferSizeUnits(Buffer, GuiData, &WidthUnit, &HeightUnit);
+/******************************************************************************
+ *                        GUI Terminal Initialization                         *
+ ******************************************************************************/
 
-    Rect->left   = (SmallRect->Left       - Buffer->ViewOrigin.X) * WidthUnit ;
-    Rect->top    = (SmallRect->Top        - Buffer->ViewOrigin.Y) * HeightUnit;
-    Rect->right  = (SmallRect->Right  + 1 - Buffer->ViewOrigin.X) * WidthUnit ;
-    Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ViewOrigin.Y) * HeightUnit;
-}
+VOID
+CreateSysMenu(HWND hWnd);
 
-static VOID
-GuiConsoleUpdateSelection(PCONSOLE Console, PCOORD coord)
+static ULONG NTAPI
+GuiConsoleInputThread(PVOID Param)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
-    RECT oldRect, newRect;
-
-    SmallRectToRect(GuiData, &oldRect, &Console->Selection.srSelection);
-
-    if (coord != NULL)
-    {
-        SMALL_RECT rc;
-        /* exchange left/top with right/bottom if required */
-        rc.Left   = min(Console->Selection.dwSelectionAnchor.X, coord->X);
-        rc.Top    = min(Console->Selection.dwSelectionAnchor.Y, coord->Y);
-        rc.Right  = max(Console->Selection.dwSelectionAnchor.X, coord->X);
-        rc.Bottom = max(Console->Selection.dwSelectionAnchor.Y, coord->Y);
-
-        SmallRectToRect(GuiData, &newRect, &rc);
-
-        if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
-        {
-            if (memcmp(&rc, &Console->Selection.srSelection, sizeof(SMALL_RECT)) != 0)
-            {
-                HRGN rgn1, rgn2;
+    NTSTATUS Status;
+    PCSR_THREAD pcsrt = NULL;
+    PGUI_INIT_INFO GuiInitInfo = (PGUI_INIT_INFO)Param;
+    DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo;
+    ULONG_PTR InputThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
+    HANDLE hThread = NULL;
+
+    LONG WindowCount = 0;
+    MSG msg;
 
-                /* calculate the region that needs to be updated */
-                if ((rgn1 = CreateRectRgnIndirect(&oldRect)))
-                {
-                    if ((rgn2 = CreateRectRgnIndirect(&newRect)))
-                    {
-                        if (CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR)
-                        {
-                            InvalidateRgn(GuiData->hWindow, rgn1, FALSE);
-                        }
-                        DeleteObject(rgn2);
-                    }
-                    DeleteObject(rgn1);
-                }
-            }
-        }
-        else
-        {
-            InvalidateRect(GuiData->hWindow, &newRect, FALSE);
-        }
-        Console->Selection.dwFlags |= CONSOLE_SELECTION_NOT_EMPTY;
-        Console->Selection.srSelection = rc;
-        Console->dwSelectionCursor = *coord;
-        ConioPause(Console, PAUSED_FROM_SELECTION);
-    }
-    else
-    {
-        /* clear the selection */
-        if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
-        {
-            InvalidateRect(GuiData->hWindow, &oldRect, FALSE);
-        }
-        Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
-        ConioUnpause(Console, PAUSED_FROM_SELECTION);
-    }
-}
+    /*
+     * This thread dispatches all the console notifications to the
+     * notification window. It is common for all the console windows
+     * in a given desktop in a window station.
+     */
 
+    /* Assign this console input thread to this desktop */
+    DesktopConsoleThreadInfo.DesktopHandle = GuiInitInfo->Desktop; // Duplicated desktop handle
+    DesktopConsoleThreadInfo.ThreadId = InputThreadId;
+    Status = NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+                                  &DesktopConsoleThreadInfo,
+                                  sizeof(DesktopConsoleThreadInfo));
+    if (!NT_SUCCESS(Status)) goto Quit;
 
-VOID
-GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
-                       PGUI_CONSOLE_DATA GuiData,
-                       PRECT rcView,
-                       PRECT rcFramebuffer);
-VOID
-GuiPaintGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
-                       PGUI_CONSOLE_DATA GuiData,
-                       PRECT rcView,
-                       PRECT rcFramebuffer);
+    /* Connect this CSR thread to the USER subsystem */
+    pcsrt = CsrConnectToUser();
+    if (pcsrt == NULL) goto Quit;
+    hThread = pcsrt->ThreadHandle;
 
-static VOID
-GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData)
-{
-    BOOL Success = TRUE;
-    PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
-    PAINTSTRUCT ps;
-    RECT rcPaint;
+    /* Assign the desktop to this thread */
+    if (!SetThreadDesktop(DesktopConsoleThreadInfo.DesktopHandle)) goto Quit;
 
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-    {
-        Success = FALSE;
-        goto Quit;
-    }
-    ActiveBuffer = GuiData->ActiveBuffer;
+    /* The thread has been initialized, set the event */
+    NtSetEvent(GuiInitInfo->GuiThreadStartupEvent, NULL);
+    Status = STATUS_SUCCESS;
 
-    BeginPaint(GuiData->hWindow, &ps);
-    if (ps.hdc != NULL &&
-        ps.rcPaint.left < ps.rcPaint.right &&
-        ps.rcPaint.top < ps.rcPaint.bottom)
+    while (GetMessageW(&msg, NULL, 0, 0))
     {
-        EnterCriticalSection(&GuiData->Lock);
-
-        /* Compose the current screen-buffer on-memory */
-        if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
-        {
-            GuiPaintTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)ActiveBuffer,
-                                   GuiData, &ps.rcPaint, &rcPaint);
-        }
-        else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
-        {
-            GuiPaintGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)ActiveBuffer,
-                                   GuiData, &ps.rcPaint, &rcPaint);
-        }
-
-        /* Send it to screen */
-        BitBlt(ps.hdc,
-               ps.rcPaint.left,
-               ps.rcPaint.top,
-               rcPaint.right  - rcPaint.left,
-               rcPaint.bottom - rcPaint.top,
-               GuiData->hMemDC,
-               rcPaint.left,
-               rcPaint.top,
-               SRCCOPY);
-
-        if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
+        switch (msg.message)
         {
-            SmallRectToRect(GuiData, &rcPaint, &Console->Selection.srSelection);
-
-            /* Invert the selection */
-            if (IntersectRect(&rcPaint, &ps.rcPaint, &rcPaint))
+            case PM_CREATE_CONSOLE:
             {
-                InvertRect(ps.hdc, &rcPaint);
-            }
-        }
-
-        LeaveCriticalSection(&GuiData->Lock);
-    }
-    EndPaint(GuiData->hWindow, &ps);
-
-Quit:
-    if (Success)
-        LeaveCriticalSection(&Console->Lock);
-    else
-        DefWindowProcW(GuiData->hWindow, WM_PAINT, 0, 0);
-
-    return;
-}
-
-static BOOL
-IsSystemKey(WORD VirtualKeyCode)
-{
-    switch (VirtualKeyCode)
-    {
-        /* From MSDN, "Virtual-Key Codes" */
-        case VK_RETURN:
-        case VK_SHIFT:
-        case VK_CONTROL:
-        case VK_MENU:
-        case VK_PAUSE:
-        case VK_CAPITAL:
-        case VK_ESCAPE:
-        case VK_LWIN:
-        case VK_RWIN:
-        case VK_NUMLOCK:
-        case VK_SCROLL:
-            return TRUE;
-        default:
-            return FALSE;
-    }
-}
-
-static VOID
-GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-    PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
-
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
-
-    ActiveBuffer = GuiData->ActiveBuffer;
-
-    if (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS)
-    {
-        WORD VirtualKeyCode = LOWORD(wParam);
+                PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)msg.lParam;
+                PCONSRV_CONSOLE Console = GuiData->Console;
+                HWND NewWindow;
+                RECT rcWnd;
+
+                DPRINT("PM_CREATE_CONSOLE -- creating window\n");
+
+                NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE,
+                                            GUI_CONWND_CLASS,
+                                            Console->Title.Buffer,
+                                            WS_OVERLAPPEDWINDOW,
+                                            CW_USEDEFAULT,
+                                            CW_USEDEFAULT,
+                                            CW_USEDEFAULT,
+                                            CW_USEDEFAULT,
+                                            GuiData->IsWindowVisible ? HWND_DESKTOP : HWND_MESSAGE,
+                                            NULL,
+                                            ConSrvDllInstance,
+                                            (PVOID)GuiData);
+                if (NewWindow == NULL)
+                {
+                    DPRINT1("Failed to create a new console window\n");
+                    continue;
+                }
 
-        if (msg != WM_KEYDOWN) goto Quit;
+                ASSERT(NewWindow == GuiData->hWindow);
 
-        if (VirtualKeyCode == VK_RETURN)
-        {
-            /* Copy (and clear) selection if ENTER is pressed */
-            GuiConsoleCopy(GuiData);
-            goto Quit;
-        }
-        else if ( VirtualKeyCode == VK_ESCAPE ||
-                 (VirtualKeyCode == 'C' && GetKeyState(VK_CONTROL) & 0x8000) )
-        {
-            /* Cancel selection if ESC or Ctrl-C are pressed */
-            GuiConsoleUpdateSelection(Console, NULL);
-            SetWindowText(GuiData->hWindow, Console->Title.Buffer);
+                InterlockedIncrement(&WindowCount);
 
-            goto Quit;
-        }
+                //
+                // FIXME: TODO: Move everything there into conwnd.c!OnNcCreate()
+                //
 
-        if ((Console->Selection.dwFlags & CONSOLE_MOUSE_SELECTION) == 0)
-        {
-            /* Keyboard selection mode */
-            BOOL Interpreted = FALSE;
-            BOOL MajPressed  = (GetKeyState(VK_SHIFT) & 0x8000);
+                /* Retrieve our real position */
+                // See conwnd.c!OnMove()
+                GetWindowRect(GuiData->hWindow, &rcWnd);
+                GuiData->GuiInfo.WindowOrigin.x = rcWnd.left;
+                GuiData->GuiInfo.WindowOrigin.y = rcWnd.top;
 
-            switch (VirtualKeyCode)
-            {
-                case VK_LEFT:
+                if (GuiData->IsWindowVisible)
                 {
-                    Interpreted = TRUE;
-                    if (Console->dwSelectionCursor.X > 0)
-                        Console->dwSelectionCursor.X--;
-
-                    break;
+                    /* Move and resize the window to the user's values */
+                    /* CAN WE DEADLOCK ?? */
+                    GuiConsoleMoveWindow(GuiData); // FIXME: This MUST be done via the CreateWindowExW call.
+                    SendMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
                 }
 
-                case VK_RIGHT:
-                {
-                    Interpreted = TRUE;
-                    if (Console->dwSelectionCursor.X < ActiveBuffer->ScreenBufferSize.X - 1)
-                        Console->dwSelectionCursor.X++;
-
-                    break;
-                }
-
-                case VK_UP:
-                {
-                    Interpreted = TRUE;
-                    if (Console->dwSelectionCursor.Y > 0)
-                        Console->dwSelectionCursor.Y--;
-
-                    break;
-                }
-
-                case VK_DOWN:
-                {
-                    Interpreted = TRUE;
-                    if (Console->dwSelectionCursor.Y < ActiveBuffer->ScreenBufferSize.Y - 1)
-                        Console->dwSelectionCursor.Y++;
-
-                    break;
-                }
-
-                case VK_HOME:
-                {
-                    Interpreted = TRUE;
-                    Console->dwSelectionCursor.X = 0;
-                    Console->dwSelectionCursor.Y = 0;
-                    break;
-                }
-
-                case VK_END:
-                {
-                    Interpreted = TRUE;
-                    Console->dwSelectionCursor.Y = ActiveBuffer->ScreenBufferSize.Y - 1;
-                    break;
-                }
-
-                case VK_PRIOR:
-                {
-                    Interpreted = TRUE;
-                    Console->dwSelectionCursor.Y -= ActiveBuffer->ViewSize.Y;
-                    if (Console->dwSelectionCursor.Y < 0)
-                        Console->dwSelectionCursor.Y = 0;
-
-                    break;
-                }
-
-                case VK_NEXT:
-                {
-                    Interpreted = TRUE;
-                    Console->dwSelectionCursor.Y += ActiveBuffer->ViewSize.Y;
-                    if (Console->dwSelectionCursor.Y >= ActiveBuffer->ScreenBufferSize.Y)
-                        Console->dwSelectionCursor.Y  = ActiveBuffer->ScreenBufferSize.Y - 1;
-
-                    break;
-                }
-
-                default:
-                    break;
-            }
-
-            if (Interpreted)
-            {
-                if (!MajPressed)
-                    Console->Selection.dwSelectionAnchor = Console->dwSelectionCursor;
-
-                GuiConsoleUpdateSelection(Console, &Console->dwSelectionCursor);
-            }
-            else if (!IsSystemKey(VirtualKeyCode))
-            {
-                /* Emit an error beep sound */
-                SendNotifyMessage(GuiData->hWindow, PM_CONSOLE_BEEP, 0, 0);
-            }
-
-            goto Quit;
-        }
-        else
-        {
-            /* Mouse selection mode */
-
-            if (!IsSystemKey(VirtualKeyCode))
-            {
-                /* Clear the selection and send the key into the input buffer */
-                GuiConsoleUpdateSelection(Console, NULL);
-                SetWindowText(GuiData->hWindow, Console->Title.Buffer);
-            }
-            else
-            {
-                goto Quit;
-            }
-        }
-    }
-
-    if ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) == 0)
-    {
-        MSG Message;
-
-        Message.hwnd = GuiData->hWindow;
-        Message.message = msg;
-        Message.wParam = wParam;
-        Message.lParam = lParam;
-
-        ConioProcessKey(Console, &Message);
-    }
-
-Quit:
-    LeaveCriticalSection(&Console->Lock);
-}
-
-static VOID
-GuiInvalidateCell(IN OUT PFRONTEND This, SHORT x, SHORT y)
-{
-    SMALL_RECT CellRect = { x, y, x, y };
-    GuiDrawRegion(This, &CellRect);
-}
-
-static VOID
-GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData)
-{
-    PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER Buff;
-
-    SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CURSOR_BLINK_TIME, NULL);
-
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
-
-    Buff = GuiData->ActiveBuffer;
-
-    if (GetType(Buff) == TEXTMODE_BUFFER)
-    {
-        GuiInvalidateCell(&Console->TermIFace, Buff->CursorPosition.X, Buff->CursorPosition.Y);
-        Buff->CursorBlinkOn = !Buff->CursorBlinkOn;
-
-        if ((GuiData->OldCursor.x != Buff->CursorPosition.X) ||
-            (GuiData->OldCursor.y != Buff->CursorPosition.Y))
-        {
-            SCROLLINFO xScroll;
-            int OldScrollX = -1, OldScrollY = -1;
-            int NewScrollX = -1, NewScrollY = -1;
-
-            xScroll.cbSize = sizeof(SCROLLINFO);
-            xScroll.fMask = SIF_POS;
-            // Capture the original position of the scroll bars and save them.
-            if (GetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll)) OldScrollX = xScroll.nPos;
-            if (GetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll)) OldScrollY = xScroll.nPos;
-
-            // If we successfully got the info for the horizontal scrollbar
-            if (OldScrollX >= 0)
-            {
-                if ((Buff->CursorPosition.X < Buff->ViewOrigin.X) ||
-                    (Buff->CursorPosition.X >= (Buff->ViewOrigin.X + Buff->ViewSize.X)))
-                {
-                    // Handle the horizontal scroll bar
-                    if (Buff->CursorPosition.X >= Buff->ViewSize.X)
-                        NewScrollX = Buff->CursorPosition.X - Buff->ViewSize.X + 1;
-                    else
-                        NewScrollX = 0;
-                }
-                else
-                {
-                    NewScrollX = OldScrollX;
-                }
-            }
-            // If we successfully got the info for the vertical scrollbar
-            if (OldScrollY >= 0)
-            {
-                if ((Buff->CursorPosition.Y < Buff->ViewOrigin.Y) ||
-                    (Buff->CursorPosition.Y >= (Buff->ViewOrigin.Y + Buff->ViewSize.Y)))
-                {
-                    // Handle the vertical scroll bar
-                    if (Buff->CursorPosition.Y >= Buff->ViewSize.Y)
-                        NewScrollY = Buff->CursorPosition.Y - Buff->ViewSize.Y + 1;
-                    else
-                        NewScrollY = 0;
-                }
-                else
-                {
-                    NewScrollY = OldScrollY;
-                }
-            }
-
-            // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
-            // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
-            //       was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
-            //       and their associated scrollbar is left alone.
-            if ((OldScrollX != NewScrollX) || (OldScrollY != NewScrollY))
-            {
-                Buff->ViewOrigin.X = NewScrollX;
-                Buff->ViewOrigin.Y = NewScrollY;
-                ScrollWindowEx(GuiData->hWindow,
-                               (OldScrollX - NewScrollX) * GuiData->CharWidth,
-                               (OldScrollY - NewScrollY) * GuiData->CharHeight,
-                               NULL,
-                               NULL,
-                               NULL,
-                               NULL,
-                               SW_INVALIDATE);
-                if (NewScrollX >= 0)
-                {
-                    xScroll.nPos = NewScrollX;
-                    SetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll, TRUE);
-                }
-                if (NewScrollY >= 0)
-                {
-                    xScroll.nPos = NewScrollY;
-                    SetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll, TRUE);
-                }
-                UpdateWindow(GuiData->hWindow);
-                // InvalidateRect(GuiData->hWindow, NULL, FALSE);
-                GuiData->OldCursor.x = Buff->CursorPosition.X;
-                GuiData->OldCursor.y = Buff->CursorPosition.Y;
-            }
-        }
-    }
-    else /* if (GetType(Buff) == GRAPHICS_BUFFER) */
-    {
-    }
-
-    LeaveCriticalSection(&Console->Lock);
-}
-
-static BOOL
-GuiConsoleHandleClose(PGUI_CONSOLE_DATA GuiData)
-{
-    PCONSOLE Console = GuiData->Console;
-
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-        return TRUE;
-
-    // TODO: Prompt for termination ? (Warn the user about possible apps running in this console)
-
-    /*
-     * FIXME: Windows will wait up to 5 seconds for the thread to exit.
-     * We shouldn't wait here, though, since the console lock is entered.
-     * A copy of the thread list probably needs to be made.
-     */
-    ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT);
-
-    LeaveCriticalSection(&Console->Lock);
-    return FALSE;
-}
-
-static LRESULT
-GuiConsoleHandleNcDestroy(HWND hWnd)
-{
-    PGUI_CONSOLE_DATA GuiData = GuiGetGuiData(hWnd);
-
-    KillTimer(hWnd, CONGUI_UPDATE_TIMER);
-    GetSystemMenu(hWnd, TRUE);
-
-    if (GuiData)
-    {
-        /* Free the terminal framebuffer */
-        if (GuiData->hMemDC ) DeleteDC(GuiData->hMemDC);
-        if (GuiData->hBitmap) DeleteObject(GuiData->hBitmap);
-        // if (GuiData->hSysPalette) DeleteObject(GuiData->hSysPalette);
-        if (GuiData->Font) DeleteObject(GuiData->Font);
-    }
-
-    /* Free the GuiData registration */
-    SetWindowLongPtrW(hWnd, GWLP_USERDATA, (DWORD_PTR)NULL);
-
-    return DefWindowProcW(hWnd, WM_NCDESTROY, 0, 0);
-}
-
-static COORD
-PointToCoord(PGUI_CONSOLE_DATA GuiData, LPARAM lParam)
-{
-    PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
-    COORD Coord;
-    UINT  WidthUnit, HeightUnit;
-
-    GetScreenBufferSizeUnits(Buffer, GuiData, &WidthUnit, &HeightUnit);
-
-    Coord.X = Buffer->ViewOrigin.X + ((SHORT)LOWORD(lParam) / (int)WidthUnit );
-    Coord.Y = Buffer->ViewOrigin.Y + ((SHORT)HIWORD(lParam) / (int)HeightUnit);
-
-    /* Clip coordinate to ensure it's inside buffer */
-    if (Coord.X < 0)
-        Coord.X = 0;
-    else if (Coord.X >= Buffer->ScreenBufferSize.X)
-        Coord.X = Buffer->ScreenBufferSize.X - 1;
-
-    if (Coord.Y < 0)
-        Coord.Y = 0;
-    else if (Coord.Y >= Buffer->ScreenBufferSize.Y)
-        Coord.Y = Buffer->ScreenBufferSize.Y - 1;
-
-    return Coord;
-}
-
-static LRESULT
-GuiConsoleHandleMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-    BOOL Err = FALSE;
-    PCONSOLE Console = GuiData->Console;
-
-    if (GuiData->IgnoreNextMouseSignal)
-    {
-        if (msg != WM_LBUTTONDOWN &&
-            msg != WM_MBUTTONDOWN &&
-            msg != WM_RBUTTONDOWN)
-        {
-            /*
-             * If this mouse signal is not a button-down action,
-             * then it is the last signal being ignored.
-             */
-            GuiData->IgnoreNextMouseSignal = FALSE;
-        }
-        else
-        {
-            /*
-             * This mouse signal is a button-down action.
-             * Ignore it and perform default action.
-             */
-            Err = TRUE;
-        }
-        goto Quit;
-    }
-
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-    {
-        Err = TRUE;
-        goto Quit;
-    }
-
-    if ( (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) ||
-         (Console->QuickEdit) )
-    {
-        switch (msg)
-        {
-            case WM_LBUTTONDOWN:
-            {
-                LPWSTR WindowTitle = NULL;
-                SIZE_T Length = 0;
-
-                Console->Selection.dwSelectionAnchor = PointToCoord(GuiData, lParam);
-                SetCapture(GuiData->hWindow);
-                Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
-                GuiConsoleUpdateSelection(Console, &Console->Selection.dwSelectionAnchor);
-
-                Length = Console->Title.Length + sizeof(L"Selection - ")/sizeof(WCHAR) + 1;
-                WindowTitle = ConsoleAllocHeap(0, Length * sizeof(WCHAR));
-                wcscpy(WindowTitle, L"Selection - ");
-                wcscat(WindowTitle, Console->Title.Buffer);
-                SetWindowText(GuiData->hWindow, WindowTitle);
-                ConsoleFreeHeap(WindowTitle);
-
-                break;
-            }
-
-            case WM_LBUTTONUP:
-            {
-                COORD c;
-
-                if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
-
-                c = PointToCoord(GuiData, lParam);
-                Console->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
-                GuiConsoleUpdateSelection(Console, &c);
-                ReleaseCapture();
-
-                break;
-            }
-
-            case WM_LBUTTONDBLCLK:
-            {
-                DPRINT1("Handle left-double-click for selecting a word\n");
-                break;
-            }
-
-            case WM_RBUTTONDOWN:
-            case WM_RBUTTONDBLCLK:
-            {
-                if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
-                {
-                    GuiConsolePaste(GuiData);
-                }
-                else
-                {
-                    GuiConsoleCopy(GuiData);
-                }
-
-                GuiData->IgnoreNextMouseSignal = TRUE;
-                break;
-            }
-
-            case WM_MOUSEMOVE:
-            {
-                COORD c;
-
-                if (!(wParam & MK_LBUTTON)) break;
-                if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
-
-                c = PointToCoord(GuiData, lParam); /* TODO: Scroll buffer to bring c into view */
-                GuiConsoleUpdateSelection(Console, &c);
-
-                break;
-            }
-
-            default:
-                Err = FALSE; // TRUE;
-                break;
-        }
-    }
-    else if (Console->InputBuffer.Mode & ENABLE_MOUSE_INPUT)
-    {
-        INPUT_RECORD er;
-        WORD  wKeyState         = GET_KEYSTATE_WPARAM(wParam);
-        DWORD dwButtonState     = 0;
-        DWORD dwControlKeyState = 0;
-        DWORD dwEventFlags      = 0;
-
-        switch (msg)
-        {
-            case WM_LBUTTONDOWN:
-                SetCapture(GuiData->hWindow);
-                dwButtonState = FROM_LEFT_1ST_BUTTON_PRESSED;
-                dwEventFlags  = 0;
-                break;
-
-            case WM_MBUTTONDOWN:
-                SetCapture(GuiData->hWindow);
-                dwButtonState = FROM_LEFT_2ND_BUTTON_PRESSED;
-                dwEventFlags  = 0;
-                break;
-
-            case WM_RBUTTONDOWN:
-                SetCapture(GuiData->hWindow);
-                dwButtonState = RIGHTMOST_BUTTON_PRESSED;
-                dwEventFlags  = 0;
-                break;
-
-            case WM_LBUTTONUP:
-                ReleaseCapture();
-                dwButtonState = 0;
-                dwEventFlags  = 0;
-                break;
-
-            case WM_MBUTTONUP:
-                ReleaseCapture();
-                dwButtonState = 0;
-                dwEventFlags  = 0;
-                break;
-
-            case WM_RBUTTONUP:
-                ReleaseCapture();
-                dwButtonState = 0;
-                dwEventFlags  = 0;
-                break;
-
-            case WM_LBUTTONDBLCLK:
-                dwButtonState = FROM_LEFT_1ST_BUTTON_PRESSED;
-                dwEventFlags  = DOUBLE_CLICK;
-                break;
-
-            case WM_MBUTTONDBLCLK:
-                dwButtonState = FROM_LEFT_2ND_BUTTON_PRESSED;
-                dwEventFlags  = DOUBLE_CLICK;
-                break;
-
-            case WM_RBUTTONDBLCLK:
-                dwButtonState = RIGHTMOST_BUTTON_PRESSED;
-                dwEventFlags  = DOUBLE_CLICK;
-                break;
-
-            case WM_MOUSEMOVE:
-                dwButtonState = 0;
-                dwEventFlags  = MOUSE_MOVED;
-                break;
-
-            case WM_MOUSEWHEEL:
-                dwButtonState = GET_WHEEL_DELTA_WPARAM(wParam) << 16;
-                dwEventFlags  = MOUSE_WHEELED;
-                break;
-
-            case WM_MOUSEHWHEEL:
-                dwButtonState = GET_WHEEL_DELTA_WPARAM(wParam) << 16;
-                dwEventFlags  = MOUSE_HWHEELED;
-                break;
-
-            default:
-                Err = TRUE;
-                break;
-        }
-
-        if (!Err)
-        {
-            if (wKeyState & MK_LBUTTON)
-                dwButtonState |= FROM_LEFT_1ST_BUTTON_PRESSED;
-            if (wKeyState & MK_MBUTTON)
-                dwButtonState |= FROM_LEFT_2ND_BUTTON_PRESSED;
-            if (wKeyState & MK_RBUTTON)
-                dwButtonState |= RIGHTMOST_BUTTON_PRESSED;
-
-            if (GetKeyState(VK_RMENU) & 0x8000)
-                dwControlKeyState |= RIGHT_ALT_PRESSED;
-            if (GetKeyState(VK_LMENU) & 0x8000)
-                dwControlKeyState |= LEFT_ALT_PRESSED;
-            if (GetKeyState(VK_RCONTROL) & 0x8000)
-                dwControlKeyState |= RIGHT_CTRL_PRESSED;
-            if (GetKeyState(VK_LCONTROL) & 0x8000)
-                dwControlKeyState |= LEFT_CTRL_PRESSED;
-            if (GetKeyState(VK_SHIFT) & 0x8000)
-                dwControlKeyState |= SHIFT_PRESSED;
-            if (GetKeyState(VK_NUMLOCK) & 0x0001)
-                dwControlKeyState |= NUMLOCK_ON;
-            if (GetKeyState(VK_SCROLL) & 0x0001)
-                dwControlKeyState |= SCROLLLOCK_ON;
-            if (GetKeyState(VK_CAPITAL) & 0x0001)
-                dwControlKeyState |= CAPSLOCK_ON;
-            /* See WM_CHAR MSDN documentation for instance */
-            if (lParam & 0x01000000)
-                dwControlKeyState |= ENHANCED_KEY;
-
-            er.EventType = MOUSE_EVENT;
-            er.Event.MouseEvent.dwMousePosition   = PointToCoord(GuiData, lParam);
-            er.Event.MouseEvent.dwButtonState     = dwButtonState;
-            er.Event.MouseEvent.dwControlKeyState = dwControlKeyState;
-            er.Event.MouseEvent.dwEventFlags      = dwEventFlags;
-
-            ConioProcessInputEvent(Console, &er);
-        }
-    }
-    else
-    {
-        Err = TRUE;
-    }
-
-    LeaveCriticalSection(&Console->Lock);
-
-Quit:
-    if (Err)
-        return DefWindowProcW(GuiData->hWindow, msg, wParam, lParam);
-    else
-        return 0;
-}
-
-VOID
-GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
-                          PGUI_CONSOLE_DATA GuiData);
-VOID
-GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
-                          PGUI_CONSOLE_DATA GuiData);
-
-static VOID
-GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
-{
-    if (OpenClipboard(GuiData->hWindow) == TRUE)
-    {
-        PCONSOLE Console = GuiData->Console;
-        PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
-
-        if (GetType(Buffer) == TEXTMODE_BUFFER)
-        {
-            GuiCopyFromTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer, GuiData);
-        }
-        else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
-        {
-            GuiCopyFromGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer, GuiData);
-        }
-
-        CloseClipboard();
-
-        /* Clear the selection */
-        GuiConsoleUpdateSelection(Console, NULL);
-        SetWindowText(GuiData->hWindow, Console->Title.Buffer);
-    }
-}
-
-VOID
-GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
-                         PGUI_CONSOLE_DATA GuiData);
-VOID
-GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
-                         PGUI_CONSOLE_DATA GuiData);
-
-static VOID
-GuiConsolePaste(PGUI_CONSOLE_DATA GuiData)
-{
-    if (OpenClipboard(GuiData->hWindow) == TRUE)
-    {
-        PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
-
-        if (GetType(Buffer) == TEXTMODE_BUFFER)
-        {
-            GuiPasteToTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer, GuiData);
-        }
-        else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
-        {
-            GuiPasteToGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer, GuiData);
-        }
-
-        CloseClipboard();
-    }
-}
-
-static VOID
-GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData, PMINMAXINFO minMaxInfo)
-{
-    PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
-    DWORD windx, windy;
-    UINT  WidthUnit, HeightUnit;
-
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
-
-    ActiveBuffer = GuiData->ActiveBuffer;
-
-    GetScreenBufferSizeUnits(ActiveBuffer, GuiData, &WidthUnit, &HeightUnit);
-
-    windx = CONGUI_MIN_WIDTH  * WidthUnit  + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
-    windy = CONGUI_MIN_HEIGHT * HeightUnit + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
-
-    minMaxInfo->ptMinTrackSize.x = windx;
-    minMaxInfo->ptMinTrackSize.y = windy;
-
-    windx = (ActiveBuffer->ScreenBufferSize.X) * WidthUnit  + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
-    windy = (ActiveBuffer->ScreenBufferSize.Y) * HeightUnit + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
-
-    if (ActiveBuffer->ViewSize.X < ActiveBuffer->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL);    // window currently has a horizontal scrollbar
-    if (ActiveBuffer->ViewSize.Y < ActiveBuffer->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL);    // window currently has a vertical scrollbar
-
-    minMaxInfo->ptMaxTrackSize.x = windx;
-    minMaxInfo->ptMaxTrackSize.y = windy;
-
-    LeaveCriticalSection(&Console->Lock);
-}
-
-static VOID
-GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
-{
-    PCONSOLE Console = GuiData->Console;
-
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
-
-    if ((GuiData->WindowSizeLock == FALSE) &&
-        (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED))
-    {
-        PCONSOLE_SCREEN_BUFFER Buff = GuiData->ActiveBuffer;
-        DWORD windx, windy, charx, chary;
-        UINT  WidthUnit, HeightUnit;
-
-        GetScreenBufferSizeUnits(Buff, GuiData, &WidthUnit, &HeightUnit);
-
-        GuiData->WindowSizeLock = TRUE;
-
-        windx = LOWORD(lParam);
-        windy = HIWORD(lParam);
-
-        // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
-        if (Buff->ViewSize.X < Buff->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL);    // window currently has a horizontal scrollbar
-        if (Buff->ViewSize.Y < Buff->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL);    // window currently has a vertical scrollbar
-
-        charx = windx / (int)WidthUnit ;
-        chary = windy / (int)HeightUnit;
-
-        // Character alignment (round size up or down)
-        if ((windx % WidthUnit ) >= (WidthUnit  / 2)) ++charx;
-        if ((windy % HeightUnit) >= (HeightUnit / 2)) ++chary;
-
-        // Compensate for added scroll bars in new window
-        if (charx < Buff->ScreenBufferSize.X) windy -= GetSystemMetrics(SM_CYHSCROLL);    // new window will have a horizontal scroll bar
-        if (chary < Buff->ScreenBufferSize.Y) windx -= GetSystemMetrics(SM_CXVSCROLL);    // new window will have a vertical scroll bar
-
-        charx = windx / (int)WidthUnit ;
-        chary = windy / (int)HeightUnit;
-
-        // Character alignment (round size up or down)
-        if ((windx % WidthUnit ) >= (WidthUnit  / 2)) ++charx;
-        if ((windy % HeightUnit) >= (HeightUnit / 2)) ++chary;
-
-        // Resize window
-        if ((charx != Buff->ViewSize.X) || (chary != Buff->ViewSize.Y))
-        {
-            Buff->ViewSize.X = (charx <= Buff->ScreenBufferSize.X) ? charx : Buff->ScreenBufferSize.X;
-            Buff->ViewSize.Y = (chary <= Buff->ScreenBufferSize.Y) ? chary : Buff->ScreenBufferSize.Y;
-        }
-
-        GuiConsoleResizeWindow(GuiData, WidthUnit, HeightUnit);
-
-        // Adjust the start of the visible area if we are attempting to show nonexistent areas
-        if ((Buff->ScreenBufferSize.X - Buff->ViewOrigin.X) < Buff->ViewSize.X) Buff->ViewOrigin.X = Buff->ScreenBufferSize.X - Buff->ViewSize.X;
-        if ((Buff->ScreenBufferSize.Y - Buff->ViewOrigin.Y) < Buff->ViewSize.Y) Buff->ViewOrigin.Y = Buff->ScreenBufferSize.Y - Buff->ViewSize.Y;
-        InvalidateRect(GuiData->hWindow, NULL, TRUE);
-
-        GuiData->WindowSizeLock = FALSE;
-    }
-
-    LeaveCriticalSection(&Console->Lock);
-}
-
-/*
-// HACK: This functionality is standard for general scrollbars. Don't add it by hand.
-
-VOID
-FASTCALL
-GuiConsoleHandleScrollbarMenu(VOID)
-{
-    HMENU hMenu;
-
-    hMenu = CreatePopupMenu();
-    if (hMenu == NULL)
-    {
-        DPRINT("CreatePopupMenu failed\n");
-        return;
-    }
-
-    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
-    //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
-    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
-    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
-    //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
-    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
-    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
-    //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
-    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
-    //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
-}
-*/
-
-static LRESULT
-GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData, UINT uMsg, WPARAM wParam)
-{
-    PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER Buff;
-    SCROLLINFO sInfo;
-    int fnBar;
-    int old_pos, Maximum;
-    PSHORT pShowXY;
-
-    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
-
-    Buff = GuiData->ActiveBuffer;
-
-    if (uMsg == WM_HSCROLL)
-    {
-        fnBar = SB_HORZ;
-        Maximum = Buff->ScreenBufferSize.X - Buff->ViewSize.X;
-        pShowXY = &Buff->ViewOrigin.X;
-    }
-    else
-    {
-        fnBar = SB_VERT;
-        Maximum = Buff->ScreenBufferSize.Y - Buff->ViewSize.Y;
-        pShowXY = &Buff->ViewOrigin.Y;
-    }
-
-    /* set scrollbar sizes */
-    sInfo.cbSize = sizeof(SCROLLINFO);
-    sInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS;
-
-    if (!GetScrollInfo(GuiData->hWindow, fnBar, &sInfo)) goto Quit;
-
-    old_pos = sInfo.nPos;
-
-    switch (LOWORD(wParam))
-    {
-        case SB_LINELEFT:
-            sInfo.nPos -= 1;
-            break;
-
-        case SB_LINERIGHT:
-            sInfo.nPos += 1;
-            break;
-
-        case SB_PAGELEFT:
-            sInfo.nPos -= sInfo.nPage;
-            break;
-
-        case SB_PAGERIGHT:
-            sInfo.nPos += sInfo.nPage;
-            break;
-
-        case SB_THUMBTRACK:
-            sInfo.nPos = sInfo.nTrackPos;
-            ConioPause(Console, PAUSED_FROM_SCROLLBAR);
-            break;
-
-        case SB_THUMBPOSITION:
-            ConioUnpause(Console, PAUSED_FROM_SCROLLBAR);
-            break;
-
-        case SB_TOP:
-            sInfo.nPos = sInfo.nMin;
-            break;
-
-        case SB_BOTTOM:
-            sInfo.nPos = sInfo.nMax;
-            break;
-
-        default:
-            break;
-    }
-
-    sInfo.nPos = max(sInfo.nPos, 0);
-    sInfo.nPos = min(sInfo.nPos, Maximum);
-
-    if (old_pos != sInfo.nPos)
-    {
-        USHORT OldX = Buff->ViewOrigin.X;
-        USHORT OldY = Buff->ViewOrigin.Y;
-        UINT   WidthUnit, HeightUnit;
-
-        *pShowXY = sInfo.nPos;
-
-        GetScreenBufferSizeUnits(Buff, GuiData, &WidthUnit, &HeightUnit);
-
-        ScrollWindowEx(GuiData->hWindow,
-                       (OldX - Buff->ViewOrigin.X) * WidthUnit ,
-                       (OldY - Buff->ViewOrigin.Y) * HeightUnit,
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL,
-                       SW_INVALIDATE);
-
-        sInfo.fMask = SIF_POS;
-        SetScrollInfo(GuiData->hWindow, fnBar, &sInfo, TRUE);
-
-        UpdateWindow(GuiData->hWindow);
-        // InvalidateRect(GuiData->hWindow, NULL, FALSE);
-    }
-
-Quit:
-    LeaveCriticalSection(&Console->Lock);
-    return 0;
-}
-
-
-BOOL
-EnterFullScreen(PGUI_CONSOLE_DATA GuiData);
-VOID
-LeaveFullScreen(PGUI_CONSOLE_DATA GuiData);
-VOID
-SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen);
-VOID
-GuiConsoleSwitchFullScreen(PGUI_CONSOLE_DATA GuiData);
-
-static LRESULT CALLBACK
-GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-    LRESULT Result = 0;
-    PGUI_CONSOLE_DATA GuiData = NULL;
-    PCONSOLE Console = NULL;
-
-    /*
-     * - If it's the first time we create a window for the terminal,
-     *   just initialize it and return.
-     *
-     * - If we are destroying the window, just do it and return.
-     */
-    if (msg == WM_NCCREATE)
-    {
-        return (LRESULT)GuiConsoleHandleNcCreate(hWnd, (LPCREATESTRUCTW)lParam);
-    }
-    else if (msg == WM_NCDESTROY)
-    {
-        return GuiConsoleHandleNcDestroy(hWnd);
-    }
-
-    /*
-     * Now the terminal window is initialized.
-     * Get the terminal data via the window's data.
-     * If there is no data, just go away.
-     */
-    GuiData = GuiGetGuiData(hWnd);
-    if (GuiData == NULL) return DefWindowProcW(hWnd, msg, wParam, lParam);
-
-    // TEMPORARY HACK until all of the functions can deal with a NULL GuiData->ActiveBuffer ...
-    if (GuiData->ActiveBuffer == NULL) return DefWindowProcW(hWnd, msg, wParam, lParam);
-
-    /*
-     * Just retrieve a pointer to the console in case somebody needs it.
-     * It is not NULL because it was checked in GuiGetGuiData.
-     * Each helper function which needs the console has to validate and lock it.
-     */
-    Console = GuiData->Console;
-
-    /* We have a console, start message dispatching */
-    switch (msg)
-    {
-        case WM_ACTIVATE:
-        {
-            WORD ActivationState = LOWORD(wParam);
-
-            DPRINT1("WM_ACTIVATE - ActivationState = %d\n");
-
-            if ( ActivationState == WA_ACTIVE ||
-                 ActivationState == WA_CLICKACTIVE )
-            {
-                if (GuiData->GuiInfo.FullScreen)
-                {
-                    EnterFullScreen(GuiData);
-                    // // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
-                    // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
-                }
-            }
-            else // if (ActivationState == WA_INACTIVE)
-            {
-                if (GuiData->GuiInfo.FullScreen)
-                {
-                    SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
-                    LeaveFullScreen(GuiData);
-                    // // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
-                    // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
-                }
-            }
-
-            if (ActivationState == WA_CLICKACTIVE) GuiData->IgnoreNextMouseSignal = TRUE;
-
-            break;
-        }
-
-        case WM_CLOSE:
-            if (GuiConsoleHandleClose(GuiData)) goto Default;
-            break;
-
-        case WM_PAINT:
-            GuiConsoleHandlePaint(GuiData);
-            break;
-
-        case WM_PALETTECHANGED:
-        {
-            PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
-
-            DPRINT("WM_PALETTECHANGED called\n");
-
-            /*
-             * Protects against infinite loops:
-             * "... A window that receives this message must not realize
-             * its palette, unless it determines that wParam does not contain
-             * its own window handle." (WM_PALETTECHANGED description - MSDN)
-             *
-             * This message is sent to all windows, including the one that
-             * changed the system palette and caused this message to be sent.
-             * The wParam of this message contains the handle of the window
-             * that caused the system palette to change. To avoid an infinite
-             * loop, care must be taken to check that the wParam of this message
-             * does not match the window's handle.
-             */
-            if ((HWND)wParam == hWnd) break;
-
-            DPRINT("WM_PALETTECHANGED ok\n");
-
-            // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
-            if (ActiveBuffer->PaletteHandle)
-            {
-                DPRINT("WM_PALETTECHANGED changing palette\n");
-
-                /* Specify the use of the system palette for the framebuffer */
-                SetSystemPaletteUse(GuiData->hMemDC, ActiveBuffer->PaletteUsage);
-
-                /* Realize the (logical) palette */
-                RealizePalette(GuiData->hMemDC);
-            }
-
-            DPRINT("WM_PALETTECHANGED quit\n");
-
-            break;
-        }
-
-        case WM_KEYDOWN:
-        case WM_KEYUP:
-        case WM_CHAR:
-        case WM_DEADCHAR:
-        case WM_SYSKEYDOWN:
-        case WM_SYSKEYUP:
-        case WM_SYSCHAR:
-        case WM_SYSDEADCHAR:
-        {
-            /* Detect Alt-Enter presses and switch back and forth to fullscreen mode */
-            if (msg == WM_SYSKEYDOWN && (HIWORD(lParam) & KF_ALTDOWN) && wParam == VK_RETURN)
-            {
-                /* Switch only at first Alt-Enter press, and ignore subsequent key repetitions */
-                if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT)
-                    GuiConsoleSwitchFullScreen(GuiData);
-
-                break;
-            }
-
-            GuiConsoleHandleKey(GuiData, msg, wParam, lParam);
-            break;
-        }
-
-        case WM_TIMER:
-            GuiConsoleHandleTimer(GuiData);
-            break;
-
-        case WM_SETCURSOR:
-        {
-            /*
-             * The message was sent because we are manually triggering a change.
-             * Check whether the mouse is indeed present on this console window
-             * and take appropriate decisions.
-             */
-            if (wParam == -1 && lParam == -1)
-            {
-                POINT mouseCoords;
-                HWND  hWndHit;
-
-                /* Get the placement of the mouse */
-                GetCursorPos(&mouseCoords);
-
-                /* On which window is placed the mouse ? */
-                hWndHit = WindowFromPoint(mouseCoords);
-
-                /* It's our window. Perform the hit-test to be used later on. */
-                if (hWndHit == hWnd)
-                {
-                    wParam = (WPARAM)hWnd;
-                    lParam = DefWindowProcW(hWndHit, WM_NCHITTEST, 0,
-                                            MAKELPARAM(mouseCoords.x, mouseCoords.y));
-                }
-            }
-
-            /* Set the mouse cursor only when we are in the client area */
-            if ((HWND)wParam == hWnd && LOWORD(lParam) == HTCLIENT)
-            {
-                if (GuiData->MouseCursorRefCount >= 0)
-                {
-                    /* Show the cursor */
-                    SetCursor(GuiData->hCursor);
-                }
-                else
-                {
-                    /* Hide the cursor if the reference count is negative */
-                    SetCursor(NULL);
-                }
-                return TRUE;
-            }
-            else
-            {
-                goto Default;
-            }
-        }
-
-        case WM_LBUTTONDOWN:
-        case WM_MBUTTONDOWN:
-        case WM_RBUTTONDOWN:
-        case WM_LBUTTONUP:
-        case WM_MBUTTONUP:
-        case WM_RBUTTONUP:
-        case WM_LBUTTONDBLCLK:
-        case WM_MBUTTONDBLCLK:
-        case WM_RBUTTONDBLCLK:
-        case WM_MOUSEMOVE:
-        case WM_MOUSEWHEEL:
-        case WM_MOUSEHWHEEL:
-        {
-            Result = GuiConsoleHandleMouse(GuiData, msg, wParam, lParam);
-            break;
-        }
-
-        case WM_HSCROLL:
-        case WM_VSCROLL:
-        {
-            Result = GuiConsoleHandleScroll(GuiData, msg, wParam);
-            break;
-        }
-
-        case WM_NCRBUTTONDOWN:
-        {
-            DPRINT1("WM_NCRBUTTONDOWN\n");
-            /*
-             * HACK: !! Because, when we deal with WM_RBUTTON* and we do not
-             * call after that DefWindowProc, on ReactOS, right-clicks on the
-             * (non-client) application title-bar does not display the system
-             * menu and does not trigger a WM_NCRBUTTONUP message too.
-             * See: http://git.reactos.org/?p=reactos.git;a=blob;f=reactos/win32ss/user/user32/windows/defwnd.c;hb=332bc8f482f40fd05ab510f78276576719fbfba8#l1103
-             * and line 1135 too.
-             */
-#if 0
-            if (DefWindowProcW(hWnd, WM_NCHITTEST, 0, lParam) == HTCAPTION)
-            {
-                /* Call DefWindowProcW with the WM_CONTEXTMENU message */
-                msg = WM_CONTEXTMENU;
-            }
-#endif
-            goto Default;
-        }
-        // case WM_NCRBUTTONUP:
-            // DPRINT1("WM_NCRBUTTONUP\n");
-            // goto Default;
-
-        case WM_CONTEXTMENU:
-        {
-            if (DefWindowProcW(hWnd /*GuiData->hWindow*/, WM_NCHITTEST, 0, lParam) == HTCLIENT)
-            {
-                HMENU hMenu = CreatePopupMenu();
-                if (hMenu != NULL)
-                {
-                    GuiConsoleAppendMenuItems(hMenu, GuiConsoleEditMenuItems);
-                    TrackPopupMenuEx(hMenu,
-                                     TPM_RIGHTBUTTON,
-                                     GET_X_LPARAM(lParam),
-                                     GET_Y_LPARAM(lParam),
-                                     hWnd,
-                                     NULL);
-                    DestroyMenu(hMenu);
-                }
-                break;
-            }
-            else
-            {
-                goto Default;
-            }
-        }
-
-        case WM_INITMENU:
-        {
-            HMENU hMenu = (HMENU)wParam;
-            if (hMenu != NULL)
-            {
-                /* Enable or disable the Close menu item */
-                EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND |
-                               (GuiData->IsCloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
-
-                /* Enable or disable the Copy and Paste items */
-                EnableMenuItem(hMenu, ID_SYSTEM_EDIT_COPY , MF_BYCOMMAND |
-                               ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
-                                (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) ? MF_ENABLED : MF_GRAYED));
-                // FIXME: Following whether the active screen buffer is text-mode
-                // or graphics-mode, search for CF_UNICODETEXT or CF_BITMAP formats.
-                EnableMenuItem(hMenu, ID_SYSTEM_EDIT_PASTE, MF_BYCOMMAND |
-                               (!(Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
-                                IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));
-            }
-
-            if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-            {
-                GuiSendMenuEvent(Console, WM_INITMENU);
-                LeaveCriticalSection(&Console->Lock);
-            }
-            break;
-        }
-
-        case WM_MENUSELECT:
-        {
-            if (HIWORD(wParam) == 0xFFFF) // Allow all the menu flags
-            {
-                if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-                {
-                    GuiSendMenuEvent(Console, WM_MENUSELECT);
-                    LeaveCriticalSection(&Console->Lock);
-                }
-            }
-            break;
-        }
-
-        case WM_COMMAND:
-        case WM_SYSCOMMAND:
-        {
-            Result = GuiConsoleHandleSysMenuCommand(GuiData, wParam, lParam);
-            break;
-        }
-
-        case WM_SETFOCUS:
-        case WM_KILLFOCUS:
-        {
-            if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-            {
-                BOOL SetFocus = (msg == WM_SETFOCUS);
-                INPUT_RECORD er;
-
-                er.EventType = FOCUS_EVENT;
-                er.Event.FocusEvent.bSetFocus = SetFocus;
-                ConioProcessInputEvent(Console, &er);
-
-                if (SetFocus)
-                    DPRINT1("TODO: Create console caret\n");
-                else
-                    DPRINT1("TODO: Destroy console caret\n");
-
-                LeaveCriticalSection(&Console->Lock);
-            }
-            break;
-        }
-
-        case WM_GETMINMAXINFO:
-            GuiConsoleGetMinMaxInfo(GuiData, (PMINMAXINFO)lParam);
-            break;
-
-        case WM_SIZE:
-            GuiConsoleResize(GuiData, wParam, lParam);
-            break;
-
-        case PM_RESIZE_TERMINAL:
-        {
-            PCONSOLE_SCREEN_BUFFER Buff = GuiData->ActiveBuffer;
-            HDC hDC;
-            HBITMAP hnew, hold;
-
-            DWORD Width, Height;
-            UINT  WidthUnit, HeightUnit;
-
-            GetScreenBufferSizeUnits(Buff, GuiData, &WidthUnit, &HeightUnit);
-
-            Width  = Buff->ScreenBufferSize.X * WidthUnit ;
-            Height = Buff->ScreenBufferSize.Y * HeightUnit;
-
-            /* Recreate the framebuffer */
-            hDC  = GetDC(GuiData->hWindow);
-            hnew = CreateCompatibleBitmap(hDC, Width, Height);
-            ReleaseDC(GuiData->hWindow, hDC);
-            hold = SelectObject(GuiData->hMemDC, hnew);
-            if (GuiData->hBitmap)
-            {
-                if (hold == GuiData->hBitmap) DeleteObject(GuiData->hBitmap);
-            }
-            GuiData->hBitmap = hnew;
-
-            /* Resize the window to the user's values */
-            GuiData->WindowSizeLock = TRUE;
-            GuiConsoleResizeWindow(GuiData, WidthUnit, HeightUnit);
-            GuiData->WindowSizeLock = FALSE;
-            break;
-        }
-
-        case PM_APPLY_CONSOLE_INFO:
-        {
-            if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-            {
-                GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam);
-                LeaveCriticalSection(&Console->Lock);
-            }
-            break;
-        }
-
-        case PM_CONSOLE_BEEP:
-            DPRINT1("Beep !!\n");
-            Beep(800, 200);
-            break;
-
-        // case PM_CONSOLE_SET_TITLE:
-            // SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
-            // break;
-
-        default: Default:
-            Result = DefWindowProcW(hWnd, msg, wParam, lParam);
-            break;
-    }
-
-    return Result;
-}
-
-
-
-/******************************************************************************
- *                        GUI Terminal Initialization                         *
- ******************************************************************************/
-
-static LRESULT CALLBACK
-GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-    HWND NewWindow;
-    LONG WindowCount;
-    MSG Msg;
-
-    switch (msg)
-    {
-        case WM_CREATE:
-        {
-            SetWindowLongW(hWnd, GWL_USERDATA, 0);
-            return 0;
-        }
-    
-        case PM_CREATE_CONSOLE:
-        {
-            PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
-            PCONSOLE Console = GuiData->Console;
-
-            NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE,
-                                        GUI_CONSOLE_WINDOW_CLASS,
-                                        Console->Title.Buffer,
-                                        WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
-                                        CW_USEDEFAULT,
-                                        CW_USEDEFAULT,
-                                        CW_USEDEFAULT,
-                                        CW_USEDEFAULT,
-                                        NULL,
-                                        NULL,
-                                        ConSrvDllInstance,
-                                        (PVOID)GuiData);
-            if (NULL != NewWindow)
-            {
-                ASSERT(NewWindow == GuiData->hWindow);
-
-                WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
-                WindowCount++;
-                SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
+                // FIXME: HACK: Potential HACK for CORE-8129; see revision 63595.
+                CreateSysMenu(GuiData->hWindow);
 
-                DPRINT("Set icons via PM_CREATE_CONSOLE\n");
-                if (GuiData->hIcon == NULL)
+                if (GuiData->IsWindowVisible)
                 {
-                    DPRINT("Not really /o\\...\n");
-                    GuiData->hIcon   = ghDefaultIcon;
-                    GuiData->hIconSm = ghDefaultIconSm;
+                    /* Switch to full-screen mode if necessary */
+                    // FIXME: Move elsewhere, it cause misdrawings of the window.
+                    if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE);
+
+                    DPRINT("PM_CREATE_CONSOLE -- showing window\n");
+                    ShowWindowAsync(NewWindow, (int)GuiData->GuiInfo.ShowWindow);
                 }
-                else if (GuiData->hIcon != ghDefaultIcon)
+                else
                 {
-                    DPRINT("Yes \\o/\n");
-                    SendMessageW(GuiData->hWindow, WM_SETICON, ICON_BIG, (LPARAM)GuiData->hIcon);
-                    SendMessageW(GuiData->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)GuiData->hIconSm);
+                    DPRINT("PM_CREATE_CONSOLE -- hidden window\n");
+                    ShowWindowAsync(NewWindow, SW_HIDE);
                 }
 
-                /* Move and resize the window to the user's values */
-                /* CAN WE DEADLOCK ?? */
-                GuiConsoleMoveWindow(GuiData);
-                SendMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
-
-                /* Switch to full-screen mode if necessary */
-                if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE);
-
-                // ShowWindow(NewWindow, (int)wParam);
-                ShowWindowAsync(NewWindow, (int)wParam);
-                DPRINT("Window showed\n");
+                continue;
             }
 
-            return (LRESULT)NewWindow;
-        }
+            case PM_DESTROY_CONSOLE:
+            {
+                PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)msg.lParam;
+                MSG TempMsg;
 
-        case PM_DESTROY_CONSOLE:
-        {
-            PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
+                /* Exit the full screen mode if it was already set */
+                // LeaveFullScreen(GuiData);
 
-            /* Exit the full screen mode if it was already set */
-            // LeaveFullScreen(GuiData);
+                /*
+                 * Window creation is done using a PostMessage(), so it's possible
+                 * that the window that we want to destroy doesn't exist yet.
+                 * So first empty the message queue.
+                 */
+                while (PeekMessageW(&TempMsg, NULL, 0, 0, PM_REMOVE))
+                {
+                    DispatchMessageW(&TempMsg);
+                }
 
-            /*
-             * Window creation is done using a PostMessage(), so it's possible
-             * that the window that we want to destroy doesn't exist yet.
-             * So first empty the message queue.
-             */
-            /*
-            while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
-            {
-                TranslateMessage(&Msg);
-                DispatchMessageW(&Msg);
-            }*/
-            while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) ;
+                if (GuiData->hWindow == NULL) continue;
 
-            if (GuiData->hWindow != NULL) /* && DestroyWindow(GuiData->hWindow) */
-            {
                 DestroyWindow(GuiData->hWindow);
 
-                WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
-                WindowCount--;
-                SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
-                if (0 == WindowCount)
+                NtSetEvent(GuiData->hGuiTermEvent, NULL);
+
+                if (InterlockedDecrement(&WindowCount) == 0)
                 {
-                    NotifyWnd = NULL;
-                    DestroyWindow(hWnd);
-                    DPRINT("CONSRV: Going to quit the Gui Thread!!\n");
-                    PostQuitMessage(0);
+                    DPRINT("CONSRV: Going to quit the Input Thread 0x%p\n", InputThreadId);
+                    goto Quit;
                 }
-            }
 
-            return 0;
+                continue;
+            }
         }
 
-        default:
-            return DefWindowProcW(hWnd, msg, wParam, lParam);
+        TranslateMessage(&msg);
+        DispatchMessageW(&msg);
+    }
+
+Quit:
+    DPRINT("CONSRV: Quit the Input Thread 0x%p, Status = 0x%08lx\n", InputThreadId, Status);
+
+    /* Remove this console input thread from this desktop */
+    // DesktopConsoleThreadInfo.DesktopHandle;
+    DesktopConsoleThreadInfo.ThreadId = 0;
+    NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+                         &DesktopConsoleThreadInfo,
+                         sizeof(DesktopConsoleThreadInfo));
+
+    /* Close the duplicated desktop handle */
+    CloseDesktop(DesktopConsoleThreadInfo.DesktopHandle); // NtUserCloseDesktop
+
+    /* Cleanup CSR thread */
+    if (pcsrt)
+    {
+        if (hThread != pcsrt->ThreadHandle)
+            DPRINT1("WARNING!! hThread (0x%p) != pcsrt->ThreadHandle (0x%p), you may expect crashes soon!!\n", hThread, pcsrt->ThreadHandle);
+
+        CsrDereferenceThread(pcsrt);
     }
+
+    /* Exit the thread */
+    RtlExitUserThread(Status);
+    return 0;
 }
 
-static DWORD NTAPI
-GuiConsoleGuiThread(PVOID Data)
+// FIXME: Maybe return a NTSTATUS
+static BOOL
+GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo,
+        IN HANDLE ConsoleLeaderProcessHandle,
+        IN OUT PGUI_INIT_INFO GuiInitInfo)
 {
-    MSG msg;
-    PHANDLE GraphicsStartupEvent = (PHANDLE)Data;
+    BOOL Success = TRUE;
+    UNICODE_STRING DesktopPath;
+    DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo;
+    HWINSTA hWinSta;
+    HDESK hDesk;
+
+    NTSTATUS Status;
+    HANDLE hInputThread;
+    CLIENT_ID ClientId;
 
     /*
-     * This thread dispatches all the console notifications to the notify window.
-     * It is common for all the console windows.
+     * Initialize and register the console window class, if needed.
      */
-
-    PrivateCsrssManualGuiCheck(+1);
-
-    NotifyWnd = CreateWindowW(L"ConSrvCreateNotify",
-                              L"",
-                              WS_OVERLAPPEDWINDOW,
-                              CW_USEDEFAULT,
-                              CW_USEDEFAULT,
-                              CW_USEDEFAULT,
-                              CW_USEDEFAULT,
-                              NULL,
-                              NULL,
-                              ConSrvDllInstance,
-                              NULL);
-    if (NULL == NotifyWnd)
+    if (!ConsInitialized)
     {
-        PrivateCsrssManualGuiCheck(-1);
-        SetEvent(*GraphicsStartupEvent);
-        return 1;
+        if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE;
+        ConsInitialized = TRUE;
     }
 
-    SetEvent(*GraphicsStartupEvent);
+    /*
+     * Set-up the console input thread. We have
+     * one console input thread per desktop.
+     */
+
+    if (!CsrImpersonateClient(NULL))
+        // return STATUS_BAD_IMPERSONATION_LEVEL;
+        return FALSE;
 
-    while (GetMessageW(&msg, NULL, 0, 0))
+    if (ConsoleInitInfo->DesktopLength)
     {
-        TranslateMessage(&msg);
-        DispatchMessageW(&msg);
+        DesktopPath.MaximumLength = ConsoleInitInfo->DesktopLength;
+        DesktopPath.Length = DesktopPath.MaximumLength - sizeof(UNICODE_NULL);
+        DesktopPath.Buffer = ConsoleInitInfo->Desktop;
+    }
+    else
+    {
+        RtlInitUnicodeString(&DesktopPath, L"Default");
     }
 
-    DPRINT("CONSRV: Quit the Gui Thread!!\n");
-    PrivateCsrssManualGuiCheck(-1);
+    hDesk = NtUserResolveDesktop(ConsoleLeaderProcessHandle,
+                                 &DesktopPath,
+                                 FALSE,
+                                 &hWinSta);
+    DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n",
+           &DesktopPath, hDesk, hWinSta);
 
-    return 1;
-}
+    CsrRevertToSelf();
 
-static BOOL
-GuiInit(VOID)
-{
-    WNDCLASSEXW wc;
-    ATOM ConsoleClassAtom;
+    if (hDesk == NULL) return FALSE;
 
-    /* Exit if we were already initialized */
-    // if (ConsInitialized) return TRUE;
+    /*
+     * We need to see whether we need to create a
+     * new console input thread for this desktop.
+     */
+    DesktopConsoleThreadInfo.DesktopHandle = hDesk;
+    DesktopConsoleThreadInfo.ThreadId = (ULONG_PTR)INVALID_HANDLE_VALUE; // Special value to say we just want to retrieve the thread ID.
+    NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+                         &DesktopConsoleThreadInfo,
+                         sizeof(DesktopConsoleThreadInfo));
+    DPRINT("NtUserConsoleControl returned ThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId);
 
     /*
-     * Initialize and register the different window classes, if needed.
+     * Save the opened window station and desktop handles in the initialization
+     * structure. They will be used later on, and released, by the GUI frontend.
      */
-    if (!ConsInitialized)
+    GuiInitInfo->WinSta  = hWinSta;
+    GuiInitInfo->Desktop = hDesk;
+
+    /* Here GuiInitInfo contains original handles */
+
+    /* If we already have a console input thread on this desktop... */
+    if (DesktopConsoleThreadInfo.ThreadId != 0)
     {
-        /* Initialize the notification window class */
-        wc.cbSize = sizeof(WNDCLASSEXW);
-        wc.lpszClassName = L"ConSrvCreateNotify";
-        wc.lpfnWndProc = GuiConsoleNotifyWndProc;
-        wc.style = 0;
-        wc.hInstance = ConSrvDllInstance;
-        wc.hIcon = NULL;
-        wc.hIconSm = NULL;
-        wc.hCursor = NULL;
-        wc.hbrBackground = NULL;
-        wc.lpszMenuName = NULL;
-        wc.cbClsExtra = 0;
-        wc.cbWndExtra = 0;
-        if (RegisterClassExW(&wc) == 0)
-        {
-            DPRINT1("Failed to register GUI notify wndproc\n");
-            return FALSE;
-        }
+        /* ... just use it... */
+        DPRINT("Using input thread InputThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId);
+        GuiInitInfo->InputThreadId = DesktopConsoleThreadInfo.ThreadId;
+        goto Quit;
+    }
 
-        /* Initialize the console window class */
-        ghDefaultIcon   = LoadImageW(ConSrvDllInstance,
-                                     MAKEINTRESOURCEW(IDI_TERMINAL),
-                                     IMAGE_ICON,
-                                     GetSystemMetrics(SM_CXICON),
-                                     GetSystemMetrics(SM_CYICON),
-                                     LR_SHARED);
-        ghDefaultIconSm = LoadImageW(ConSrvDllInstance,
-                                     MAKEINTRESOURCEW(IDI_TERMINAL),
-                                     IMAGE_ICON,
-                                     GetSystemMetrics(SM_CXSMICON),
-                                     GetSystemMetrics(SM_CYSMICON),
-                                     LR_SHARED);
-        ghDefaultCursor = LoadCursorW(NULL, IDC_ARROW);
-        wc.cbSize = sizeof(WNDCLASSEXW);
-        wc.lpszClassName = GUI_CONSOLE_WINDOW_CLASS;
-        wc.lpfnWndProc = GuiConsoleWndProc;
-        wc.style = CS_DBLCLKS /* | CS_HREDRAW | CS_VREDRAW */;
-        wc.hInstance = ConSrvDllInstance;
-        wc.hIcon = ghDefaultIcon;
-        wc.hIconSm = ghDefaultIconSm;
-        wc.hCursor = ghDefaultCursor;
-        wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // The color of a terminal when it is switch off.
-        wc.lpszMenuName = NULL;
-        wc.cbClsExtra = 0;
-        wc.cbWndExtra = GWLP_CONSOLEWND_ALLOC;
-
-        ConsoleClassAtom = RegisterClassExW(&wc);
-        if (ConsoleClassAtom == 0)
-        {
-            DPRINT1("Failed to register GUI console wndproc\n");
-            return FALSE;
-        }
-        else
-        {
-            NtUserConsoleControl(GuiConsoleWndClassAtom, &ConsoleClassAtom, sizeof(ATOM));
-        }
+    /* ... otherwise create a new one. */
 
-        ConsInitialized = TRUE;
+    /* Initialize a startup event for the thread to signal it */
+    Status = NtCreateEvent(&GuiInitInfo->GuiThreadStartupEvent, EVENT_ALL_ACCESS,
+                           NULL, SynchronizationEvent, FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        Success = FALSE;
+        goto Quit;
     }
 
     /*
-     * Set-up the notification window
+     * Duplicate the desktop handle for the console input thread internal needs.
+     * If it happens to need also a window station handle in the future, then
+     * it is there that you also need to duplicate the window station handle!
+     *
+     * Note also that we are going to temporarily overwrite the stored handles
+     * in GuiInitInfo because it happens that we use also this structure to give
+     * the duplicated handles to the input thread that is going to initialize.
+     * After the input thread finishes its initialization, we restore the handles
+     * in GuiInitInfo to their old values.
      */
-    if (NULL == NotifyWnd)
+    Status = NtDuplicateObject(NtCurrentProcess(),
+                               hDesk,
+                               NtCurrentProcess(),
+                               (PHANDLE)&GuiInitInfo->Desktop,
+                               0, 0, DUPLICATE_SAME_ACCESS);
+    if (!NT_SUCCESS(Status))
     {
-        HANDLE ThreadHandle;
-        HANDLE GraphicsStartupEvent;
-
-        GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
-        if (NULL == GraphicsStartupEvent) return FALSE;
-
-        ThreadHandle = CreateThread(NULL,
-                                    0,
-                                    GuiConsoleGuiThread,
-                                    (PVOID)&GraphicsStartupEvent,
-                                    0,
-                                    NULL);
-        if (NULL == ThreadHandle)
-        {
-            CloseHandle(GraphicsStartupEvent);
-            DPRINT1("CONSRV: Failed to create graphics console thread. Expect problems\n");
-            return FALSE;
-        }
-        SetThreadPriority(ThreadHandle, THREAD_PRIORITY_HIGHEST);
-        CloseHandle(ThreadHandle);
+        Success = FALSE;
+        goto Quit;
+    }
 
-        WaitForSingleObject(GraphicsStartupEvent, INFINITE);
-        CloseHandle(GraphicsStartupEvent);
+    /* Here GuiInitInfo contains duplicated handles */
 
-        if (NULL == NotifyWnd)
-        {
-            DPRINT1("CONSRV: Failed to create notification window.\n");
-            return FALSE;
-        }
+    Status = RtlCreateUserThread(NtCurrentProcess(),
+                                 NULL,
+                                 TRUE, // Start the thread in suspended state
+                                 0,
+                                 0,
+                                 0,
+                                 (PVOID)GuiConsoleInputThread,
+                                 (PVOID)GuiInitInfo,
+                                 &hInputThread,
+                                 &ClientId);
+    if (NT_SUCCESS(Status))
+    {
+        /* Add it as a static server thread and resume it */
+        CsrAddStaticServerThread(hInputThread, &ClientId, 0);
+        Status = NtResumeThread(hInputThread, NULL);
     }
+    DPRINT("Thread creation hInputThread = 0x%p, InputThreadId = 0x%p, Status = 0x%08lx\n",
+           hInputThread, ClientId.UniqueThread, Status);
 
-    // ConsInitialized = TRUE;
+    if (!NT_SUCCESS(Status) || hInputThread == NULL)
+    {
+        /* Close the thread's handle */
+        if (hInputThread) NtClose(hInputThread);
 
-    return TRUE;
-}
+        /* We need to close here the duplicated desktop handle */
+        CloseDesktop(GuiInitInfo->Desktop); // NtUserCloseDesktop
+
+        /* Close the startup event and bail out */
+        NtClose(GuiInitInfo->GuiThreadStartupEvent);
+
+        DPRINT1("CONSRV: Failed to create graphics console thread.\n");
+        Success = FALSE;
+        goto Quit;
+    }
+
+    /* No need to close hInputThread, this is done by CSR automatically */
+
+    /* Wait for the thread to finish its initialization, and close the startup event */
+    NtWaitForSingleObject(GuiInitInfo->GuiThreadStartupEvent, FALSE, NULL);
+    NtClose(GuiInitInfo->GuiThreadStartupEvent);
+
+    /*
+     * Save the input thread ID for later use, and restore the original handles.
+     * The copies are held by the console input thread.
+     */
+    GuiInitInfo->InputThreadId = (ULONG_PTR)ClientId.UniqueThread;
+    GuiInitInfo->WinSta  = hWinSta;
+    GuiInitInfo->Desktop = hDesk;
+
+    /* Here GuiInitInfo contains again original handles */
+
+Quit:
+    if (!Success)
+    {
+        /*
+         * Close the original handles. Do not use the copies in GuiInitInfo
+         * because we may have failed in the middle of the duplicate operation
+         * and the handles stored in GuiInitInfo may have changed.
+         */
+        CloseDesktop(hDesk); // NtUserCloseDesktop
+        CloseWindowStation(hWinSta); // NtUserCloseWindowStation
+    }
 
+    return Success;
+}
 
 
 /******************************************************************************
@@ -2330,137 +471,55 @@ GuiInit(VOID)
 static VOID NTAPI
 GuiDeinitFrontEnd(IN OUT PFRONTEND This);
 
-NTSTATUS NTAPI
+static NTSTATUS NTAPI
 GuiInitFrontEnd(IN OUT PFRONTEND This,
-                IN PCONSOLE Console)
+                IN PCONSRV_CONSOLE Console)
 {
     PGUI_INIT_INFO GuiInitInfo;
-    PCONSOLE_INFO  ConsoleInfo;
-    PCONSOLE_START_INFO ConsoleStartInfo;
-
     PGUI_CONSOLE_DATA GuiData;
-    GUI_CONSOLE_INFO  TermInfo;
-
-    SIZE_T Length    = 0;
-    LPWSTR IconPath  = NULL;
-    INT    IconIndex = 0;
 
-    if (This == NULL || Console == NULL || This->OldData == NULL)
+    if (This == NULL || Console == NULL || This->Context2 == NULL)
         return STATUS_INVALID_PARAMETER;
 
     ASSERT(This->Console == Console);
 
-    GuiInitInfo = This->OldData;
-
-    if (GuiInitInfo->ConsoleInfo == NULL || GuiInitInfo->ConsoleStartInfo == NULL)
-        return STATUS_INVALID_PARAMETER;
-
-    ConsoleInfo      = GuiInitInfo->ConsoleInfo;
-    ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo;
-
-    IconPath  = ConsoleStartInfo->IconPath;
-    IconIndex = ConsoleStartInfo->IconIndex;
-
+    GuiInitInfo = This->Context2;
 
     /* Terminal data allocation */
-    GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
+    GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiData));
     if (!GuiData)
     {
         DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
         return STATUS_UNSUCCESSFUL;
     }
-    /* HACK */ Console->TermIFace.Data = (PVOID)GuiData; /* HACK */
+    /// /* HACK */ Console->FrontEndIFace.Context = (PVOID)GuiData; /* HACK */
     GuiData->Console      = Console;
     GuiData->ActiveBuffer = Console->ActiveBuffer;
     GuiData->hWindow = NULL;
+    GuiData->IsWindowVisible = GuiInitInfo->IsWindowVisible;
 
     /* The console can be resized */
     Console->FixedSize = FALSE;
 
     InitializeCriticalSection(&GuiData->Lock);
 
-
     /*
-     * Load terminal settings
+     * Set up GUI data
      */
+    RtlCopyMemory(&GuiData->GuiInfo, &GuiInitInfo->TermInfo, sizeof(GuiInitInfo->TermInfo));
 
-    /* 1. Load the default settings */
-    GuiConsoleGetDefaultSettings(&TermInfo, GuiInitInfo->ProcessId);
-
-    /* 3. Load the remaining console settings via the registry. */
-    if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
-    {
-        /* Load the terminal infos from the registry. */
-        GuiConsoleReadUserSettings(&TermInfo,
-                                   ConsoleInfo->ConsoleTitle,
-                                   GuiInitInfo->ProcessId);
-
-        /*
-         * Now, update them with the properties the user might gave to us
-         * via the STARTUPINFO structure before calling CreateProcess
-         * (and which was transmitted via the ConsoleStartInfo structure).
-         * We therefore overwrite the values read in the registry.
-         */
-        if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW)
-        {
-            TermInfo.ShowWindow = ConsoleStartInfo->wShowWindow;
-        }
-        if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
-        {
-            TermInfo.AutoPosition = FALSE;
-            TermInfo.WindowOrigin.x = ConsoleStartInfo->dwWindowOrigin.X;
-            TermInfo.WindowOrigin.y = ConsoleStartInfo->dwWindowOrigin.Y;
-        }
-        if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
-        {
-            TermInfo.FullScreen = TRUE;
-        }
-    }
-
+    /* Initialize the icon handles */
+    if (GuiInitInfo->hIcon != NULL)
+        GuiData->hIcon = GuiInitInfo->hIcon;
+    else
+        GuiData->hIcon = ghDefaultIcon;
 
-    /*
-     * Set up GUI data
-     */
+    if (GuiInitInfo->hIconSm != NULL)
+        GuiData->hIconSm = GuiInitInfo->hIconSm;
+    else
+        GuiData->hIconSm = ghDefaultIconSm;
 
-    Length = min(wcslen(TermInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
-    wcsncpy(GuiData->GuiInfo.FaceName, TermInfo.FaceName, LF_FACESIZE);
-    GuiData->GuiInfo.FaceName[Length] = L'\0';
-    GuiData->GuiInfo.FontFamily     = TermInfo.FontFamily;
-    GuiData->GuiInfo.FontSize       = TermInfo.FontSize;
-    GuiData->GuiInfo.FontWeight     = TermInfo.FontWeight;
-    GuiData->GuiInfo.UseRasterFonts = TermInfo.UseRasterFonts;
-    GuiData->GuiInfo.FullScreen     = TermInfo.FullScreen;
-    GuiData->GuiInfo.ShowWindow     = TermInfo.ShowWindow;
-    GuiData->GuiInfo.AutoPosition   = TermInfo.AutoPosition;
-    GuiData->GuiInfo.WindowOrigin   = TermInfo.WindowOrigin;
-
-    /* Initialize the icon handles to their default values */
-    GuiData->hIcon   = ghDefaultIcon;
-    GuiData->hIconSm = ghDefaultIconSm;
-
-    /* Get the associated icon, if any */
-    if (IconPath == NULL || IconPath[0] == L'\0')
-    {
-        IconPath  = ConsoleStartInfo->AppPath;
-        IconIndex = 0;
-    }
-    DPRINT("IconPath = %S ; IconIndex = %lu\n", (IconPath ? IconPath : L"n/a"), IconIndex);
-    if (IconPath && IconPath[0] != L'\0')
-    {
-        HICON hIcon = NULL, hIconSm = NULL;
-        PrivateExtractIconExW(IconPath,
-                              IconIndex,
-                              &hIcon,
-                              &hIconSm,
-                              1);
-        DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
-        if (hIcon != NULL)
-        {
-            DPRINT("Effectively set the icons\n");
-            GuiData->hIcon   = hIcon;
-            GuiData->hIconSm = hIconSm;
-        }
-    }
+    ASSERT(GuiData->hIcon && GuiData->hIconSm);
 
     /* Mouse is shown by default with its default cursor shape */
     GuiData->hCursor = ghDefaultCursor;
@@ -2468,6 +527,8 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
 
     /* A priori don't ignore mouse signals */
     GuiData->IgnoreNextMouseSignal = FALSE;
+    /* Initialize HACK FOR CORE-8394. See conwnd.c!OnMouse for more details. */
+    GuiData->HackCORE8394IgnoreNextMove = FALSE;
 
     /* Close button and the corresponding system menu item are enabled by default */
     GuiData->IsCloseButtonEnabled = TRUE;
@@ -2475,23 +536,42 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
     /* There is no user-reserved menu id range by default */
     GuiData->CmdIdLow = GuiData->CmdIdHigh = 0;
 
+    /* Initialize the selection */
+    RtlZeroMemory(&GuiData->Selection, sizeof(GuiData->Selection));
+    GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION;
+    RtlZeroMemory(&GuiData->dwSelectionCursor, sizeof(GuiData->dwSelectionCursor));
+    GuiData->LineSelection = FALSE; // Default to block selection
+    // TODO: Retrieve the selection mode via the registry.
+
+    GuiData->InputThreadId = GuiInitInfo->InputThreadId;
+    GuiData->WinSta  = GuiInitInfo->WinSta;
+    GuiData->Desktop = GuiInitInfo->Desktop;
+
+    /* Finally, finish to initialize the frontend structure */
+    This->Context  = GuiData;
+    ConsoleFreeHeap(This->Context2);
+    This->Context2 = NULL;
+
     /*
      * We need to wait until the GUI has been fully initialized
      * to retrieve custom settings i.e. WindowSize etc...
      * Ideally we could use SendNotifyMessage for this but its not
      * yet implemented.
      */
-    GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    NtCreateEvent(&GuiData->hGuiInitEvent, EVENT_ALL_ACCESS,
+                  NULL, SynchronizationEvent, FALSE);
+    NtCreateEvent(&GuiData->hGuiTermEvent, EVENT_ALL_ACCESS,
+                  NULL, SynchronizationEvent, FALSE);
 
     DPRINT("GUI - Checkpoint\n");
 
     /* Create the terminal window */
-    PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, GuiData->GuiInfo.ShowWindow, (LPARAM)GuiData);
+    PostThreadMessageW(GuiData->InputThreadId, PM_CREATE_CONSOLE, 0, (LPARAM)GuiData);
 
     /* Wait until initialization has finished */
-    WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
+    NtWaitForSingleObject(GuiData->hGuiInitEvent, FALSE, NULL);
     DPRINT("OK we created the console window\n");
-    CloseHandle(GuiData->hGuiInitEvent);
+    NtClose(GuiData->hGuiInitEvent);
     GuiData->hGuiInitEvent = NULL;
 
     /* Check whether we really succeeded in initializing the terminal window */
@@ -2502,20 +582,23 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
         return STATUS_UNSUCCESSFUL;
     }
 
-    /* Finally, finish to initialize the frontend structure */
-    This->Data = GuiData;
-    if (This->OldData) ConsoleFreeHeap(This->OldData);
-    This->OldData = NULL;
-
     return STATUS_SUCCESS;
 }
 
 static VOID NTAPI
 GuiDeinitFrontEnd(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
+
+    DPRINT("Send PM_DESTROY_CONSOLE message and wait on hGuiTermEvent...\n");
+    PostThreadMessageW(GuiData->InputThreadId, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
+    NtWaitForSingleObject(GuiData->hGuiTermEvent, FALSE, NULL);
+    DPRINT("hGuiTermEvent set\n");
+    NtClose(GuiData->hGuiTermEvent);
+    GuiData->hGuiTermEvent = NULL;
 
-    SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
+    CloseDesktop(GuiData->Desktop); // NtUserCloseDesktop
+    CloseWindowStation(GuiData->WinSta); // NtUserCloseWindowStation
 
     DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n",
             GuiData->hIcon, ghDefaultIcon, GuiData->hIconSm, ghDefaultIconSm);
@@ -2530,7 +613,7 @@ GuiDeinitFrontEnd(IN OUT PFRONTEND This)
         DestroyIcon(GuiData->hIconSm);
     }
 
-    This->Data = NULL;
+    This->Context = NULL;
     DeleteCriticalSection(&GuiData->Lock);
     ConsoleFreeHeap(GuiData);
 
@@ -2541,13 +624,12 @@ static VOID NTAPI
 GuiDrawRegion(IN OUT PFRONTEND This,
               SMALL_RECT* Region)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
-    RECT RegionRect;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
 
-    SmallRectToRect(GuiData, &RegionRect, Region);
-    /* Do not erase the background: it speeds up redrawing and reduce flickering */
-    InvalidateRect(GuiData->hWindow, &RegionRect, FALSE);
-    /**UpdateWindow(GuiData->hWindow);**/
+    /* Do nothing if the window is hidden */
+    if (!GuiData->IsWindowVisible) return;
+
+    DrawRegion(GuiData, Region);
 }
 
 static VOID NTAPI
@@ -2559,13 +641,16 @@ GuiWriteStream(IN OUT PFRONTEND This,
                PWCHAR Buffer,
                UINT Length)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     PCONSOLE_SCREEN_BUFFER Buff;
     SHORT CursorEndX, CursorEndY;
     RECT ScrollRect;
 
     if (NULL == GuiData || NULL == GuiData->hWindow) return;
 
+    /* Do nothing if the window is hidden */
+    if (!GuiData->IsWindowVisible) return;
+
     Buff = GuiData->ActiveBuffer;
     if (GetType(Buff) != TEXTMODE_BUFFER) return;
 
@@ -2586,12 +671,12 @@ GuiWriteStream(IN OUT PFRONTEND This,
                        SW_INVALIDATE);
     }
 
-    GuiDrawRegion(This, Region);
+    DrawRegion(GuiData, Region);
 
     if (CursorStartX < Region->Left || Region->Right < CursorStartX
             || CursorStartY < Region->Top || Region->Bottom < CursorStartY)
     {
-        GuiInvalidateCell(This, CursorStartX, CursorStartY);
+        InvalidateCell(GuiData, CursorStartX, CursorStartY);
     }
 
     CursorEndX = Buff->CursorPosition.X;
@@ -2600,24 +685,37 @@ GuiWriteStream(IN OUT PFRONTEND This,
             || CursorEndY < Region->Top || Region->Bottom < CursorEndY)
             && (CursorEndX != CursorStartX || CursorEndY != CursorStartY))
     {
-        GuiInvalidateCell(This, CursorEndX, CursorEndY);
+        InvalidateCell(GuiData, CursorEndX, CursorEndY);
     }
 
+    // HACK!!
     // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
     // repaint the window without having it just freeze up and stay on the screen permanently.
     Buff->CursorBlinkOn = TRUE;
     SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
 }
 
+/* static */ VOID NTAPI
+GuiRingBell(IN OUT PFRONTEND This)
+{
+    PGUI_CONSOLE_DATA GuiData = This->Context;
+
+    /* Emit an error beep sound */
+    SendNotifyMessage(GuiData->hWindow, PM_CONSOLE_BEEP, 0, 0);
+}
+
 static BOOL NTAPI
 GuiSetCursorInfo(IN OUT PFRONTEND This,
                  PCONSOLE_SCREEN_BUFFER Buff)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
+
+    /* Do nothing if the window is hidden */
+    if (!GuiData->IsWindowVisible) return TRUE;
 
     if (GuiData->ActiveBuffer == Buff)
     {
-        GuiInvalidateCell(This, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+        InvalidateCell(GuiData, Buff->CursorPosition.X, Buff->CursorPosition.Y);
     }
 
     return TRUE;
@@ -2629,14 +727,17 @@ GuiSetScreenInfo(IN OUT PFRONTEND This,
                  SHORT OldCursorX,
                  SHORT OldCursorY)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
+
+    /* Do nothing if the window is hidden */
+    if (!GuiData->IsWindowVisible) return TRUE;
 
     if (GuiData->ActiveBuffer == Buff)
     {
         /* Redraw char at old position (remove cursor) */
-        GuiInvalidateCell(This, OldCursorX, OldCursorY);
+        InvalidateCell(GuiData, OldCursorX, OldCursorY);
         /* Redraw char at new position (show cursor) */
-        GuiInvalidateCell(This, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+        InvalidateCell(GuiData, Buff->CursorPosition.X, Buff->CursorPosition.Y);
     }
 
     return TRUE;
@@ -2645,7 +746,7 @@ GuiSetScreenInfo(IN OUT PFRONTEND This,
 static VOID NTAPI
 GuiResizeTerminal(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
 
     /* Resize the window to the user's values */
     PostMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
@@ -2654,14 +755,14 @@ GuiResizeTerminal(IN OUT PFRONTEND This)
 static VOID NTAPI
 GuiSetActiveScreenBuffer(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     PCONSOLE_SCREEN_BUFFER ActiveBuffer;
     HPALETTE hPalette;
 
     EnterCriticalSection(&GuiData->Lock);
     GuiData->WindowSizeLock = TRUE;
 
-    InterlockedExchangePointer(&GuiData->ActiveBuffer,
+    InterlockedExchangePointer((PVOID*)&GuiData->ActiveBuffer,
                                ConDrvGetActiveScreenBuffer(GuiData->Console));
 
     GuiData->WindowSizeLock = FALSE;
@@ -2671,15 +772,11 @@ GuiSetActiveScreenBuffer(IN OUT PFRONTEND This)
 
     /* Change the current palette */
     if (ActiveBuffer->PaletteHandle == NULL)
-    {
         hPalette = GuiData->hSysPalette;
-    }
     else
-    {
         hPalette = ActiveBuffer->PaletteHandle;
-    }
 
-    DPRINT1("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette);
+    DPRINT("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette);
 
     /* Set the new palette for the framebuffer */
     SelectPalette(GuiData->hMemDC, hPalette, FALSE);
@@ -2698,7 +795,7 @@ static VOID NTAPI
 GuiReleaseScreenBuffer(IN OUT PFRONTEND This,
                        IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
 
     /*
      * If we were notified to release a screen buffer that is not actually
@@ -2731,31 +828,13 @@ GuiReleaseScreenBuffer(IN OUT PFRONTEND This,
         EnterCriticalSection(&GuiData->Lock);
         GuiData->WindowSizeLock = TRUE;
 
-        InterlockedExchangePointer(&GuiData->ActiveBuffer, NULL);
+        InterlockedExchangePointer((PVOID*)&GuiData->ActiveBuffer, NULL);
 
         GuiData->WindowSizeLock = FALSE;
         LeaveCriticalSection(&GuiData->Lock);
     }
 }
 
-static BOOL NTAPI
-GuiProcessKeyCallback(IN OUT PFRONTEND This,
-                      MSG* msg,
-                      BYTE KeyStateMenu,
-                      DWORD ShiftState,
-                      UINT VirtualKeyCode,
-                      BOOL Down)
-{
-    if ((ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) || KeyStateMenu & 0x80) &&
-        (VirtualKeyCode == VK_ESCAPE || VirtualKeyCode == VK_TAB || VirtualKeyCode == VK_SPACE))
-    {
-        DefWindowProcW(msg->hwnd, msg->message, msg->wParam, msg->lParam);
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
 static BOOL NTAPI
 GuiSetMouseCursor(IN OUT PFRONTEND This,
                   HCURSOR CursorHandle);
@@ -2763,10 +842,10 @@ GuiSetMouseCursor(IN OUT PFRONTEND This,
 static VOID NTAPI
 GuiRefreshInternalInfo(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
 
     /* Update the console leader information held by the window */
-    SetConsoleWndConsoleLeaderCID(GuiData);
+    SetConWndConsoleLeaderCID(GuiData);
 
     /*
      * HACK:
@@ -2785,16 +864,16 @@ GuiRefreshInternalInfo(IN OUT PFRONTEND This)
 static VOID NTAPI
 GuiChangeTitle(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     // PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0);
-    SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
+    SetWindowTextW(GuiData->hWindow, GuiData->Console->Title.Buffer);
 }
 
 static BOOL NTAPI
 GuiChangeIcon(IN OUT PFRONTEND This,
               HICON IconHandle)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     HICON hIcon, hIconSm;
 
     if (IconHandle == NULL)
@@ -2809,9 +888,7 @@ GuiChangeIcon(IN OUT PFRONTEND This,
     }
 
     if (hIcon == NULL)
-    {
         return FALSE;
-    }
 
     if (hIcon != GuiData->hIcon)
     {
@@ -2828,7 +905,7 @@ GuiChangeIcon(IN OUT PFRONTEND This,
         GuiData->hIconSm = hIconSm;
 
         DPRINT("Set icons in GuiChangeIcon\n");
-        PostMessageW(GuiData->hWindow, WM_SETICON, ICON_BIG, (LPARAM)GuiData->hIcon);
+        PostMessageW(GuiData->hWindow, WM_SETICON, ICON_BIG  , (LPARAM)GuiData->hIcon  );
         PostMessageW(GuiData->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)GuiData->hIconSm);
     }
 
@@ -2838,7 +915,7 @@ GuiChangeIcon(IN OUT PFRONTEND This,
 static HWND NTAPI
 GuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     return GuiData->hWindow;
 }
 
@@ -2846,43 +923,77 @@ static VOID NTAPI
 GuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
                                PCOORD pSize)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     PCONSOLE_SCREEN_BUFFER ActiveBuffer;
-    RECT WorkArea;
-    LONG width, height;
+    HMONITOR hMonitor;
+    MONITORINFO MonitorInfo;
+    LONG Width, Height;
     UINT WidthUnit, HeightUnit;
 
     if (!pSize) return;
 
-    if (!SystemParametersInfoW(SPI_GETWORKAREA, 0, &WorkArea, 0))
+    /*
+     * Retrieve the monitor that is mostly covered by the current console window;
+     * default to primary monitor otherwise.
+     */
+    MonitorInfo.cbSize = sizeof(MonitorInfo);
+    hMonitor = MonitorFromWindow(GuiData->hWindow, MONITOR_DEFAULTTOPRIMARY);
+    if (hMonitor && GetMonitorInfoW(hMonitor, &MonitorInfo))
+    {
+        /* Retrieve the width and height of the client area of this monitor */
+        Width  = MonitorInfo.rcWork.right - MonitorInfo.rcWork.left;
+        Height = MonitorInfo.rcWork.bottom - MonitorInfo.rcWork.top;
+    }
+    else
     {
-        DPRINT1("SystemParametersInfoW failed - What to do ??\n");
-        return;
+        /*
+         * Retrieve the width and height of the client area for a full-screen
+         * window on the primary display monitor.
+         */
+        Width  = GetSystemMetrics(SM_CXFULLSCREEN);
+        Height = GetSystemMetrics(SM_CYFULLSCREEN);
+
+        // RECT WorkArea;
+        // SystemParametersInfoW(SPI_GETWORKAREA, 0, &WorkArea, 0);
+        // Width  = WorkArea.right;
+        // Height = WorkArea.bottom;
     }
 
     ActiveBuffer = GuiData->ActiveBuffer;
+#if 0
+    // NOTE: This would be surprising if we wouldn't have an associated buffer...
     if (ActiveBuffer)
-    {
+#endif
         GetScreenBufferSizeUnits(ActiveBuffer, GuiData, &WidthUnit, &HeightUnit);
-    }
+#if 0
     else
-    {
-        /* Default: text mode */
-        WidthUnit  = GuiData->CharWidth ;
-        HeightUnit = GuiData->CharHeight;
-    }
+        /* Default: graphics mode */
+        WidthUnit = HeightUnit = 1;
+#endif
 
-    width  = WorkArea.right;
-    height = WorkArea.bottom;
+    Width  -= (2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)));
+    Height -= (2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION));
 
-    width  -= (2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)));
-    height -= (2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION));
+    if (Width  < 0) Width  = 0;
+    if (Height < 0) Height = 0;
 
-    if (width  < 0) width  = 0;
-    if (height < 0) height = 0;
+    pSize->X = (SHORT)(Width  / (int)WidthUnit ) /* HACK */ + 2;
+    pSize->Y = (SHORT)(Height / (int)HeightUnit) /* HACK */ + 1;
+}
+
+static BOOL NTAPI
+GuiGetSelectionInfo(IN OUT PFRONTEND This,
+                    PCONSOLE_SELECTION_INFO pSelectionInfo)
+{
+    PGUI_CONSOLE_DATA GuiData = This->Context;
 
-    pSize->X = (SHORT)(width  / (int)WidthUnit ) /* HACK */ + 2;
-    pSize->Y = (SHORT)(height / (int)HeightUnit) /* HACK */ + 1;
+    if (pSelectionInfo == NULL) return FALSE;
+
+    ZeroMemory(pSelectionInfo, sizeof(*pSelectionInfo));
+    if (GuiData->Selection.dwFlags != CONSOLE_NO_SELECTION)
+        RtlCopyMemory(pSelectionInfo, &GuiData->Selection, sizeof(*pSelectionInfo));
+
+    return TRUE;
 }
 
 static BOOL NTAPI
@@ -2890,7 +1001,7 @@ GuiSetPalette(IN OUT PFRONTEND This,
               HPALETTE PaletteHandle,
               UINT PaletteUsage)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     HPALETTE OldPalette;
 
     // if (GetType(GuiData->ActiveBuffer) != GRAPHICS_BUFFER) return FALSE;
@@ -2915,7 +1026,7 @@ GuiSetPalette(IN OUT PFRONTEND This,
 static ULONG NTAPI
 GuiGetDisplayMode(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     ULONG DisplayMode = 0;
 
     if (GuiData->GuiInfo.FullScreen)
@@ -2930,12 +1041,15 @@ static BOOL NTAPI
 GuiSetDisplayMode(IN OUT PFRONTEND This,
                   ULONG NewMode)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     BOOL FullScreen;
 
     if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
         return FALSE;
 
+    /* Do nothing if the window is hidden */
+    if (!GuiData->IsWindowVisible) return TRUE;
+
     FullScreen = ((NewMode & CONSOLE_FULLSCREEN_MODE) != 0);
 
     if (FullScreen != GuiData->GuiInfo.FullScreen)
@@ -2950,14 +1064,17 @@ static INT NTAPI
 GuiShowMouseCursor(IN OUT PFRONTEND This,
                    BOOL Show)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
 
-    /* Set the reference count */
-    if (Show) ++GuiData->MouseCursorRefCount;
-    else      --GuiData->MouseCursorRefCount;
+    if (GuiData->IsWindowVisible)
+    {
+        /* Set the reference count */
+        if (Show) ++GuiData->MouseCursorRefCount;
+        else      --GuiData->MouseCursorRefCount;
 
-    /* Effectively show (or hide) the cursor (use special values for (w|l)Param) */
-    PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
+        /* Effectively show (or hide) the cursor (use special values for (w|l)Param) */
+        PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
+    }
 
     return GuiData->MouseCursorRefCount;
 }
@@ -2966,7 +1083,10 @@ static BOOL NTAPI
 GuiSetMouseCursor(IN OUT PFRONTEND This,
                   HCURSOR CursorHandle)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
+
+    /* Do nothing if the window is hidden */
+    if (!GuiData->IsWindowVisible) return TRUE;
 
     /*
      * Set the cursor's handle. If the given handle is NULL,
@@ -2985,7 +1105,7 @@ GuiMenuControl(IN OUT PFRONTEND This,
                UINT CmdIdLow,
                UINT CmdIdHigh)
 {
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
 
     GuiData->CmdIdLow  = CmdIdLow ;
     GuiData->CmdIdHigh = CmdIdHigh;
@@ -3003,7 +1123,7 @@ GuiSetMenuClose(IN OUT PFRONTEND This,
      * for more information.
      */
 
-    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PGUI_CONSOLE_DATA GuiData = This->Context;
     HMENU hSysMenu = GetSystemMenu(GuiData->hWindow, FALSE);
 
     if (hSysMenu == NULL) return FALSE;
@@ -3020,17 +1140,18 @@ static FRONTEND_VTBL GuiVtbl =
     GuiDeinitFrontEnd,
     GuiDrawRegion,
     GuiWriteStream,
+    GuiRingBell,
     GuiSetCursorInfo,
     GuiSetScreenInfo,
     GuiResizeTerminal,
     GuiSetActiveScreenBuffer,
     GuiReleaseScreenBuffer,
-    GuiProcessKeyCallback,
     GuiRefreshInternalInfo,
     GuiChangeTitle,
     GuiChangeIcon,
     GuiGetConsoleWindowHandle,
     GuiGetLargestConsoleWindowSize,
+    GuiGetSelectionInfo,
     GuiSetPalette,
     GuiGetDisplayMode,
     GuiSetDisplayMode,
@@ -3041,155 +1162,132 @@ static FRONTEND_VTBL GuiVtbl =
 };
 
 
-static BOOL
-LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
-                         IN OUT PCONSOLE_INFO ConsoleInfo)
+NTSTATUS NTAPI
+GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+                IN OUT PCONSOLE_STATE_INFO ConsoleInfo,
+                IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
+                IN HANDLE ConsoleLeaderProcessHandle)
 {
-#define PATH_SEPARATOR L'\\'
+    PCONSOLE_START_INFO ConsoleStartInfo;
+    PGUI_INIT_INFO GuiInitInfo;
+    USEROBJECTFLAGS UserObjectFlags;
 
-    BOOL    RetVal   = FALSE;
-    HRESULT hRes     = S_OK;
-    LPWSTR  LinkName = NULL;
-    SIZE_T  Length   = 0;
+    if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL)
+        return STATUS_INVALID_PARAMETER;
 
-    if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
-        return FALSE;
+    ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo;
 
-    ConsoleStartInfo->IconPath[0] = L'\0';
-    ConsoleStartInfo->IconIndex   = 0;
+    /*
+     * Initialize a private initialization info structure for later use.
+     * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
+     */
+    GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiInitInfo));
+    if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
 
-    /* 1- Find the last path separator if any */
-    LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
-    if (LinkName == NULL)
+    /* Initialize GUI terminal emulator common functionalities */
+    if (!GuiInit(ConsoleInitInfo, ConsoleLeaderProcessHandle, GuiInitInfo))
     {
-        LinkName = ConsoleStartInfo->ConsoleTitle;
+        ConsoleFreeHeap(GuiInitInfo);
+        return STATUS_UNSUCCESSFUL;
     }
-    else
+
+    GuiInitInfo->IsWindowVisible = ConsoleInitInfo->IsWindowVisible;
+    if (GuiInitInfo->IsWindowVisible)
     {
-        /* Skip the path separator */
-        ++LinkName;
+        /* Don't show the console if the window station is not interactive */
+        if (GetUserObjectInformationW(GuiInitInfo->WinSta,
+                                      UOI_FLAGS,
+                                      &UserObjectFlags,
+                                      sizeof(UserObjectFlags),
+                                      NULL))
+        {
+            if (!(UserObjectFlags.dwFlags & WSF_VISIBLE))
+                GuiInitInfo->IsWindowVisible = FALSE;
+        }
     }
 
-    /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
-    Length = wcslen(LinkName);
-    if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
-        return FALSE;
+    /*
+     * Load terminal settings
+     */
+#if 0
+    /* Impersonate the caller in order to retrieve settings in its context */
+    // if (!CsrImpersonateClient(NULL))
+        // return STATUS_UNSUCCESSFUL;
+    CsrImpersonateClient(NULL);
+
+    /* 1. Load the default settings */
+    GuiConsoleGetDefaultSettings(&GuiInitInfo->TermInfo);
+#endif
 
-    /* 3- It may be a link. Try to retrieve some properties */
-    hRes = CoInitialize(NULL);
-    if (SUCCEEDED(hRes))
+    GuiInitInfo->TermInfo.ShowWindow = SW_SHOWNORMAL;
+
+    if (GuiInitInfo->IsWindowVisible)
     {
-        /* Get a pointer to the IShellLink interface */
-        IShellLinkW* pshl = NULL;
-        hRes = CoCreateInstance(&CLSID_ShellLink,
-                                NULL, 
-                                CLSCTX_INPROC_SERVER,
-                                &IID_IShellLinkW,
-                                (LPVOID*)&pshl);
-        if (SUCCEEDED(hRes))
+        /* 2. Load the remaining console settings via the registry */
+        if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
         {
-            /* Get a pointer to the IPersistFile interface */
-            IPersistFile* ppf = NULL;
-            hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
-            if (SUCCEEDED(hRes))
+#if 0
+            /* Load the terminal infos from the registry */
+            GuiConsoleReadUserSettings(&GuiInitInfo->TermInfo);
+#endif
+
+            /*
+             * Now, update them with the properties the user might gave to us
+             * via the STARTUPINFO structure before calling CreateProcess
+             * (and which was transmitted via the ConsoleStartInfo structure).
+             * We therefore overwrite the values read in the registry.
+             */
+            if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW)
             {
-                /* Load the shortcut */
-                hRes = IPersistFile_Load(ppf, ConsoleStartInfo->ConsoleTitle, STGM_READ);
-                if (SUCCEEDED(hRes))
-                {
-                    /*
-                     * Finally we can get the properties !
-                     * Update the old ones if needed.
-                     */
-                    INT ShowCmd = 0;
-                    // WORD HotKey = 0;
-
-                    /* Reset the name of the console with the name of the shortcut */
-                    Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
-                                 sizeof(ConsoleInfo->ConsoleTitle) / sizeof(ConsoleInfo->ConsoleTitle[0]) - 1);
-                    wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
-                    ConsoleInfo->ConsoleTitle[Length] = L'\0';
-
-                    /* Get the window showing command */
-                    hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
-                    if (SUCCEEDED(hRes)) ConsoleStartInfo->wShowWindow = (WORD)ShowCmd;
-
-                    /* Get the hotkey */
-                    // hRes = pshl->GetHotkey(&ShowCmd);
-                    // if (SUCCEEDED(hRes)) ConsoleStartInfo->HotKey = HotKey;
-
-                    /* Get the icon location, if any */
-
-                    hRes = IShellLinkW_GetIconLocation(pshl,
-                                                       ConsoleStartInfo->IconPath,
-                                                       sizeof(ConsoleStartInfo->IconPath)/sizeof(ConsoleStartInfo->IconPath[0]) - 1, // == MAX_PATH
-                                                       &ConsoleStartInfo->IconIndex);
-                    if (!SUCCEEDED(hRes))
-                    {
-                        ConsoleStartInfo->IconPath[0] = L'\0';
-                        ConsoleStartInfo->IconIndex   = 0;
-                    }
-
-                    // FIXME: Since we still don't load console properties from the shortcut,
-                    // return false. When this will be done, we will return true instead.
-                    RetVal = FALSE;
-                }
-                IPersistFile_Release(ppf);
+                GuiInitInfo->TermInfo.ShowWindow = ConsoleStartInfo->wShowWindow;
+            }
+            if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
+            {
+                ConsoleInfo->AutoPosition = FALSE;
+                ConsoleInfo->WindowPosition.x = ConsoleStartInfo->dwWindowOrigin.X;
+                ConsoleInfo->WindowPosition.y = ConsoleStartInfo->dwWindowOrigin.Y;
+            }
+            if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
+            {
+                ConsoleInfo->FullScreen = TRUE;
             }
-            IShellLinkW_Release(pshl);
         }
     }
-    CoUninitialize();
-
-    return RetVal;
-}
 
-NTSTATUS NTAPI
-GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
-                IN OUT PCONSOLE_INFO ConsoleInfo,
-                IN OUT PVOID ExtraConsoleInfo,
-                IN ULONG ProcessId)
-{
-    PCONSOLE_START_INFO ConsoleStartInfo = ExtraConsoleInfo;
-    PGUI_INIT_INFO GuiInitInfo;
+#if 0
+    /* Revert impersonation */
+    CsrRevertToSelf();
+#endif
 
-    if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleStartInfo == NULL)
-        return STATUS_INVALID_PARAMETER;
+    // Font data
+    StringCchCopyNW(GuiInitInfo->TermInfo.FaceName, ARRAYSIZE(GuiInitInfo->TermInfo.FaceName),
+                    ConsoleInfo->FaceName, ARRAYSIZE(ConsoleInfo->FaceName));
+    GuiInitInfo->TermInfo.FontFamily = ConsoleInfo->FontFamily;
+    GuiInitInfo->TermInfo.FontSize   = ConsoleInfo->FontSize;
+    GuiInitInfo->TermInfo.FontWeight = ConsoleInfo->FontWeight;
 
-    /* Initialize GUI terminal emulator common functionalities */
-    if (!GuiInit()) return STATUS_UNSUCCESSFUL;
+    // Display
+    GuiInitInfo->TermInfo.FullScreen   = ConsoleInfo->FullScreen;
+    GuiInitInfo->TermInfo.AutoPosition = ConsoleInfo->AutoPosition;
+    GuiInitInfo->TermInfo.WindowOrigin = ConsoleInfo->WindowPosition;
 
-    /*
-     * Load per-application terminal settings.
-     *
-     * Check whether the process creating the console was launched via
-     * a shell-link. ConsoleInfo->ConsoleTitle may be updated with the
-     * name of the shortcut, and ConsoleStartInfo->Icon[Path|Index] too.
-     */
-    if (ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)
-    {
-        if (!LoadShellLinkConsoleInfo(ConsoleStartInfo, ConsoleInfo))
-        {
-            ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
-        }
-    }
+    /* Initialize the icon handles */
+    // if (ConsoleStartInfo->hIcon != NULL)
+        GuiInitInfo->hIcon = ConsoleStartInfo->hIcon;
+    // else
+        // GuiInitInfo->hIcon = ghDefaultIcon;
 
-    /*
-     * Initialize a private initialization info structure for later use.
-     * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
-     */
-    GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_INIT_INFO));
-    if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
+    // if (ConsoleStartInfo->hIconSm != NULL)
+        GuiInitInfo->hIconSm = ConsoleStartInfo->hIconSm;
+    // else
+        // GuiInitInfo->hIconSm = ghDefaultIconSm;
 
-    // HACK: We suppose that the pointers will be valid in GuiInitFrontEnd...
-    GuiInitInfo->ConsoleInfo      = ConsoleInfo;
-    GuiInitInfo->ConsoleStartInfo = ConsoleStartInfo;
-    GuiInitInfo->ProcessId        = ProcessId;
+    // ASSERT(GuiInitInfo->hIcon && GuiInitInfo->hIconSm);
 
     /* Finally, initialize the frontend structure */
-    FrontEnd->Vtbl    = &GuiVtbl;
-    FrontEnd->Data    = NULL;
-    FrontEnd->OldData = GuiInitInfo;
+    FrontEnd->Vtbl     = &GuiVtbl;
+    FrontEnd->Context  = NULL;
+    FrontEnd->Context2 = GuiInitInfo;
 
     return STATUS_SUCCESS;
 }
@@ -3199,8 +1297,8 @@ GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
 {
     if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
 
-    if (FrontEnd->Data)    GuiDeinitFrontEnd(FrontEnd);
-    if (FrontEnd->OldData) ConsoleFreeHeap(FrontEnd->OldData);
+    if (FrontEnd->Context ) GuiDeinitFrontEnd(FrontEnd);
+    if (FrontEnd->Context2) ConsoleFreeHeap(FrontEnd->Context2);
 
     return STATUS_SUCCESS;
 }