[CONSRV]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 23 Jun 2013 00:18:47 +0000 (00:18 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 23 Jun 2013 00:18:47 +0000 (00:18 +0000)
Start to separate better the CSR console server layer from the pure set of console functions (which will constitute a future console driver called... condrv :) ), and rework the terminal frontends interface.
Now load the frontends by order :
- the tui if we're in console mode
- the gui, otherwise.
(It's a temporary solution)
More modifications to come !

svn path=/trunk/; revision=59297

18 files changed:
reactos/win32ss/user/consrv/CMakeLists.txt
reactos/win32ss/user/consrv/condrv/console.c [new file with mode: 0644]
reactos/win32ss/user/consrv/condrv/graphics.c [moved from reactos/win32ss/user/consrv/graphics.c with 100% similarity]
reactos/win32ss/user/consrv/coninput.c
reactos/win32ss/user/consrv/coninput.h
reactos/win32ss/user/consrv/conio.h
reactos/win32ss/user/consrv/conoutput.c
reactos/win32ss/user/consrv/conoutput.h
reactos/win32ss/user/consrv/console.c
reactos/win32ss/user/consrv/console.h
reactos/win32ss/user/consrv/frontendctl.c [new file with mode: 0644]
reactos/win32ss/user/consrv/frontends/gui/guiterm.c
reactos/win32ss/user/consrv/frontends/input.c [new file with mode: 0644]
reactos/win32ss/user/consrv/frontends/tui/tuiterm.c
reactos/win32ss/user/consrv/handle.c
reactos/win32ss/user/consrv/include/conio.h
reactos/win32ss/user/consrv/include/console.h
reactos/win32ss/user/consrv/init.c

index ca5fae6..40432db 100644 (file)
@@ -12,13 +12,16 @@ list(APPEND SOURCE
     alias.c
     coninput.c
     conoutput.c
-    graphics.c
     text.c
     console.c
+    frontendctl.c
     handle.c
     init.c
     lineinput.c
     settings.c
+    condrv/console.c
+    condrv/graphics.c
+    frontends/input.c
     frontends/gui/guiterm.c
     frontends/gui/guisettings.c
     frontends/gui/graphics.c
diff --git a/reactos/win32ss/user/consrv/condrv/console.c b/reactos/win32ss/user/consrv/condrv/console.c
new file mode 100644 (file)
index 0000000..80fdda8
--- /dev/null
@@ -0,0 +1,984 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Console Server DLL
+ * FILE:            win32ss/user/consrv/condrv/console.c
+ * PURPOSE:         Console Management Functions
+ * PROGRAMMERS:     Gé van Geldorp
+ *                  Jeffrey Morlan
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "handle.h"
+#include "procinit.h"
+#include "alias.h"
+#include "coninput.h"
+#include "conoutput.h"
+#include "lineinput.h"
+#include "include/settings.h"
+
+#include "include/console.h"
+#include "console.h"
+#include "resource.h"
+
+#define NDEBUG
+#include <debug.h>
+
+// FIXME: Add this prototype to winternl.h / rtlfuncs.h / ...
+NTSTATUS NTAPI RtlGetLastNtStatus(VOID);
+
+
+/* GLOBALS ********************************************************************/
+
+static LIST_ENTRY ConsoleList;  /* The list of all the allocated consoles */
+static RTL_RESOURCE ListLock;
+
+#define ConDrvLockConsoleListExclusive()    \
+    RtlAcquireResourceExclusive(&ListLock, TRUE)
+
+#define ConDrvLockConsoleListShared()       \
+    RtlAcquireResourceShared(&ListLock, TRUE)
+
+#define ConDrvUnlockConsoleList()           \
+    RtlReleaseResource(&ListLock)
+
+// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
+BOOLEAN
+ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest,
+                           IN PCWSTR Source)
+{
+    SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR);
+    if (Size > MAXUSHORT) return FALSE;
+
+    UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size);
+    if (UniDest->Buffer == NULL) return FALSE;
+
+    RtlCopyMemory(UniDest->Buffer, Source, Size);
+    UniDest->MaximumLength = (USHORT)Size;
+    UniDest->Length = (USHORT)Size - sizeof(WCHAR);
+
+    return TRUE;
+}
+
+// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431
+VOID
+ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
+{
+    if (UnicodeString->Buffer)
+    {
+        ConsoleFreeHeap(UnicodeString->Buffer);
+        RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
+    }
+}
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static NTSTATUS
+ConDrvConsoleCtrlEventTimeout(IN ULONG Event,
+                              IN PCONSOLE_PROCESS_DATA ProcessData,
+                              IN ULONG Timeout)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("ConDrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
+
+    if (ProcessData->CtrlDispatcher)
+    {
+        _SEH2_TRY
+        {
+            HANDLE Thread = NULL;
+
+            _SEH2_TRY
+            {
+                Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
+                                            ProcessData->CtrlDispatcher,
+                                            UlongToPtr(Event), 0, NULL);
+                if (NULL == Thread)
+                {
+                    Status = RtlGetLastNtStatus();
+                    DPRINT1("Failed thread creation, Status = 0x%08lx\n", Status);
+                }
+                else
+                {
+                    DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
+                    WaitForSingleObject(Thread, Timeout);
+                }
+            }
+            _SEH2_FINALLY
+            {
+                CloseHandle(Thread);
+            }
+            _SEH2_END;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+            DPRINT1("ConDrvConsoleCtrlEventTimeout - Caught an exception, Status = 0x%08lx\n", Status);
+        }
+        _SEH2_END;
+    }
+
+    return Status;
+}
+
+static NTSTATUS
+ConDrvConsoleCtrlEvent(IN ULONG Event,
+                       IN PCONSOLE_PROCESS_DATA ProcessData)
+{
+    return ConDrvConsoleCtrlEventTimeout(Event, ProcessData, 0);
+}
+
+VOID FASTCALL
+ConioPause(PCONSOLE Console, UINT Flags)
+{
+    Console->PauseFlags |= Flags;
+    if (!Console->UnpauseEvent)
+        Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+}
+
+VOID FASTCALL
+ConioUnpause(PCONSOLE Console, UINT Flags)
+{
+    Console->PauseFlags &= ~Flags;
+
+    // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
+    if (Console->PauseFlags == 0 && Console->UnpauseEvent)
+    {
+        SetEvent(Console->UnpauseEvent);
+        CloseHandle(Console->UnpauseEvent);
+        Console->UnpauseEvent = NULL;
+
+        CsrNotifyWait(&Console->WriteWaitQueue,
+                      WaitAll,
+                      NULL,
+                      NULL);
+        if (!IsListEmpty(&Console->WriteWaitQueue))
+        {
+            CsrDereferenceWait(&Console->WriteWaitQueue);
+        }
+    }
+}
+
+
+/*
+ * Console accessibility check helpers
+ */
+
+BOOLEAN NTAPI
+ConDrvValidateConsolePointer(IN PCONSOLE Console)
+{
+    PLIST_ENTRY ConsoleEntry;
+    PCONSOLE CurrentConsole = NULL;
+
+    if (!Console) return FALSE;
+
+    /* The console list must be locked */
+    // ASSERT(Console_list_locked);
+
+    ConsoleEntry = ConsoleList.Flink;
+    while (ConsoleEntry != &ConsoleList)
+    {
+        CurrentConsole = CONTAINING_RECORD(ConsoleEntry, CONSOLE, Entry);
+        ConsoleEntry = ConsoleEntry->Flink;
+        if (CurrentConsole == Console) return TRUE;
+    }
+
+    return FALSE;
+}
+
+BOOLEAN NTAPI
+ConDrvValidateConsoleState(IN PCONSOLE Console,
+                           IN CONSOLE_STATE ExpectedState)
+{
+    // if (!Console) return FALSE;
+
+    /* The console must be locked */
+    // ASSERT(Console_locked);
+
+    return (Console->State == ExpectedState);
+}
+
+BOOLEAN NTAPI
+ConDrvValidateConsoleUnsafe(IN PCONSOLE Console,
+                            IN CONSOLE_STATE ExpectedState,
+                            IN BOOLEAN LockConsole)
+{
+    if (!Console) return FALSE;
+
+    /*
+     * Lock the console to forbid possible console's state changes
+     * (which must be done when the console is already locked).
+     * If we don't want to lock it, it's because the lock is already
+     * held. So there must be no problems.
+     */
+    if (LockConsole) EnterCriticalSection(&Console->Lock);
+
+    // ASSERT(Console_locked);
+
+    /* Check whether the console's state is what we expect */
+    if (!ConDrvValidateConsoleState(Console, ExpectedState))
+    {
+        if (LockConsole) LeaveCriticalSection(&Console->Lock);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+BOOLEAN NTAPI
+ConDrvValidateConsole(IN PCONSOLE Console,
+                      IN CONSOLE_STATE ExpectedState,
+                      IN BOOLEAN LockConsole)
+{
+    BOOLEAN RetVal = FALSE;
+
+    if (!Console) return FALSE;
+
+    /*
+     * Forbid creation or deletion of consoles when
+     * checking for the existence of a console.
+     */
+    ConDrvLockConsoleListShared();
+
+    if (ConDrvValidateConsolePointer(Console))
+    {
+        RetVal = ConDrvValidateConsoleUnsafe(Console,
+                                             ExpectedState,
+                                             LockConsole);
+    }
+
+    /* Unlock the console list and return */
+    ConDrvUnlockConsoleList();
+    return RetVal;
+}
+
+NTSTATUS NTAPI
+ConDrvGrabConsole(IN PCONSOLE Console,
+                  IN BOOLEAN LockConsole)
+{
+    NTSTATUS Status = STATUS_INVALID_HANDLE;
+
+    if (ConDrvValidateConsole(Console, CONSOLE_RUNNING, LockConsole))
+    {
+        InterlockedIncrement(&Console->ReferenceCount);
+        Status = STATUS_SUCCESS;
+    }
+
+    return Status;
+}
+
+VOID NTAPI
+ConDrvReleaseConsole(IN PCONSOLE Console,
+                     IN BOOLEAN WasConsoleLocked)
+{
+    LONG RefCount = 0;
+
+    if (!Console) return;
+    // if (Console->ReferenceCount == 0) return; // This shouldn't happen
+    ASSERT(Console->ReferenceCount > 0);
+
+    /* The console must be locked */
+    // ASSERT(Console_locked);
+
+    /*
+     * Decrement the reference count. Save the new value too,
+     * because Console->ReferenceCount might be modified after
+     * the console gets unlocked but before we check whether we
+     * can destroy it.
+     */
+    RefCount = _InterlockedDecrement(&Console->ReferenceCount);
+
+    /* Unlock the console if needed */
+    if (WasConsoleLocked) LeaveCriticalSection(&Console->Lock);
+
+    /* Delete the console if needed */
+    if (RefCount <= 0) ConDrvDeleteConsole(Console);
+}
+
+
+/* CONSOLE INITIALIZATION FUNCTIONS *******************************************/
+
+VOID NTAPI
+ConDrvInitConsoleSupport(VOID)
+{
+    DPRINT("CONSRV: ConDrvInitConsoleSupport()\n");
+
+    /* Initialize the console list and its lock */
+    InitializeListHead(&ConsoleList);
+    RtlInitializeResource(&ListLock);
+
+    /* Should call LoadKeyboardLayout */
+}
+
+
+NTSTATUS NTAPI
+ConDrvInitConsole(OUT PCONSOLE* NewConsole,
+                  IN PCONSOLE_INFO ConsoleInfo,
+                  IN ULONG ConsoleLeaderProcessId)
+{
+    NTSTATUS Status;
+    SECURITY_ATTRIBUTES SecurityAttributes;
+    // CONSOLE_INFO CapturedConsoleInfo;
+    TEXTMODE_BUFFER_INFO ScreenBufferInfo;
+    PCONSOLE Console;
+    PCONSOLE_SCREEN_BUFFER NewBuffer;
+    // WCHAR DefaultTitle[128];
+
+    if (NewConsole == NULL || ConsoleInfo == NULL)
+        return STATUS_INVALID_PARAMETER;
+    
+    *NewConsole = NULL;
+
+    /*
+     * Allocate a console structure
+     */
+    Console = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(CONSOLE));
+    if (NULL == Console)
+    {
+        DPRINT1("Not enough memory for console creation.\n");
+        return STATUS_NO_MEMORY;
+    }
+
+    /*
+     * Load the console settings
+     */
+
+    /* 1. Load the default settings */
+    // ConSrvGetDefaultSettings(ConsoleInfo, ProcessId);
+
+    // /* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */
+    // Length = min(wcslen(ConsoleStartInfo->ConsoleTitle),
+                 // sizeof(ConsoleInfo.ConsoleTitle) / sizeof(ConsoleInfo.ConsoleTitle[0]) - 1);
+    // wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length);
+    // ConsoleInfo.ConsoleTitle[Length] = L'\0';
+
+    /*
+     * 4. Load the remaining console settings via the registry.
+     */
+#if 0
+    if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+    {
+        /*
+         * Either we weren't created by an app launched via a shell-link,
+         * or we failed to load shell-link console properties.
+         * Therefore, load the console infos for the application from the registry.
+         */
+        ConSrvReadUserSettings(ConsoleInfo, 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_USEFILLATTRIBUTE)
+        {
+            ConsoleInfo->ScreenAttrib = (USHORT)ConsoleStartInfo->FillAttribute;
+        }
+        if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
+        {
+            ConsoleInfo->ScreenBufferSize = ConsoleStartInfo->ScreenBufferSize;
+        }
+        if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
+        {
+            // ConsoleInfo->ConsoleSize = ConsoleStartInfo->ConsoleWindowSize;
+            ConsoleInfo->ConsoleSize.X = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cx;
+            ConsoleInfo->ConsoleSize.Y = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cy;
+        }
+    }
+#endif
+
+    /*
+     * Fix the screen buffer size if needed. The rule is:
+     * ScreenBufferSize >= ConsoleSize
+     */
+    if (ConsoleInfo->ScreenBufferSize.X < ConsoleInfo->ConsoleSize.X)
+        ConsoleInfo->ScreenBufferSize.X = ConsoleInfo->ConsoleSize.X;
+    if (ConsoleInfo->ScreenBufferSize.Y < ConsoleInfo->ConsoleSize.Y)
+        ConsoleInfo->ScreenBufferSize.Y = ConsoleInfo->ConsoleSize.Y;
+
+    /*
+     * Initialize the console
+     */
+    Console->State = CONSOLE_INITIALIZING;
+    Console->ReferenceCount = 0;
+    InitializeCriticalSection(&Console->Lock);
+    InitializeListHead(&Console->ProcessList);
+    RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
+
+    memcpy(Console->Colors, ConsoleInfo->Colors, sizeof(ConsoleInfo->Colors));
+    Console->ConsoleSize = ConsoleInfo->ConsoleSize;
+    Console->FixedSize   = FALSE; // Value by default; is reseted by the front-ends if needed.
+
+    /*
+     * Initialize the input buffer
+     */
+    ConSrvInitObject(&Console->InputBuffer.Header, INPUT_BUFFER, Console);
+
+    SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+    SecurityAttributes.lpSecurityDescriptor = NULL;
+    SecurityAttributes.bInheritHandle = TRUE;
+    Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
+    if (NULL == Console->InputBuffer.ActiveEvent)
+    {
+        DeleteCriticalSection(&Console->Lock);
+        ConsoleFreeHeap(Console);
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    Console->InputBuffer.InputBufferSize = 0; // FIXME!
+    InitializeListHead(&Console->InputBuffer.InputEvents);
+    InitializeListHead(&Console->InputBuffer.ReadWaitQueue);
+    Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
+                                ENABLE_ECHO_INPUT      | ENABLE_MOUSE_INPUT;
+
+    Console->QuickEdit  = ConsoleInfo->QuickEdit;
+    Console->InsertMode = ConsoleInfo->InsertMode;
+    Console->LineBuffer = NULL;
+    Console->LineMaxSize = Console->LineSize = Console->LinePos = 0;
+    Console->LineComplete = Console->LineUpPressed = Console->LineInsertToggle = FALSE;
+    // LineWakeupMask
+
+    // FIXME: This is terminal-specific !! VV
+    RtlZeroMemory(&Console->Selection, sizeof(CONSOLE_SELECTION_INFO));
+    Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
+    // dwSelectionCursor
+
+    /* Set-up the code page */
+    Console->CodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
+
+    /* Initialize a new text-mode screen buffer with default settings */
+    ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
+    ScreenBufferInfo.ScreenAttrib     = ConsoleInfo->ScreenAttrib;
+    ScreenBufferInfo.PopupAttrib      = ConsoleInfo->PopupAttrib;
+    ScreenBufferInfo.IsCursorVisible  = TRUE;
+    ScreenBufferInfo.CursorSize       = ConsoleInfo->CursorSize;
+
+    InitializeListHead(&Console->BufferList);
+    Status = ConSrvCreateScreenBuffer(&NewBuffer,
+                                      Console,
+                                      CONSOLE_TEXTMODE_BUFFER,
+                                      &ScreenBufferInfo);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("ConSrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
+        CloseHandle(Console->InputBuffer.ActiveEvent);
+        DeleteCriticalSection(&Console->Lock);
+        ConsoleFreeHeap(Console);
+        return Status;
+    }
+    /* Make the new screen buffer active */
+    Console->ActiveBuffer = NewBuffer;
+    InitializeListHead(&Console->WriteWaitQueue);
+    Console->PauseFlags = 0;
+    Console->UnpauseEvent = NULL;
+
+    /*
+     * Initialize the alias and history buffers
+     */
+    Console->Aliases = NULL;
+    InitializeListHead(&Console->HistoryBuffers);
+    Console->HistoryBufferSize      = ConsoleInfo->HistoryBufferSize;
+    Console->NumberOfHistoryBuffers = ConsoleInfo->NumberOfHistoryBuffers;
+    Console->HistoryNoDup           = ConsoleInfo->HistoryNoDup;
+
+    /* Initialize the console title */
+    ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo->ConsoleTitle);
+    // if (ConsoleInfo.ConsoleTitle[0] == L'\0')
+    // {
+        // if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0])))
+        // {
+            // ConsoleCreateUnicodeString(&Console->Title, DefaultTitle);
+        // }
+        // else
+        // {
+            // ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console");
+        // }
+    // }
+    // else
+    // {
+        ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo->ConsoleTitle);
+    // }
+
+    /* Lock the console until its initialization is finished */
+    // EnterCriticalSection(&Console->Lock);
+
+    DPRINT("Console initialized\n");
+
+    /* All went right, so add the console to the list */
+    ConDrvLockConsoleListExclusive();
+    DPRINT("Insert in the list\n");
+    InsertTailList(&ConsoleList, &Console->Entry);
+
+    /* The initialization is finished */
+    DPRINT("Change state\n");
+    Console->State = CONSOLE_RUNNING;
+
+    /* Unlock the console */
+    // LeaveCriticalSection(&Console->Lock);
+
+    /* Unlock the console list */
+    ConDrvUnlockConsoleList();
+
+    /* Return the newly created console to the caller and a success code too */
+    *NewConsole = Console;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvRegisterFrontEnd(IN PCONSOLE Console,
+                       IN PFRONTEND FrontEnd)
+{
+    NTSTATUS Status;
+
+    if (Console == NULL || FrontEnd == NULL)
+        return STATUS_INVALID_PARAMETER;
+
+    /* FIXME: Lock the console before ?? */
+
+    /*
+     * Attach the frontend to the console. Use now the TermIFace of the console,
+     * and not the user-defined temporary FrontEnd pointer.
+     */
+    Console->TermIFace = *FrontEnd;
+    Console->TermIFace.Console = Console;
+
+    /* Initialize the frontend AFTER having attached it to the console */
+    DPRINT("Finish initialization of frontend\n");
+    Status = Console->TermIFace.Vtbl->InitFrontEnd(&Console->TermIFace, Console);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("FrontEnd initialization failed, Status = 0x%08lx\n", Status);
+
+        /* We failed, detach the frontend from the console */
+        FrontEnd->Console = NULL; // For the caller
+        RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
+
+        return Status;
+    }
+
+    /* Copy buffer contents to screen */
+    // FrontEnd.Draw();
+    // ConioDrawConsole(Console);
+    DPRINT("Console drawn\n");
+
+    DPRINT("Terminal FrontEnd initialization done\n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvDeregisterFrontEnd(IN PCONSOLE Console)
+{
+    if (Console == NULL) return STATUS_INVALID_PARAMETER;
+
+    /* FIXME: Lock the console before ?? */
+
+    /* Deinitialize the frontend BEFORE detaching it from the console */
+    Console->TermIFace.Vtbl->DeinitFrontEnd(&Console->TermIFace/*, Console*/);
+
+    /* Detach the frontend from the console */
+    RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
+
+    DPRINT("Terminal FrontEnd unregistered\n");
+    return STATUS_SUCCESS;
+}
+
+VOID NTAPI
+ConDrvDeleteConsole(IN PCONSOLE Console)
+{
+    DPRINT("ConDrvDeleteConsole(0x%p)\n", Console);
+
+    /*
+     * Forbid validation of any console by other threads
+     * during the deletion of this console.
+     */
+    ConDrvLockConsoleListExclusive();
+
+    /* Check the existence of the console, and if it's ok, continue */
+    if (!ConDrvValidateConsolePointer(Console))
+    {
+        /* Unlock the console list and return */
+        ConDrvUnlockConsoleList();
+        return;
+    }
+
+    /*
+     * If the console is already being destroyed
+     * (thus not running), just return.
+     */
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+    {
+        /* Unlock the console list and return */
+        ConDrvUnlockConsoleList();
+        return;
+    }
+
+    /*
+     * We are about to be destroyed. Signal it to other people
+     * so that they can terminate what they are doing, and that
+     * they cannot longer validate the console.
+     */
+    Console->State = CONSOLE_TERMINATING;
+
+    /*
+     * Allow other threads to finish their job: basically, unlock
+     * all other calls to EnterCriticalSection(&Console->Lock); by
+     * ConDrvValidateConsole(Unsafe) functions so that they just see
+     * that we are not in CONSOLE_RUNNING state anymore, or unlock
+     * other concurrent calls to ConDrvDeleteConsole so that they
+     * can see that we are in fact already deleting the console.
+     */
+    LeaveCriticalSection(&Console->Lock);
+    ConDrvUnlockConsoleList();
+
+    /* FIXME: Send a terminate message to all the processes owning this console */
+
+    /* Cleanup the UI-oriented part */
+    DPRINT("Deregister console\n");
+    ConDrvDeregisterFrontEnd(Console);
+    DPRINT("Console deregistered\n");
+
+    /***
+     * Check that the console is in terminating state before continuing
+     * (the cleanup code must not change the state of the console...
+     * ...unless to cancel console deletion ?).
+     ***/
+
+    ConDrvLockConsoleListExclusive();
+
+    /* Re-check the existence of the console, and if it's ok, continue */
+    if (!ConDrvValidateConsolePointer(Console))
+    {
+        /* Unlock the console list and return */
+        ConDrvUnlockConsoleList();
+        return;
+    }
+
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_TERMINATING, TRUE))
+    {
+        ConDrvUnlockConsoleList();
+        return;
+    }
+
+    /* We are now in destruction */
+    Console->State = CONSOLE_IN_DESTRUCTION;
+
+    /* Remove the console from the list */
+    RemoveEntryList(&Console->Entry);
+
+    /* We really delete the console. Reset the count to be sure. */
+    Console->ReferenceCount = 0;
+
+    /* Discard all entries in the input event queue */
+    PurgeInputBuffer(Console);
+
+    if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer);
+
+    IntDeleteAllAliases(Console);
+    HistoryDeleteBuffers(Console);
+
+    ConioDeleteScreenBuffer(Console->ActiveBuffer);
+    if (!IsListEmpty(&Console->BufferList))
+    {
+        DPRINT1("BUG: screen buffer list not empty\n");
+        ASSERT(FALSE);
+    }
+
+    /**/ CloseHandle(Console->InputBuffer.ActiveEvent); /**/
+    if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
+
+    ConsoleFreeUnicodeString(&Console->OriginalTitle);
+    ConsoleFreeUnicodeString(&Console->Title);
+
+    DPRINT("ConDrvDeleteConsole - Unlocking\n");
+    LeaveCriticalSection(&Console->Lock);
+    DPRINT("ConDrvDeleteConsole - Destroying lock\n");
+    DeleteCriticalSection(&Console->Lock);
+    DPRINT("ConDrvDeleteConsole - Lock destroyed ; freeing console\n");
+
+    ConsoleFreeHeap(Console);
+    DPRINT("ConDrvDeleteConsole - Console destroyed\n");
+
+    /* Unlock the console list and return */
+    ConDrvUnlockConsoleList();
+}
+
+
+/* PUBLIC SERVER APIS *********************************************************/
+
+NTSTATUS NTAPI
+ConDrvGetConsoleMode(IN PCONSOLE Console,
+                     IN PCONSOLE_IO_OBJECT Object,
+                     OUT PULONG ConsoleMode)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    if (Console == NULL || Object == NULL || ConsoleMode == NULL)
+        return STATUS_INVALID_PARAMETER;
+
+    /* Validity check */
+    ASSERT(Console == Object->Console);
+
+    /*** FIXME: */ *ConsoleMode = 0; /***/
+
+    if (INPUT_BUFFER == Object->Type)
+    {
+        PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
+
+        *ConsoleMode = InputBuffer->Mode;
+
+        if (Console->QuickEdit || Console->InsertMode)
+        {
+            // Windows does this, even if it's not documented on MSDN
+            *ConsoleMode |= ENABLE_EXTENDED_FLAGS;
+
+            if (Console->QuickEdit ) *ConsoleMode |= ENABLE_QUICK_EDIT_MODE;
+            if (Console->InsertMode) *ConsoleMode |= ENABLE_INSERT_MODE;
+        }
+    }
+    else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
+    {
+        PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
+        *ConsoleMode = Buffer->Mode;
+    }
+    else
+    {
+        Status = STATUS_INVALID_HANDLE;
+    }
+
+    return Status;
+}
+
+NTSTATUS NTAPI
+ConDrvSetConsoleMode(IN PCONSOLE Console,
+                     IN PCONSOLE_IO_OBJECT Object,
+                     IN ULONG ConsoleMode)
+{
+#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS   | ENABLE_INSERT_MODE  | ENABLE_QUICK_EDIT_MODE )
+#define CONSOLE_VALID_INPUT_MODES   ( ENABLE_PROCESSED_INPUT  | ENABLE_LINE_INPUT   | \
+                                      ENABLE_ECHO_INPUT       | ENABLE_WINDOW_INPUT | \
+                                      ENABLE_MOUSE_INPUT )
+#define CONSOLE_VALID_OUTPUT_MODES  ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
+
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    if (Console == NULL || Object == NULL)
+        return STATUS_INVALID_PARAMETER;
+
+    /* Validity check */
+    ASSERT(Console == Object->Console);
+
+    if (INPUT_BUFFER == Object->Type)
+    {
+        PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
+
+        DPRINT("SetConsoleMode(Input, %d)\n", ConsoleMode);
+
+        /*
+         * 1. Only the presence of valid mode flags is allowed.
+         */
+        if (ConsoleMode & ~(CONSOLE_VALID_INPUT_MODES | CONSOLE_VALID_CONTROL_MODES))
+        {
+            Status = STATUS_INVALID_PARAMETER;
+            goto Quit;
+        }
+
+        /*
+         * 2. If we use control mode flags without ENABLE_EXTENDED_FLAGS,
+         *    then consider the flags invalid.
+         *
+        if ( (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) &&
+             (ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0 )
+        {
+            Status = STATUS_INVALID_PARAMETER;
+            goto Quit;
+        }
+        */
+
+        /*
+         * 3. Now we can continue.
+         */
+        if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
+        {
+            Console->QuickEdit  = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
+            Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
+        }
+        InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
+    }
+    else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
+    {
+        PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
+
+        DPRINT("SetConsoleMode(Output, %d)\n", ConsoleMode);
+
+        if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
+        {
+            Status = STATUS_INVALID_PARAMETER;
+        }
+        else
+        {
+            Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
+        }
+    }
+    else
+    {
+        Status = STATUS_INVALID_HANDLE;
+    }
+
+Quit:
+    return Status;
+}
+
+NTSTATUS NTAPI
+ConDrvGetConsoleTitle(IN PCONSOLE Console,
+                      IN OUT PWCHAR Title,
+                      IN OUT PULONG BufLength)
+{
+    ULONG Length;
+
+    if (Console == NULL || Title == NULL || BufLength == NULL)
+        return STATUS_INVALID_PARAMETER;
+
+    /* Copy title of the console to the user title buffer */
+    if (*BufLength >= sizeof(WCHAR))
+    {
+        Length = min(*BufLength - sizeof(WCHAR), Console->Title.Length);
+        RtlCopyMemory(Title, Console->Title.Buffer, Length);
+        Title[Length / sizeof(WCHAR)] = L'\0';
+    }
+
+    *BufLength = Console->Title.Length;
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvSetConsoleTitle(IN PCONSOLE Console,
+                      IN PWCHAR Title,
+                      IN ULONG BufLength)
+{
+    PWCHAR Buffer;
+
+    if (Console == NULL || Title == NULL)
+        return STATUS_INVALID_PARAMETER;
+
+    /* Allocate a new buffer to hold the new title (NULL-terminated) */
+    Buffer = ConsoleAllocHeap(0, BufLength + sizeof(WCHAR));
+    if (!Buffer) return STATUS_NO_MEMORY;
+
+    /* Free the old title */
+    ConsoleFreeUnicodeString(&Console->Title);
+
+    /* Copy title to console */
+    Console->Title.Buffer = Buffer;
+    Console->Title.Length = BufLength;
+    Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
+    RtlCopyMemory(Console->Title.Buffer, Title, Console->Title.Length);
+    Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
+
+    // ConioChangeTitle(Console);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvGetConsoleCP(IN PCONSOLE Console,
+                   OUT PUINT CodePage,
+                   IN BOOLEAN InputCP)
+{
+    if (Console == NULL || CodePage == NULL)
+        return STATUS_INVALID_PARAMETER;
+
+    *CodePage = (InputCP ? Console->CodePage : Console->OutputCodePage);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvSetConsoleCP(IN PCONSOLE Console,
+                   IN UINT CodePage,
+                   IN BOOLEAN InputCP)
+{
+    if (Console == NULL || !IsValidCodePage(CodePage))
+        return STATUS_INVALID_PARAMETER;
+
+    if (InputCP)
+        Console->CodePage = CodePage;
+    else
+        Console->OutputCodePage = CodePage;
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvGetConsoleProcessList(IN PCONSOLE Console,
+                            IN OUT PULONG ProcessIdsList,
+                            IN ULONG MaxIdListItems,
+                            OUT PULONG ProcessIdsTotal)
+{
+    PCONSOLE_PROCESS_DATA current;
+    PLIST_ENTRY current_entry;
+
+    if (Console == NULL || ProcessIdsList == NULL || ProcessIdsTotal == NULL)
+        return STATUS_INVALID_PARAMETER;
+
+    *ProcessIdsTotal = 0;
+
+    for (current_entry = Console->ProcessList.Flink;
+         current_entry != &Console->ProcessList;
+         current_entry = current_entry->Flink)
+    {
+        current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
+        if (++(*ProcessIdsTotal) <= MaxIdListItems)
+        {
+            *ProcessIdsList++ = HandleToUlong(current->Process->ClientId.UniqueProcess);
+        }
+    }
+
+    return STATUS_SUCCESS;
+}
+
+// ConDrvGenerateConsoleCtrlEvent
+NTSTATUS NTAPI
+ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console,
+                              IN ULONG ProcessGroupId,
+                              IN ULONG Event)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PLIST_ENTRY current_entry;
+    PCONSOLE_PROCESS_DATA current;
+
+    /* If the console is already being destroyed, just return */
+    if (!ConDrvValidateConsole(Console, CONSOLE_RUNNING, FALSE))
+        return STATUS_UNSUCCESSFUL;
+
+    /*
+     * Loop through the process list, from the most recent process
+     * (the active one) to the oldest one (the first created, i.e.
+     * the console leader process), and for each, send an event
+     * (new processes are inserted at the head of the console process list).
+     */
+    current_entry = Console->ProcessList.Flink;
+    while (current_entry != &Console->ProcessList)
+    {
+        current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
+        current_entry = current_entry->Flink;
+
+        /*
+         * Only processes belonging to the same process group are signaled.
+         * If the process group ID is zero, then all the processes are signaled.
+         */
+        if (ProcessGroupId == 0 || current->Process->ProcessGroupId == ProcessGroupId)
+        {
+            Status = ConDrvConsoleCtrlEvent(Event, current);
+        }
+    }
+
+    return Status;
+}
+
+/* EOF */
index fbf5523..e1f7b7e 100644 (file)
@@ -135,137 +135,24 @@ PurgeInputBuffer(PCONSOLE Console)
     CloseHandle(Console->InputBuffer.ActiveEvent);
 }
 
-static DWORD FASTCALL
-ConioGetShiftState(PBYTE KeyState, LPARAM lParam)
+VOID NTAPI
+ConDrvProcessKey(IN PCONSOLE Console,
+                 IN BOOLEAN Down,
+                 IN UINT VirtualKeyCode,
+                 IN UINT VirtualScanCode,
+                 IN WCHAR UnicodeChar,
+                 IN ULONG ShiftState,
+                 IN BYTE KeyStateCtrl)
 {
-    DWORD ssOut = 0;
-
-    if (KeyState[VK_CAPITAL] & 0x01)
-        ssOut |= CAPSLOCK_ON;
-
-    if (KeyState[VK_NUMLOCK] & 0x01)
-        ssOut |= NUMLOCK_ON;
-
-    if (KeyState[VK_SCROLL] & 0x01)
-        ssOut |= SCROLLLOCK_ON;
-
-    if (KeyState[VK_SHIFT] & 0x80)
-        ssOut |= SHIFT_PRESSED;
-
-    if (KeyState[VK_LCONTROL] & 0x80)
-        ssOut |= LEFT_CTRL_PRESSED;
-    if (KeyState[VK_RCONTROL] & 0x80)
-        ssOut |= RIGHT_CTRL_PRESSED;
-
-    if (KeyState[VK_LMENU] & 0x80)
-        ssOut |= LEFT_ALT_PRESSED;
-    if (KeyState[VK_RMENU] & 0x80)
-        ssOut |= RIGHT_ALT_PRESSED;
-
-    /* See WM_CHAR MSDN documentation for instance */
-    if (lParam & 0x01000000)
-        ssOut |= ENHANCED_KEY;
-
-    return ssOut;
-}
-
-VOID WINAPI
-ConioProcessKey(PCONSOLE Console, MSG* msg)
-{
-    static BYTE KeyState[256] = { 0 };
-    /* MSDN mentions that you should use the last virtual key code received
-     * when putting a virtual key identity to a WM_CHAR message since multiple
-     * or translated keys may be involved. */
-    static UINT LastVirtualKey = 0;
-    DWORD ShiftState;
-    WCHAR UnicodeChar;
-    UINT VirtualKeyCode;
-    UINT VirtualScanCode;
-    BOOL Down = FALSE;
     INPUT_RECORD er;
-    BOOLEAN Fake;          // synthesized, not a real event
-    BOOLEAN NotChar;       // message should not be used to return a character
-
-    if (NULL == Console)
-    {
-        DPRINT1("No Active Console!\n");
-        return;
-    }
-
-    VirtualScanCode = HIWORD(msg->lParam) & 0xFF;
-    Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
-           msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
-
-    GetKeyboardState(KeyState);
-    ShiftState = ConioGetShiftState(KeyState, msg->lParam);
-
-    if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
-    {
-        VirtualKeyCode = LastVirtualKey;
-        UnicodeChar = msg->wParam;
-    }
-    else
-    {
-        WCHAR Chars[2];
-        INT RetChars = 0;
-
-        VirtualKeyCode = msg->wParam;
-        RetChars = ToUnicodeEx(VirtualKeyCode,
-                               VirtualScanCode,
-                               KeyState,
-                               Chars,
-                               2,
-                               0,
-                               NULL);
-        UnicodeChar = (1 == RetChars ? Chars[0] : 0);
-    }
-
-    er.EventType = KEY_EVENT;
-    er.Event.KeyEvent.bKeyDown = Down;
-    er.Event.KeyEvent.wRepeatCount = 1;
-    er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
-    er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
-    er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
-    er.Event.KeyEvent.dwControlKeyState = ShiftState;
-
-    if (ConioProcessKeyCallback(Console,
-                                msg,
-                                KeyState[VK_MENU],
-                                ShiftState,
-                                VirtualKeyCode,
-                                Down))
-    {
-        return;
-    }
-
-    Fake = UnicodeChar &&
-            (msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
-             msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
-    NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
-    if (NotChar) LastVirtualKey = msg->wParam;
-
-    DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
-           Down ? "down" : "up  ",
-           (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
-           "char" : "key ",
-           Fake ? "fake" : "real",
-           NotChar ? "notc" : "char",
-           VirtualScanCode,
-           VirtualKeyCode,
-           (UnicodeChar >= L' ') ? UnicodeChar : L'.',
-           ShiftState);
-
-    if (Fake) return;
 
     /* process Ctrl-C and Ctrl-Break */
-    if (Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT &&
-            er.Event.KeyEvent.bKeyDown &&
-            ((er.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
-             (er.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
-            (er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80))
+    if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT &&
+         Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') &&
+         (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyStateCtrl & 0x80) )
     {
         DPRINT1("Console_Api Ctrl-C\n");
-        ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT);
+        ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT);
 
         if (Console->LineBuffer && !Console->LineComplete)
         {
@@ -276,39 +163,46 @@ ConioProcessKey(PCONSOLE Console, MSG* msg)
         return;
     }
 
-    if (0 != (er.Event.KeyEvent.dwControlKeyState
-              & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
-            && (VK_UP == er.Event.KeyEvent.wVirtualKeyCode
-                || VK_DOWN == er.Event.KeyEvent.wVirtualKeyCode))
+    if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 &&
+         (VK_UP == VirtualKeyCode || VK_DOWN == VirtualKeyCode) )
     {
-        if (er.Event.KeyEvent.bKeyDown)
+        if (!Down) return;
+
+        /* scroll up or down */
+        if (VK_UP == VirtualKeyCode)
         {
-            /* scroll up or down */
-            if (VK_UP == er.Event.KeyEvent.wVirtualKeyCode)
+            /* only scroll up if there is room to scroll up into */
+            if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1)
             {
-                /* only scroll up if there is room to scroll up into */
-                if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1)
-                {
-                    Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
-                                                       Console->ActiveBuffer->ScreenBufferSize.Y - 1) %
-                                                       Console->ActiveBuffer->ScreenBufferSize.Y;
-                    Console->ActiveBuffer->CursorPosition.Y++;
-                }
+                Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
+                                                   Console->ActiveBuffer->ScreenBufferSize.Y - 1) %
+                                                   Console->ActiveBuffer->ScreenBufferSize.Y;
+                Console->ActiveBuffer->CursorPosition.Y++;
             }
-            else
+        }
+        else
+        {
+            /* only scroll down if there is room to scroll down into */
+            if (Console->ActiveBuffer->CursorPosition.Y != 0)
             {
-                /* only scroll down if there is room to scroll down into */
-                if (Console->ActiveBuffer->CursorPosition.Y != 0)
-                {
-                    Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
-                                                       Console->ActiveBuffer->ScreenBufferSize.Y;
-                    Console->ActiveBuffer->CursorPosition.Y--;
-                }
+                Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
+                                                   Console->ActiveBuffer->ScreenBufferSize.Y;
+                Console->ActiveBuffer->CursorPosition.Y--;
             }
-            ConioDrawConsole(Console);
         }
+
+        ConioDrawConsole(Console);
         return;
     }
+
+    er.EventType                        = KEY_EVENT;
+    er.Event.KeyEvent.bKeyDown          = Down;
+    er.Event.KeyEvent.wRepeatCount      = 1;
+    er.Event.KeyEvent.wVirtualKeyCode   = VirtualKeyCode;
+    er.Event.KeyEvent.wVirtualScanCode  = VirtualScanCode;
+    er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
+    er.Event.KeyEvent.dwControlKeyState = ShiftState;
+
     ConioProcessInputEvent(Console, &er);
 }
 
index 4f3efba..b7ac14e 100644 (file)
 
 VOID FASTCALL PurgeInputBuffer(PCONSOLE Console);
 
+VOID NTAPI
+ConDrvProcessKey(IN PCONSOLE Console,
+                 IN BOOLEAN Down,
+                 IN UINT VirtualKeyCode,
+                 IN UINT VirtualScanCode,
+                 IN WCHAR UnicodeChar,
+                 IN ULONG ShiftState,
+                 IN BYTE KeyStateCtrl);
+
 /* EOF */
index da698a1..17281a5 100644 (file)
 
 /* Macros used to call functions in the FRONTEND_VTBL virtual table */
 
-#define ConioCleanupConsole(Console) \
-    (Console)->TermIFace.Vtbl->CleanupConsole(Console)
 #define ConioDrawRegion(Console, Region) \
-    (Console)->TermIFace.Vtbl->DrawRegion((Console), (Region))
+    (Console)->TermIFace.Vtbl->DrawRegion(&(Console)->TermIFace, (Region))
 #define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \
-    (Console)->TermIFace.Vtbl->WriteStream((Console), (Block), (CurStartX), (CurStartY), \
+    (Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (Block), (CurStartX), (CurStartY), \
                                            (ScrolledLines), (Buffer), (Length))
 #define ConioSetCursorInfo(Console, Buff) \
-    (Console)->TermIFace.Vtbl->SetCursorInfo((Console), (Buff))
+    (Console)->TermIFace.Vtbl->SetCursorInfo(&(Console)->TermIFace, (Buff))
 #define ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY) \
-    (Console)->TermIFace.Vtbl->SetScreenInfo((Console), (Buff), (OldCursorX), (OldCursorY))
+    (Console)->TermIFace.Vtbl->SetScreenInfo(&(Console)->TermIFace, (Buff), (OldCursorX), (OldCursorY))
 #define ConioResizeTerminal(Console) \
-    (Console)->TermIFace.Vtbl->ResizeTerminal(Console)
+    (Console)->TermIFace.Vtbl->ResizeTerminal(&(Console)->TermIFace)
 #define ConioProcessKeyCallback(Console, Msg, KeyStateMenu, ShiftState, VirtualKeyCode, Down) \
-    (Console)->TermIFace.Vtbl->ProcessKeyCallback((Console), (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down))
+    (Console)->TermIFace.Vtbl->ProcessKeyCallback(&(Console)->TermIFace, (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down))
 #define ConioRefreshInternalInfo(Console) \
-    (Console)->TermIFace.Vtbl->RefreshInternalInfo(Console)
+    (Console)->TermIFace.Vtbl->RefreshInternalInfo(&(Console)->TermIFace)
 
 #define ConioChangeTitle(Console) \
-    (Console)->TermIFace.Vtbl->ChangeTitle(Console)
+    (Console)->TermIFace.Vtbl->ChangeTitle(&(Console)->TermIFace)
 #define ConioChangeIcon(Console, hWindowIcon) \
-    (Console)->TermIFace.Vtbl->ChangeIcon((Console), (hWindowIcon))
+    (Console)->TermIFace.Vtbl->ChangeIcon(&(Console)->TermIFace, (hWindowIcon))
 #define ConioGetConsoleWindowHandle(Console) \
-    (Console)->TermIFace.Vtbl->GetConsoleWindowHandle(Console)
+    (Console)->TermIFace.Vtbl->GetConsoleWindowHandle(&(Console)->TermIFace)
 #define ConioGetLargestConsoleWindowSize(Console, pSize) \
-    (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize((Console), (pSize))
+    (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize(&(Console)->TermIFace, (pSize))
 #define ConioGetDisplayMode(Console) \
-    (Console)->TermIFace.Vtbl->GetDisplayMode(Console)
+    (Console)->TermIFace.Vtbl->GetDisplayMode(&(Console)->TermIFace)
 #define ConioSetDisplayMode(Console, NewMode) \
-    (Console)->TermIFace.Vtbl->SetDisplayMode((Console), (NewMode))
+    (Console)->TermIFace.Vtbl->SetDisplayMode(&(Console)->TermIFace, (NewMode))
 #define ConioShowMouseCursor(Console, Show) \
-    (Console)->TermIFace.Vtbl->ShowMouseCursor((Console), (Show))
+    (Console)->TermIFace.Vtbl->ShowMouseCursor(&(Console)->TermIFace, (Show))
 #define ConioSetMouseCursor(Console, hCursor) \
-    (Console)->TermIFace.Vtbl->SetMouseCursor((Console), (hCursor))
+    (Console)->TermIFace.Vtbl->SetMouseCursor(&(Console)->TermIFace, (hCursor))
 #define ConioMenuControl(Console, CmdIdLow, CmdIdHigh) \
-    (Console)->TermIFace.Vtbl->MenuControl((Console), (CmdIdLow), (CmdIdHigh))
+    (Console)->TermIFace.Vtbl->MenuControl(&(Console)->TermIFace, (CmdIdLow), (CmdIdHigh))
 #define ConioSetMenuClose(Console, Enable) \
-    (Console)->TermIFace.Vtbl->SetMenuClose((Console), (Enable))
+    (Console)->TermIFace.Vtbl->SetMenuClose(&(Console)->TermIFace, (Enable))
 
 /* EOF */
index d74f76d..39fd9c6 100644 (file)
@@ -150,6 +150,11 @@ ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
     // ConioDrawConsole(Console);
 }
 
+PCONSOLE_SCREEN_BUFFER
+ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
+{
+    return (Console ? Console->ActiveBuffer : NULL);
+}
 
 /* PUBLIC SERVER APIS *********************************************************/
 
index f10320b..8d11d7b 100644 (file)
@@ -40,4 +40,7 @@ NTSTATUS FASTCALL ConSrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
 VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
 VOID FASTCALL ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
 
+PCONSOLE_SCREEN_BUFFER
+ConDrvGetActiveScreenBuffer(IN PCONSOLE Console);
+
 /* EOF */
index deed524..d0e0243 100644 (file)
@@ -10,9 +10,6 @@
 
 /* INCLUDES *******************************************************************/
 
-#define COBJMACROS
-#define NONAMELESSUNION
-
 #include "consrv.h"
 #include "include/conio.h"
 #include "conio.h"
 #include "include/settings.h"
 
 #include "frontends/gui/guiterm.h"
+#ifdef TUITERM_COMPILE
 #include "frontends/tui/tuiterm.h"
+#endif
 
 #include "include/console.h"
 #include "console.h"
 #include "resource.h"
 
-#include <shlwapi.h>
-#include <shlobj.h>
-
 #define NDEBUG
 #include <debug.h>
 
-/* GLOBALS ********************************************************************/
-
-static LIST_ENTRY ConsoleList;  /* The list of all the allocated consoles */
-static RTL_RESOURCE ListLock;
-
-#define ConSrvLockConsoleListExclusive()    \
-    RtlAcquireResourceExclusive(&ListLock, TRUE)
-
-#define ConSrvLockConsoleListShared()       \
-    RtlAcquireResourceShared(&ListLock, TRUE)
-
-#define ConSrvUnlockConsoleList()           \
-    RtlReleaseResource(&ListLock)
 
-// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
-BOOLEAN
-ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest,
-                           IN PCWSTR Source)
-{
-    SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR);
-    if (Size > MAXUSHORT) return FALSE;
-
-    UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size);
-    if (UniDest->Buffer == NULL) return FALSE;
-
-    RtlCopyMemory(UniDest->Buffer, Source, Size);
-    UniDest->MaximumLength = (USHORT)Size;
-    UniDest->Length = (USHORT)Size - sizeof(WCHAR);
-
-    return TRUE;
-}
-
-// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431
-VOID
-ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
-{
-    if (UnicodeString->Buffer)
-    {
-        ConsoleFreeHeap(UnicodeString->Buffer);
-        RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
-    }
-}
-
-
-/* PRIVATE FUNCTIONS **********************************************************/
-
-static BOOL
-DtbgIsDesktopVisible(VOID)
-{
-    return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
-}
+/* GLOBALS ********************************************************************/
 
-static ULONG
-ConSrvConsoleCtrlEventTimeout(DWORD Event,
-                              PCONSOLE_PROCESS_DATA ProcessData,
-                              DWORD Timeout)
-{
-    ULONG Status = ERROR_SUCCESS;
+/***************/
+#ifdef TUITERM_COMPILE
+NTSTATUS NTAPI
+TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+                IN OUT PCONSOLE_INFO ConsoleInfo,
+                IN OUT PVOID ExtraConsoleInfo,
+                IN ULONG ProcessId);
+NTSTATUS NTAPI
+TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
+#endif
 
-    DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
+NTSTATUS NTAPI
+GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+                IN OUT PCONSOLE_INFO ConsoleInfo,
+                IN OUT PVOID ExtraConsoleInfo,
+                IN ULONG ProcessId);
+NTSTATUS NTAPI
+GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
+/***************/
+
+typedef
+NTSTATUS NTAPI
+(*FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
+                 IN OUT PCONSOLE_INFO ConsoleInfo,
+                 IN OUT PVOID ExtraConsoleInfo,
+                 IN ULONG ProcessId);
+
+typedef
+NTSTATUS NTAPI
+(*FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
 
-    if (ProcessData->CtrlDispatcher)
-    {
-        _SEH2_TRY
-        {
-            HANDLE Thread = NULL;
-
-            _SEH2_TRY
-            {
-                Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
-                                            ProcessData->CtrlDispatcher,
-                                            UlongToPtr(Event), 0, NULL);
-                if (NULL == Thread)
-                {
-                    Status = GetLastError();
-                    DPRINT1("Failed thread creation (Error: 0x%x)\n", Status);
-                }
-                else
-                {
-                    DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
-                    WaitForSingleObject(Thread, Timeout);
-                }
-            }
-            _SEH2_FINALLY
-            {
-                CloseHandle(Thread);
-            }
-            _SEH2_END;
-        }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-        {
-            Status = RtlNtStatusToDosError(_SEH2_GetExceptionCode());
-            DPRINT1("ConSrvConsoleCtrlEventTimeout - Caught an exception, Status = %08X\n", Status);
-        }
-        _SEH2_END;
-    }
-
-    return Status;
-}
+/*
+ * If we are not in GUI-mode, start the text-mode terminal emulator.
+ * If we fail, try to start the GUI-mode terminal emulator.
+ *
+ * Try to open the GUI-mode terminal emulator. Two cases are possible:
+ * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
+ *   failed and we start GUI-mode terminal emulator.
+ * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
+ *   succeeded BUT we failed at starting text-mode terminal emulator.
+ *   Then GuiMode was switched to TRUE in order to try to open the GUI-mode
+ *   terminal emulator (Win32k will automatically switch to graphical mode,
+ *   therefore no additional code is needed).
+ */
 
-static ULONG
-ConSrvConsoleCtrlEvent(DWORD Event,
-                       PCONSOLE_PROCESS_DATA ProcessData)
+/*
+ * NOTE: Each entry of the table should be retrieved when loading a front-end
+ *       (examples of the CSR servers which register some data for CSRSS).
+ */
+struct
 {
-    return ConSrvConsoleCtrlEventTimeout(Event, ProcessData, 0);
-}
-
-ULONG FASTCALL
-ConSrvConsoleProcessCtrlEvent(PCONSOLE Console,
-                              ULONG ProcessGroupId,
-                              DWORD Event)
+    CHAR            FrontEndName[80];
+    FRONTEND_LOAD   FrontEndLoad;
+    FRONTEND_UNLOAD FrontEndUnload;
+} FrontEndLoadingMethods[] =
 {
-    ULONG Status = ERROR_SUCCESS;
-    PLIST_ENTRY current_entry;
-    PCONSOLE_PROCESS_DATA current;
-
-    /* If the console is already being destroyed, just return */
-    if (!ConSrvValidateConsole(Console, CONSOLE_RUNNING, FALSE))
-        return STATUS_UNSUCCESSFUL;
+#ifdef TUITERM_COMPILE
+    {"TUI", TuiLoadFrontEnd,    TuiUnloadFrontEnd},
+#endif
+    {"GUI", GuiLoadFrontEnd,    GuiUnloadFrontEnd},
 
-    /*
-     * Loop through the process list, from the most recent process
-     * (the active one) to the oldest one (the first created, i.e.
-     * the console leader process), and for each, send an event
-     * (new processes are inserted at the head of the console process list).
-     */
-    current_entry = Console->ProcessList.Flink;
-    while (current_entry != &Console->ProcessList)
-    {
-        current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
-        current_entry = current_entry->Flink;
+//  {"Not found", 0, NULL}
+};
 
-        /*
-         * Only processes belonging to the same process group are signaled.
-         * If the process group ID is zero, then all the processes are signaled.
-         */
-        if (ProcessGroupId == 0 || current->Process->ProcessGroupId == ProcessGroupId)
-        {
-            Status = ConSrvConsoleCtrlEvent(Event, current);
-        }
-    }
 
-    return Status;
-}
+/* PRIVATE FUNCTIONS **********************************************************/
 
+#if 0000
 VOID FASTCALL
 ConioPause(PCONSOLE Console, UINT Flags)
 {
@@ -212,97 +134,10 @@ ConioUnpause(PCONSOLE Console, UINT Flags)
         }
     }
 }
+#endif
 
-BOOL FASTCALL
-ConSrvValidateConsolePointer(PCONSOLE Console)
-{
-    PLIST_ENTRY ConsoleEntry;
-    PCONSOLE CurrentConsole = NULL;
-
-    if (!Console) return FALSE;
-
-    /* The console list must be locked */
-    // ASSERT(Console_list_locked);
-
-    ConsoleEntry = ConsoleList.Flink;
-    while (ConsoleEntry != &ConsoleList)
-    {
-        CurrentConsole = CONTAINING_RECORD(ConsoleEntry, CONSOLE, Entry);
-        ConsoleEntry = ConsoleEntry->Flink;
-        if (CurrentConsole == Console) return TRUE;
-    }
-
-    return FALSE;
-}
-
-BOOL FASTCALL
-ConSrvValidateConsoleState(PCONSOLE Console,
-                           CONSOLE_STATE ExpectedState)
-{
-    // if (!Console) return FALSE;
-
-    /* The console must be locked */
-    // ASSERT(Console_locked);
-
-    return (Console->State == ExpectedState);
-}
-
-BOOL FASTCALL
-ConSrvValidateConsoleUnsafe(PCONSOLE Console,
-                            CONSOLE_STATE ExpectedState,
-                            BOOL LockConsole)
-{
-    if (!Console) return FALSE;
-
-    /*
-     * Lock the console to forbid possible console's state changes
-     * (which must be done when the console is already locked).
-     * If we don't want to lock it, it's because the lock is already
-     * held. So there must be no problems.
-     */
-    if (LockConsole) EnterCriticalSection(&Console->Lock);
-
-    // ASSERT(Console_locked);
-
-    /* Check whether the console's state is what we expect */
-    if (!ConSrvValidateConsoleState(Console, ExpectedState))
-    {
-        if (LockConsole) LeaveCriticalSection(&Console->Lock);
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-BOOL FASTCALL
-ConSrvValidateConsole(PCONSOLE Console,
-                      CONSOLE_STATE ExpectedState,
-                      BOOL LockConsole)
-{
-    BOOL RetVal = FALSE;
-
-    if (!Console) return FALSE;
-
-    /*
-     * Forbid creation or deletion of consoles when
-     * checking for the existence of a console.
-     */
-    ConSrvLockConsoleListShared();
-
-    if (ConSrvValidateConsolePointer(Console))
-    {
-        RetVal = ConSrvValidateConsoleUnsafe(Console,
-                                             ExpectedState,
-                                             LockConsole);
-    }
-
-    /* Unlock the console list and return */
-    ConSrvUnlockConsoleList();
-    return RetVal;
-}
 
-NTSTATUS
-FASTCALL
+NTSTATUS FASTCALL
 ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
                  PCONSOLE* Console,
                  BOOL LockConsole)
@@ -310,19 +145,14 @@ ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
     NTSTATUS Status = STATUS_SUCCESS;
     PCONSOLE ProcessConsole;
 
+    ASSERT(Console);
+    *Console = NULL;
+
     // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
     ProcessConsole = ProcessData->Console;
 
-    if (ConSrvValidateConsole(ProcessConsole, CONSOLE_RUNNING, LockConsole))
-    {
-        InterlockedIncrement(&ProcessConsole->ReferenceCount);
-        *Console = ProcessConsole;
-    }
-    else
-    {
-        *Console = NULL;
-        Status = STATUS_INVALID_HANDLE;
-    }
+    Status = ConDrvGrabConsole(ProcessConsole, LockConsole);
+    if (NT_SUCCESS(Status)) *Console = ProcessConsole;
 
     // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
     return Status;
@@ -332,183 +162,34 @@ VOID FASTCALL
 ConSrvReleaseConsole(PCONSOLE Console,
                      BOOL WasConsoleLocked)
 {
-    LONG RefCount = 0;
-
-    if (!Console) return;
-    // if (Console->ReferenceCount == 0) return; // This shouldn't happen
-    ASSERT(Console->ReferenceCount > 0);
-
-    /* The console must be locked */
-    // ASSERT(Console_locked);
-
-    /*
-     * Decrement the reference count. Save the new value too,
-     * because Console->ReferenceCount might be modified after
-     * the console gets unlocked but before we check whether we
-     * can destroy it.
-     */
-    RefCount = _InterlockedDecrement(&Console->ReferenceCount);
-
-    /* Unlock the console if needed */
-    if (WasConsoleLocked) LeaveCriticalSection(&Console->Lock);
-
-    /* Delete the console if needed */
-    if (RefCount <= 0) ConSrvDeleteConsole(Console);
-}
-
-VOID WINAPI
-ConSrvInitConsoleSupport(VOID)
-{
-    DPRINT("CONSRV: ConSrvInitConsoleSupport()\n");
-
-    /* Initialize the console list and its lock */
-    InitializeListHead(&ConsoleList);
-    RtlInitializeResource(&ListLock);
-
-    /* Should call LoadKeyboardLayout */
+    /* Just call the driver*/
+    ConDrvReleaseConsole(Console, WasConsoleLocked);
 }
 
-static BOOL
-LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
-                         IN OUT PCONSOLE_INFO ConsoleInfo,
-                         OUT LPWSTR IconPath,
-                         IN SIZE_T IconPathLength,
-                         OUT PINT piIcon)
-{
-#define PATH_SEPARATOR L'\\'
-
-    BOOL    RetVal   = FALSE;
-    HRESULT hRes     = S_OK;
-    LPWSTR  LinkName = NULL;
-    SIZE_T  Length   = 0;
-
-    if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
-        return FALSE;
-
-    if (IconPath == NULL || piIcon == NULL)
-        return FALSE;
-
-    IconPath[0] = L'\0';
-    *piIcon = 0;
-
-    /* 1- Find the last path separator if any */
-    LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
-    if (LinkName == NULL)
-    {
-        LinkName = ConsoleStartInfo->ConsoleTitle;
-    }
-    else
-    {
-        /* Skip the path separator */
-        ++LinkName;
-    }
-
-    /* 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;
-
-    /* 3- It may be a link. Try to retrieve some properties */
-    hRes = CoInitialize(NULL);
-    if (SUCCEEDED(hRes))
-    {
-        /* 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))
-        {
-            /* Get a pointer to the IPersistFile interface */
-            IPersistFile* ppf = NULL;
-            hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
-            if (SUCCEEDED(hRes))
-            {
-                /* 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->ShowWindow = (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, IconPath, IconPathLength, piIcon);
-                    if (!SUCCEEDED(hRes))
-                    {
-                        IconPath[0] = L'\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);
-            }
-            IShellLinkW_Release(pshl);
-        }
-    }
-    CoUninitialize();
-
-    return RetVal;
-}
 
 NTSTATUS WINAPI
 ConSrvInitConsole(OUT PCONSOLE* NewConsole,
                   IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
-                  IN PCSR_PROCESS ConsoleLeaderProcess)
+                  IN ULONG ConsoleLeaderProcessId)
 {
     NTSTATUS Status;
-    SECURITY_ATTRIBUTES SecurityAttributes;
-    SIZE_T Length = 0;
-    DWORD ProcessId = HandleToUlong(ConsoleLeaderProcess->ClientId.UniqueProcess);
-    CONSOLE_INFO ConsoleInfo;
-    TEXTMODE_BUFFER_INFO ScreenBufferInfo;
     PCONSOLE Console;
-    PCONSOLE_SCREEN_BUFFER NewBuffer;
-    BOOL GuiMode;
-    WCHAR DefaultTitle[128];
-    WCHAR IconPath[MAX_PATH + 1] = L"";
-    INT iIcon = 0;
+    CONSOLE_INFO ConsoleInfo;
+    SIZE_T Length = 0;
+    ULONG i = 0;
+    FRONTEND FrontEnd;
 
-    if (NewConsole == NULL) return STATUS_INVALID_PARAMETER;
-    *NewConsole = NULL;
+    if (NewConsole == NULL || ConsoleStartInfo == NULL)
+        return STATUS_INVALID_PARAMETER;
 
-    /*
-     * Allocate a console structure
-     */
-    Console = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(CONSOLE));
-    if (NULL == Console)
-    {
-        DPRINT1("Not enough memory for console creation.\n");
-        return STATUS_NO_MEMORY;
-    }
+    *NewConsole = NULL;
 
     /*
      * Load the console settings
      */
 
     /* 1. Load the default settings */
-    ConSrvGetDefaultSettings(&ConsoleInfo, ProcessId);
+    ConSrvGetDefaultSettings(&ConsoleInfo, ConsoleLeaderProcessId);
 
     /* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */
     Length = min(wcslen(ConsoleStartInfo->ConsoleTitle),
@@ -516,23 +197,39 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole,
     wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length);
     ConsoleInfo.ConsoleTitle[Length] = L'\0';
 
+
     /*
-     * 3. Check whether the process creating the console was launched
-     *    via a shell-link. ConsoleInfo.ConsoleTitle may be updated by
-     *    the name of the shortcut.
+     * Choose an adequate terminal front-end to load, and load it
      */
-    if (ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)
-    {
-        if (!LoadShellLinkConsoleInfo(ConsoleStartInfo,
-                                      &ConsoleInfo,
-                                      IconPath,
-                                      MAX_PATH,
-                                      &iIcon))
+    Status = STATUS_SUCCESS;
+    for (i = 0; i < sizeof(FrontEndLoadingMethods) / sizeof(FrontEndLoadingMethods[0]); ++i)
+    {
+        DPRINT("CONSRV: Trying to load %s terminal emulator...\n", FrontEndLoadingMethods[i].FrontEndName);
+        Status = FrontEndLoadingMethods[i].FrontEndLoad(&FrontEnd,
+                                                        &ConsoleInfo,
+                                                        ConsoleStartInfo,
+                                                        ConsoleLeaderProcessId);
+        if (NT_SUCCESS(Status))
         {
-            ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
+            DPRINT("CONSRV: %s terminal emulator loaded successfully\n", FrontEndLoadingMethods[i].FrontEndName);
+            break;
         }
+        else
+        {
+            DPRINT1("CONSRV: Loading %s terminal emulator failed, Status = 0x%08lx , continuing...\n", FrontEndLoadingMethods[i].FrontEndName, Status);
+        }
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
+        return Status;
     }
 
+    DPRINT("CONSRV: Frontend initialized\n");
+
+
+/******************************************************************************/
     /*
      * 4. Load the remaining console settings via the registry.
      */
@@ -543,7 +240,7 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole,
          * or we failed to load shell-link console properties.
          * Therefore, load the console infos for the application from the registry.
          */
-        ConSrvReadUserSettings(&ConsoleInfo, ProcessId);
+        ConSrvReadUserSettings(&ConsoleInfo, ConsoleLeaderProcessId);
 
         /*
          * Now, update them with the properties the user might gave to us
@@ -561,198 +258,36 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole,
         }
         if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
         {
-            // ConsoleInfo->ConsoleSize = ConsoleStartInfo->ConsoleWindowSize;
+            // ConsoleInfo.ConsoleSize = ConsoleStartInfo->ConsoleWindowSize;
             ConsoleInfo.ConsoleSize.X = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cx;
             ConsoleInfo.ConsoleSize.Y = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cy;
         }
     }
 
-    /*
-     * Fix the screen buffer size if needed. The rule is:
-     * ScreenBufferSize >= ConsoleSize
-     */
-    if (ConsoleInfo.ScreenBufferSize.X < ConsoleInfo.ConsoleSize.X)
-        ConsoleInfo.ScreenBufferSize.X = ConsoleInfo.ConsoleSize.X;
-    if (ConsoleInfo.ScreenBufferSize.Y < ConsoleInfo.ConsoleSize.Y)
-        ConsoleInfo.ScreenBufferSize.Y = ConsoleInfo.ConsoleSize.Y;
-
-    /*
-     * Initialize the console
-     */
-    Console->State = CONSOLE_INITIALIZING;
-    Console->ReferenceCount = 0;
-    InitializeCriticalSection(&Console->Lock);
-    InitializeListHead(&Console->ProcessList);
-    RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
-
-    memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors));
-    Console->ConsoleSize = ConsoleInfo.ConsoleSize;
-    Console->FixedSize   = FALSE; // Value by default; is reseted by the front-ends if needed.
-
-    /*
-     * Initialize the input buffer
-     */
-    ConSrvInitObject(&Console->InputBuffer.Header, INPUT_BUFFER, Console);
-
-    SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
-    SecurityAttributes.lpSecurityDescriptor = NULL;
-    SecurityAttributes.bInheritHandle = TRUE;
-    Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
-    if (NULL == Console->InputBuffer.ActiveEvent)
-    {
-        DeleteCriticalSection(&Console->Lock);
-        ConsoleFreeHeap(Console);
-        return STATUS_UNSUCCESSFUL;
-    }
+    /* Set-up the code page */
+    ConsoleInfo.CodePage = GetOEMCP();
+/******************************************************************************/
 
-    Console->InputBuffer.InputBufferSize = 0; // FIXME!
-    InitializeListHead(&Console->InputBuffer.InputEvents);
-    InitializeListHead(&Console->InputBuffer.ReadWaitQueue);
-    Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
-                                ENABLE_ECHO_INPUT      | ENABLE_MOUSE_INPUT;
-
-    Console->QuickEdit  = ConsoleInfo.QuickEdit;
-    Console->InsertMode = ConsoleInfo.InsertMode;
-    Console->LineBuffer = NULL;
-    Console->LineMaxSize = Console->LineSize = Console->LinePos = 0;
-    Console->LineComplete = Console->LineUpPressed = Console->LineInsertToggle = FALSE;
-    // LineWakeupMask
-    RtlZeroMemory(&Console->Selection, sizeof(CONSOLE_SELECTION_INFO));
-    Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
-    // dwSelectionCursor
-
-    Console->CodePage = GetOEMCP();
-    Console->OutputCodePage = GetOEMCP();
-
-    /* Initialize a new text-mode screen buffer with default settings */
-    ScreenBufferInfo.ScreenBufferSize = ConsoleInfo.ScreenBufferSize;
-    ScreenBufferInfo.ScreenAttrib     = ConsoleInfo.ScreenAttrib;
-    ScreenBufferInfo.PopupAttrib      = ConsoleInfo.PopupAttrib;
-    ScreenBufferInfo.IsCursorVisible  = TRUE;
-    ScreenBufferInfo.CursorSize       = ConsoleInfo.CursorSize;
-
-    InitializeListHead(&Console->BufferList);
-    Status = ConSrvCreateScreenBuffer(&NewBuffer,
-                                      Console,
-                                      CONSOLE_TEXTMODE_BUFFER,
-                                      &ScreenBufferInfo);
+    Status = ConDrvInitConsole(&Console, &ConsoleInfo, ConsoleLeaderProcessId);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("ConSrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
-        CloseHandle(Console->InputBuffer.ActiveEvent);
-        DeleteCriticalSection(&Console->Lock);
-        ConsoleFreeHeap(Console);
+        DPRINT1("Creating a new console failed, Status = 0x%08lx\n", Status);
+        FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
         return Status;
     }
-    /* Make the new screen buffer active */
-    Console->ActiveBuffer = NewBuffer;
-    InitializeListHead(&Console->WriteWaitQueue);
-    Console->PauseFlags = 0;
-    Console->UnpauseEvent = NULL;
-
-    /*
-     * Initialize the alias and history buffers
-     */
-    Console->Aliases = NULL;
-    InitializeListHead(&Console->HistoryBuffers);
-    Console->HistoryBufferSize = ConsoleInfo.HistoryBufferSize;
-    Console->NumberOfHistoryBuffers = ConsoleInfo.NumberOfHistoryBuffers;
-    Console->HistoryNoDup = ConsoleInfo.HistoryNoDup;
-
-    /* Initialize the console title */
-    ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo.ConsoleTitle);
-    if (ConsoleInfo.ConsoleTitle[0] == L'\0')
-    {
-        if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0])))
-        {
-            ConsoleCreateUnicodeString(&Console->Title, DefaultTitle);
-        }
-        else
-        {
-            ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console");
-        }
-    }
-    else
-    {
-        ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo.ConsoleTitle);
-    }
-
-    /* Lock the console until its initialization is finished */
-    // EnterCriticalSection(&Console->Lock);
-
-    /*
-     * If we are not in GUI-mode, start the text-mode terminal emulator.
-     * If we fail, try to start the GUI-mode terminal emulator.
-     */
-    GuiMode = DtbgIsDesktopVisible();
 
-    if (!GuiMode)
-    {
-        DPRINT("CONSRV: Opening text-mode terminal emulator\n");
-        Status = TuiInitConsole(Console,
-                                ConsoleStartInfo,
-                                &ConsoleInfo,
-                                ProcessId);
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("Failed to open text-mode terminal emulator, switching to gui-mode, Status = 0x%08lx\n", Status);
-            GuiMode = TRUE;
-        }
-    }
+    ASSERT(Console);
+    DPRINT("Console initialized\n");
 
-    /*
-     * Try to open the GUI-mode terminal emulator. Two cases are possible:
-     * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
-     *   failed and we start GUI-mode terminal emulator.
-     * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
-     *   succeeded BUT we failed at starting text-mode terminal emulator.
-     *   Then GuiMode was switched to TRUE in order to try to open the GUI-mode
-     *   terminal emulator (Win32k will automatically switch to graphical mode,
-     *   therefore no additional code is needed).
-     */
-    if (GuiMode)
+    Status = ConDrvRegisterFrontEnd(Console, &FrontEnd);
+    if (!NT_SUCCESS(Status))
     {
-        DPRINT("CONSRV: Opening GUI-mode terminal emulator\n");
-        Status = GuiInitConsole(Console,
-                                ConsoleStartInfo,
-                                &ConsoleInfo,
-                                ProcessId,
-                                IconPath,
-                                iIcon);
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
-            ConsoleFreeUnicodeString(&Console->OriginalTitle);
-            ConsoleFreeUnicodeString(&Console->Title);
-            ConioDeleteScreenBuffer(NewBuffer);
-            CloseHandle(Console->InputBuffer.ActiveEvent);
-            // LeaveCriticalSection(&Console->Lock);
-            DeleteCriticalSection(&Console->Lock);
-            ConsoleFreeHeap(Console);
-            return Status;
-        }
+        DPRINT1("Failed to register frontend to the given console, Status = 0x%08lx\n", Status);
+        ConDrvDeleteConsole(Console);
+        FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
+        return Status;
     }
-
-    DPRINT("Terminal initialized\n");
-
-    /* All went right, so add the console to the list */
-    ConSrvLockConsoleListExclusive();
-    DPRINT("Insert in the list\n");
-    InsertTailList(&ConsoleList, &Console->Entry);
-
-    /* The initialization is finished */
-    DPRINT("Change state\n");
-    Console->State = CONSOLE_RUNNING;
-
-    /* Unlock the console */
-    // LeaveCriticalSection(&Console->Lock);
-
-    /* Unlock the console list */
-    ConSrvUnlockConsoleList();
-
-    /* Copy buffer contents to screen */
-    ConioDrawConsole(Console);
-    DPRINT("Console drawn\n");
+    DPRINT("FrontEnd registered\n");
 
     /* Return the newly created console to the caller and a success code too */
     *NewConsole = Console;
@@ -764,116 +299,8 @@ ConSrvDeleteConsole(PCONSOLE Console)
 {
     DPRINT("ConSrvDeleteConsole\n");
 
-    /*
-     * Forbid validation of any console by other threads
-     * during the deletion of this console.
-     */
-    ConSrvLockConsoleListExclusive();
-
-    /* Check the existence of the console, and if it's ok, continue */
-    if (!ConSrvValidateConsolePointer(Console))
-    {
-        /* Unlock the console list and return */
-        ConSrvUnlockConsoleList();
-        return;
-    }
-
-    /*
-     * If the console is already being destroyed
-     * (thus not running), just return.
-     */
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
-    {
-        /* Unlock the console list and return */
-        ConSrvUnlockConsoleList();
-        return;
-    }
-
-    /*
-     * We are about to be destroyed. Signal it to other people
-     * so that they can terminate what they are doing, and that
-     * they cannot longer validate the console.
-     */
-    Console->State = CONSOLE_TERMINATING;
-
-    /*
-     * Allow other threads to finish their job: basically, unlock
-     * all other calls to EnterCriticalSection(&Console->Lock); by
-     * ConSrvValidateConsole(Unsafe) functions so that they just see
-     * that we are not in CONSOLE_RUNNING state anymore, or unlock
-     * other concurrent calls to ConSrvDeleteConsole so that they
-     * can see that we are in fact already deleting the console.
-     */
-    LeaveCriticalSection(&Console->Lock);
-    ConSrvUnlockConsoleList();
-
-    /* FIXME: Send a terminate message to all the processes owning this console */
-
-    /* Cleanup the UI-oriented part */
-    ConioCleanupConsole(Console);
-
-    /***
-     * Check that the console is in terminating state before continuing
-     * (the cleanup code must not change the state of the console...
-     * ...unless to cancel console deletion ?).
-     ***/
-
-    ConSrvLockConsoleListExclusive();
-
-    /* Re-check the existence of the console, and if it's ok, continue */
-    if (!ConSrvValidateConsolePointer(Console))
-    {
-        /* Unlock the console list and return */
-        ConSrvUnlockConsoleList();
-        return;
-    }
-
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_TERMINATING, TRUE))
-    {
-        ConSrvUnlockConsoleList();
-        return;
-    }
-
-    /* We are in destruction */
-    Console->State = CONSOLE_IN_DESTRUCTION;
-
-    /* Remove the console from the list */
-    RemoveEntryList(&Console->Entry);
-
-    /* Reset the count to be sure */
-    Console->ReferenceCount = 0;
-
-    /* Discard all entries in the input event queue */
-    PurgeInputBuffer(Console);
-
-    if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer);
-
-    IntDeleteAllAliases(Console);
-    HistoryDeleteBuffers(Console);
-
-    ConioDeleteScreenBuffer(Console->ActiveBuffer);
-    if (!IsListEmpty(&Console->BufferList))
-    {
-        DPRINT1("BUG: screen buffer list not empty\n");
-    }
-
-    // CloseHandle(Console->InputBuffer.ActiveEvent);
-    if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
-
-    ConsoleFreeUnicodeString(&Console->OriginalTitle);
-    ConsoleFreeUnicodeString(&Console->Title);
-
-    DPRINT("ConSrvDeleteConsole - Unlocking\n");
-    LeaveCriticalSection(&Console->Lock);
-    DPRINT("ConSrvDeleteConsole - Destroying lock\n");
-    DeleteCriticalSection(&Console->Lock);
-    DPRINT("ConSrvDeleteConsole - Lock destroyed ; freeing console\n");
-
-    ConsoleFreeHeap(Console);
-    DPRINT("ConSrvDeleteConsole - Console freed\n");
-
-    /* Unlock the console list and return */
-    ConSrvUnlockConsoleList();
+    /* Just call the driver. ConSrvDeregisterFrontEnd is called on-demand. */
+    ConDrvDeleteConsole(Console);
 }
 
 
@@ -1019,140 +446,59 @@ CSR_API(SrvFreeConsole)
     return STATUS_SUCCESS;
 }
 
+NTSTATUS NTAPI
+ConDrvGetConsoleMode(IN PCONSOLE Console,
+                     IN PCONSOLE_IO_OBJECT Object,
+                     OUT PULONG ConsoleMode);
 CSR_API(SrvGetConsoleMode)
 {
     NTSTATUS Status;
     PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
-    PCONSOLE_IO_OBJECT Object = NULL;
+    PCONSOLE_IO_OBJECT Object;
 
     Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
                              ConsoleModeRequest->ConsoleHandle,
                              &Object, NULL, GENERIC_READ, TRUE, 0);
     if (!NT_SUCCESS(Status)) return Status;
 
-    Status = STATUS_SUCCESS;
-
-    if (INPUT_BUFFER == Object->Type)
-    {
-        PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
-        PCONSOLE Console  = InputBuffer->Header.Console;
-        DWORD ConsoleMode = InputBuffer->Mode;
-
-        if (Console->QuickEdit || Console->InsertMode)
-        {
-            // Windows does this, even if it's not documented on MSDN
-            ConsoleMode |= ENABLE_EXTENDED_FLAGS;
-
-            if (Console->QuickEdit ) ConsoleMode |= ENABLE_QUICK_EDIT_MODE;
-            if (Console->InsertMode) ConsoleMode |= ENABLE_INSERT_MODE;
-        }
-
-        ConsoleModeRequest->ConsoleMode = ConsoleMode;
-    }
-    else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
-    {
-        PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
-        ConsoleModeRequest->ConsoleMode = Buffer->Mode;
-    }
-    else
-    {
-        Status = STATUS_INVALID_HANDLE;
-    }
+    Status = ConDrvGetConsoleMode(Object->Console, Object,
+                                  &ConsoleModeRequest->ConsoleMode);
 
     ConSrvReleaseObject(Object, TRUE);
     return Status;
 }
 
+NTSTATUS NTAPI
+ConDrvSetConsoleMode(IN PCONSOLE Console,
+                     IN PCONSOLE_IO_OBJECT Object,
+                     IN ULONG ConsoleMode);
 CSR_API(SrvSetConsoleMode)
 {
-#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS   | ENABLE_INSERT_MODE  | ENABLE_QUICK_EDIT_MODE )
-#define CONSOLE_VALID_INPUT_MODES   ( ENABLE_PROCESSED_INPUT  | ENABLE_LINE_INPUT   | \
-                                      ENABLE_ECHO_INPUT       | ENABLE_WINDOW_INPUT | \
-                                      ENABLE_MOUSE_INPUT )
-#define CONSOLE_VALID_OUTPUT_MODES  ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
-
     NTSTATUS Status;
     PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
-    DWORD ConsoleMode = ConsoleModeRequest->ConsoleMode;
-    PCONSOLE_IO_OBJECT Object  = NULL;
+    PCONSOLE_IO_OBJECT Object;
 
     Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
                              ConsoleModeRequest->ConsoleHandle,
                              &Object, NULL, GENERIC_WRITE, TRUE, 0);
     if (!NT_SUCCESS(Status)) return Status;
 
-    Status = STATUS_SUCCESS;
+    Status = ConDrvSetConsoleMode(Object->Console, Object,
+                                  ConsoleModeRequest->ConsoleMode);
 
-    if (INPUT_BUFFER == Object->Type)
-    {
-        PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
-        PCONSOLE Console = InputBuffer->Header.Console;
-
-        DPRINT("SetConsoleMode(Input, %d)\n", ConsoleMode);
-
-        /*
-         * 1. Only the presence of valid mode flags is allowed.
-         */
-        if (ConsoleMode & ~(CONSOLE_VALID_INPUT_MODES | CONSOLE_VALID_CONTROL_MODES))
-        {
-            Status = STATUS_INVALID_PARAMETER;
-            goto Quit;
-        }
-
-        /*
-         * 2. If we use control mode flags without ENABLE_EXTENDED_FLAGS,
-         *    then consider the flags invalid.
-         *
-        if ( (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) &&
-             (ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0 )
-        {
-            Status = STATUS_INVALID_PARAMETER;
-            goto Quit;
-        }
-        */
-
-        /*
-         * 3. Now we can continue.
-         */
-        if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
-        {
-            Console->QuickEdit  = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
-            Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
-        }
-        InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
-    }
-    else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
-    {
-        PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
-
-        DPRINT("SetConsoleMode(Output, %d)\n", ConsoleMode);
-
-        if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
-        {
-            Status = STATUS_INVALID_PARAMETER;
-        }
-        else
-        {
-            Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
-        }
-    }
-    else
-    {
-        Status = STATUS_INVALID_HANDLE;
-    }
-
-Quit:
     ConSrvReleaseObject(Object, TRUE);
     return Status;
 }
 
+NTSTATUS NTAPI
+ConDrvGetConsoleTitle(IN PCONSOLE Console,
+                      IN OUT PWCHAR Title,
+                      IN OUT PULONG BufLength);
 CSR_API(SrvGetConsoleTitle)
 {
     NTSTATUS Status;
     PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
-    // PCSR_PROCESS Process = CsrGetClientThread()->Process;
     PCONSOLE Console;
-    DWORD Length;
 
     if (!CsrValidateMessageBuffer(ApiMessage,
                                   (PVOID)&TitleRequest->Title,
@@ -1169,27 +515,23 @@ CSR_API(SrvGetConsoleTitle)
         return Status;
     }
 
-    /* Copy title of the console to the user title buffer */
-    if (TitleRequest->Length >= sizeof(WCHAR))
-    {
-        Length = min(TitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
-        memcpy(TitleRequest->Title, Console->Title.Buffer, Length);
-        TitleRequest->Title[Length / sizeof(WCHAR)] = L'\0';
-    }
-
-    TitleRequest->Length = Console->Title.Length;
+    Status = ConDrvGetConsoleTitle(Console,
+                                   TitleRequest->Title,
+                                   &TitleRequest->Length);
 
     ConSrvReleaseConsole(Console, TRUE);
-    return STATUS_SUCCESS;
+    return Status;
 }
 
+NTSTATUS NTAPI
+ConDrvSetConsoleTitle(IN PCONSOLE Console,
+                      IN PWCHAR Title,
+                      IN ULONG BufLength);
 CSR_API(SrvSetConsoleTitle)
 {
     NTSTATUS Status;
     PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
-    // PCSR_PROCESS Process = CsrGetClientThread()->Process;
     PCONSOLE Console;
-    PWCHAR Buffer;
 
     if (!CsrValidateMessageBuffer(ApiMessage,
                                   (PVOID)&TitleRequest->Title,
@@ -1206,368 +548,20 @@ CSR_API(SrvSetConsoleTitle)
         return Status;
     }
 
-    /* Allocate a new buffer to hold the new title (NULL-terminated) */
-    Buffer = ConsoleAllocHeap(0, TitleRequest->Length + sizeof(WCHAR));
-    if (Buffer)
-    {
-        /* Free the old title */
-        ConsoleFreeUnicodeString(&Console->Title);
-
-        /* Copy title to console */
-        Console->Title.Buffer = Buffer;
-        Console->Title.Length = TitleRequest->Length;
-        Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
-        RtlCopyMemory(Console->Title.Buffer,
-                      TitleRequest->Title,
-                      Console->Title.Length);
-        Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
-
-        ConioChangeTitle(Console);
-        Status = STATUS_SUCCESS;
-    }
-    else
-    {
-        Status = STATUS_NO_MEMORY;
-    }
+    Status = ConDrvSetConsoleTitle(Console,
+                                   TitleRequest->Title,
+                                   TitleRequest->Length);
 
-    ConSrvReleaseConsole(Console, TRUE);
-    return Status;
-}
-
-/**********************************************************************
- *  HardwareStateProperty
- *
- *  DESCRIPTION
- *      Set/Get the value of the HardwareState and switch
- *      between direct video buffer ouput and GDI windowed
- *      output.
- *  ARGUMENTS
- *      Client hands us a CONSOLE_GETSETHWSTATE object.
- *      We use the same object to Request.
- *  NOTE
- *      ConsoleHwState has the correct size to be compatible
- *      with NT's, but values are not.
- */
-#if 0
-static NTSTATUS FASTCALL
-SetConsoleHardwareState(PCONSOLE Console, ULONG ConsoleHwState)
-{
-    DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
-
-    if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
-            ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
-    {
-        if (Console->HardwareState != ConsoleHwState)
-        {
-            /* TODO: implement switching from full screen to windowed mode */
-            /* TODO: or back; now simply store the hardware state */
-            Console->HardwareState = ConsoleHwState;
-        }
-
-        return STATUS_SUCCESS;
-    }
-
-    return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
-}
-#endif
-
-CSR_API(SrvGetConsoleHardwareState)
-{
-#if 0
-    NTSTATUS Status;
-    PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
-    PCONSOLE_SCREEN_BUFFER Buff;
-    PCONSOLE Console;
-
-    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                                   HardwareStateRequest->OutputHandle,
-                                   &Buff,
-                                   GENERIC_READ,
-                                   TRUE);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
-        return Status;
-    }
-
-    Console = Buff->Header.Console;
-    HardwareStateRequest->State = Console->HardwareState;
-
-    ConSrvReleaseScreenBuffer(Buff, TRUE);
-    return Status;
-#else
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-#endif
-}
-
-CSR_API(SrvSetConsoleHardwareState)
-{
-#if 0
-    NTSTATUS Status;
-    PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
-    PCONSOLE_SCREEN_BUFFER Buff;
-    PCONSOLE Console;
-
-    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                                   HardwareStateRequest->OutputHandle,
-                                   &Buff,
-                                   GENERIC_WRITE,
-                                   TRUE);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
-        return Status;
-    }
-
-    DPRINT("Setting console hardware state.\n");
-    Console = Buff->Header.Console;
-    Status = SetConsoleHardwareState(Console, HardwareStateRequest->State);
-
-    ConSrvReleaseScreenBuffer(Buff, TRUE);
-    return Status;
-#else
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-#endif
-}
-
-CSR_API(SrvGetConsoleDisplayMode)
-{
-    NTSTATUS Status;
-    PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
-    PCONSOLE Console;
-
-    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                              &Console, TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    GetDisplayModeRequest->DisplayMode = ConioGetDisplayMode(Console);
-
-    ConSrvReleaseConsole(Console, TRUE);
-    return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleDisplayMode)
-{
-    NTSTATUS Status;
-    PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
-    PCONSOLE Console;
-    PCONSOLE_SCREEN_BUFFER Buff;
-
-    Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                                   SetDisplayModeRequest->OutputHandle,
-                                   &Buff,
-                                   GENERIC_WRITE,
-                                   TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    Console = Buff->Header.Console;
-
-    if (ConioSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode))
-    {
-        SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
-        Status = STATUS_SUCCESS;
-    }
-    else
-    {
-        Status = STATUS_INVALID_PARAMETER;
-    }
-
-    ConSrvReleaseScreenBuffer(Buff, TRUE);
-    return Status;
-}
-
-CSR_API(SrvGetLargestConsoleWindowSize)
-{
-    NTSTATUS Status;
-    PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetLargestWindowSizeRequest;
-    PCONSOLE_SCREEN_BUFFER Buff;
-    PCONSOLE Console;
-
-    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                                   GetLargestWindowSizeRequest->OutputHandle,
-                                   &Buff,
-                                   GENERIC_READ,
-                                   TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    Console = Buff->Header.Console;
-    ConioGetLargestConsoleWindowSize(Console, &GetLargestWindowSizeRequest->Size);
-
-    ConSrvReleaseScreenBuffer(Buff, TRUE);
-    return STATUS_SUCCESS;
-}
-
-CSR_API(SrvShowConsoleCursor)
-{
-    NTSTATUS Status;
-    PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest;
-    PCONSOLE Console;
-    PCONSOLE_SCREEN_BUFFER Buff;
-
-    Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                                   ShowCursorRequest->OutputHandle,
-                                   &Buff,
-                                   GENERIC_WRITE,
-                                   TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    Console = Buff->Header.Console;
-
-    ShowCursorRequest->RefCount = ConioShowMouseCursor(Console, ShowCursorRequest->Show);
-
-    ConSrvReleaseScreenBuffer(Buff, TRUE);
-    return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleCursor)
-{
-    NTSTATUS Status;
-    BOOL Success;
-    PCONSOLE_SETCURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
-    PCONSOLE Console;
-    PCONSOLE_SCREEN_BUFFER Buff;
-
-    // FIXME: Tests show that this function is used only for graphics screen buffers
-    // and otherwise it returns false + set last error to invalid handle.
-    // NOTE: I find that behaviour is ridiculous but ok, let's accept that at the moment...
-    Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                                     SetCursorRequest->OutputHandle,
-                                     &Buff,
-                                     GENERIC_WRITE,
-                                     TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    Console = Buff->Header.Console;
-
-    Success = ConioSetMouseCursor(Console, SetCursorRequest->hCursor);
-
-    ConSrvReleaseScreenBuffer(Buff, TRUE);
-    return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
-}
-
-CSR_API(SrvConsoleMenuControl)
-{
-    NTSTATUS Status;
-    PCONSOLE_MENUCONTROL MenuControlRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.MenuControlRequest;
-    PCONSOLE Console;
-    PCONSOLE_SCREEN_BUFFER Buff;
-
-    Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                                   MenuControlRequest->OutputHandle,
-                                   &Buff,
-                                   GENERIC_WRITE,
-                                   TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    Console = Buff->Header.Console;
-
-    MenuControlRequest->hMenu = ConioMenuControl(Console,
-                                                 MenuControlRequest->dwCmdIdLow,
-                                                 MenuControlRequest->dwCmdIdHigh);
-
-    ConSrvReleaseScreenBuffer(Buff, TRUE);
-    return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleMenuClose)
-{
-    NTSTATUS Status;
-    BOOL Success;
-    PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetMenuCloseRequest;
-    PCONSOLE Console;
-
-    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                              &Console, TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    Success = ConioSetMenuClose(Console, SetMenuCloseRequest->Enable);
-
-    ConSrvReleaseConsole(Console, TRUE);
-    return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
-}
-
-CSR_API(SrvSetConsoleWindowInfo)
-{
-    NTSTATUS Status;
-    PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetWindowInfoRequest;
-    PCONSOLE_SCREEN_BUFFER Buff;
-    SMALL_RECT WindowRect = SetWindowInfoRequest->WindowRect;
-
-    DPRINT("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
-            SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
-            WindowRect.Left, WindowRect.Top, WindowRect.Right, WindowRect.Bottom);
-
-    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
-                                     SetWindowInfoRequest->OutputHandle,
-                                     &Buff,
-                                     GENERIC_READ,
-                                     TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    if (SetWindowInfoRequest->Absolute == FALSE)
-    {
-        /* Relative positions given. Transform them to absolute ones */
-        WindowRect.Left   += Buff->ViewOrigin.X;
-        WindowRect.Top    += Buff->ViewOrigin.Y;
-        WindowRect.Right  += Buff->ViewOrigin.X + Buff->ViewSize.X - 1;
-        WindowRect.Bottom += Buff->ViewOrigin.Y + Buff->ViewSize.Y - 1;
-    }
-
-    /* See MSDN documentation on SetConsoleWindowInfo about the performed checks */
-    if ( (WindowRect.Left < 0) || (WindowRect.Top < 0)   ||
-         (WindowRect.Right  >= Buff->ScreenBufferSize.X) ||
-         (WindowRect.Bottom >= Buff->ScreenBufferSize.Y) ||
-         (WindowRect.Right  <= WindowRect.Left)          ||
-         (WindowRect.Bottom <= WindowRect.Top) )
-    {
-        ConSrvReleaseScreenBuffer(Buff, TRUE);
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    Buff->ViewOrigin.X = WindowRect.Left;
-    Buff->ViewOrigin.Y = WindowRect.Top;
-
-    Buff->ViewSize.X = WindowRect.Right - WindowRect.Left + 1;
-    Buff->ViewSize.Y = WindowRect.Bottom - WindowRect.Top + 1;
-
-    ConSrvReleaseScreenBuffer(Buff, TRUE);
-    return STATUS_SUCCESS;
-}
-
-CSR_API(SrvGetConsoleWindow)
-{
-    NTSTATUS Status;
-    PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest;
-    PCONSOLE Console;
-
-    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    GetWindowRequest->WindowHandle = ConioGetConsoleWindowHandle(Console);
-
-    ConSrvReleaseConsole(Console, TRUE);
-    return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleIcon)
-{
-    NTSTATUS Status;
-    PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest;
-    PCONSOLE Console;
-
-    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    Status = (ConioChangeIcon(Console, SetIconRequest->WindowIcon)
-                ? STATUS_SUCCESS
-                : STATUS_UNSUCCESSFUL);
+    if (NT_SUCCESS(Status)) ConioChangeTitle(Console);
 
     ConSrvReleaseConsole(Console, TRUE);
     return Status;
 }
 
+NTSTATUS NTAPI
+ConDrvGetConsoleCP(IN PCONSOLE Console,
+                   OUT PUINT CodePage,
+                   IN BOOLEAN InputCP);
 CSR_API(SrvGetConsoleCP)
 {
     NTSTATUS Status;
@@ -1580,15 +574,21 @@ CSR_API(SrvGetConsoleCP)
     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
-    ConsoleCPRequest->CodePage = (ConsoleCPRequest->InputCP ? Console->CodePage
-                                                            : Console->OutputCodePage);
+    Status = ConDrvGetConsoleCP(Console,
+                                &ConsoleCPRequest->CodePage,
+                                ConsoleCPRequest->InputCP);
+
     ConSrvReleaseConsole(Console, TRUE);
-    return STATUS_SUCCESS;
+    return Status;
 }
 
+NTSTATUS NTAPI
+ConDrvSetConsoleCP(IN PCONSOLE Console,
+                   IN UINT CodePage,
+                   IN BOOLEAN InputCP);
 CSR_API(SrvSetConsoleCP)
 {
-    NTSTATUS Status;
+    NTSTATUS Status = STATUS_INVALID_PARAMETER;
     PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
     PCONSOLE Console;
 
@@ -1598,31 +598,24 @@ CSR_API(SrvSetConsoleCP)
     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
-    if (IsValidCodePage(ConsoleCPRequest->CodePage))
-    {
-        if (ConsoleCPRequest->InputCP)
-            Console->CodePage = ConsoleCPRequest->CodePage;
-        else
-            Console->OutputCodePage = ConsoleCPRequest->CodePage;
-
-        ConSrvReleaseConsole(Console, TRUE);
-        return STATUS_SUCCESS;
-    }
+    Status = ConDrvSetConsoleCP(Console,
+                                ConsoleCPRequest->CodePage,
+                                ConsoleCPRequest->InputCP);
 
     ConSrvReleaseConsole(Console, TRUE);
-    return STATUS_INVALID_PARAMETER;
+    return Status;
 }
 
+NTSTATUS NTAPI
+ConDrvGetConsoleProcessList(IN PCONSOLE Console,
+                            IN OUT PULONG ProcessIdsList,
+                            IN ULONG MaxIdListItems,
+                            OUT PULONG ProcessIdsTotal);
 CSR_API(SrvGetConsoleProcessList)
 {
     NTSTATUS Status;
     PCONSOLE_GETPROCESSLIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
-    PDWORD Buffer;
-    // PCSR_PROCESS Process = CsrGetClientThread()->Process;
     PCONSOLE Console;
-    PCONSOLE_PROCESS_DATA current;
-    PLIST_ENTRY current_entry;
-    ULONG nItems = 0;
 
     if (!CsrValidateMessageBuffer(ApiMessage,
                                   (PVOID)&GetProcessListRequest->pProcessIds,
@@ -1632,26 +625,16 @@ CSR_API(SrvGetConsoleProcessList)
         return STATUS_INVALID_PARAMETER;
     }
 
-    Buffer = GetProcessListRequest->pProcessIds;
-
     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
-    for (current_entry = Console->ProcessList.Flink;
-         current_entry != &Console->ProcessList;
-         current_entry = current_entry->Flink)
-    {
-        current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
-        if (++nItems <= GetProcessListRequest->nMaxIds)
-        {
-            *Buffer++ = HandleToUlong(current->Process->ClientId.UniqueProcess);
-        }
-    }
+    Status = ConDrvGetConsoleProcessList(Console,
+                                         GetProcessListRequest->pProcessIds,
+                                         GetProcessListRequest->nMaxIds,
+                                         &GetProcessListRequest->nProcessIdsTotal);
 
     ConSrvReleaseConsole(Console, TRUE);
-
-    GetProcessListRequest->nProcessIdsTotal = nItems;
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 CSR_API(SrvGenerateConsoleCtrlEvent)
@@ -1663,7 +646,7 @@ CSR_API(SrvGenerateConsoleCtrlEvent)
     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
-    Status = ConSrvConsoleProcessCtrlEvent(Console,
+    Status = ConDrvConsoleProcessCtrlEvent(Console,
                                            GenerateCtrlEventRequest->ProcessGroup,
                                            GenerateCtrlEventRequest->Event);
 
@@ -1671,22 +654,4 @@ CSR_API(SrvGenerateConsoleCtrlEvent)
     return Status;
 }
 
-CSR_API(SrvGetConsoleSelectionInfo)
-{
-    NTSTATUS Status;
-    PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest;
-    PCONSOLE Console;
-
-    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
-    if (NT_SUCCESS(Status))
-    {
-        memset(&GetSelectionInfoRequest->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
-        if (Console->Selection.dwFlags != 0)
-            GetSelectionInfoRequest->Info = Console->Selection;
-        ConSrvReleaseConsole(Console, TRUE);
-    }
-
-    return Status;
-}
-
 /* EOF */
index 3a80267..b471eef 100644 (file)
@@ -8,16 +8,44 @@
 
 #pragma once
 
-VOID WINAPI ConSrvInitConsoleSupport(VOID);
+VOID NTAPI
+ConDrvInitConsoleSupport(VOID);
 
-NTSTATUS WINAPI ConSrvInitConsole(OUT struct _CONSOLE** /* PCONSOLE* */ NewConsole,
-                                  IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
-                                  IN PCSR_PROCESS ConsoleLeaderProcess);
+NTSTATUS WINAPI
+ConSrvInitConsole(OUT struct _CONSOLE** /* PCONSOLE* */ NewConsole,
+                  IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+                  IN ULONG ConsoleLeaderProcessId);
 VOID WINAPI ConSrvDeleteConsole(struct _CONSOLE* /* PCONSOLE */ Console);
+
 NTSTATUS FASTCALL ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
                                    struct _CONSOLE** /* PCONSOLE* */ Console,
                                    BOOL LockConsole);
 VOID FASTCALL ConSrvReleaseConsole(struct _CONSOLE* /* PCONSOLE */ Console,
                                    BOOL WasConsoleLocked);
 
+/******************************************************************************/
+
+NTSTATUS NTAPI
+ConDrvGrabConsole(IN struct _CONSOLE* /* PCONSOLE */ Console,
+                  IN BOOLEAN LockConsole);
+VOID NTAPI
+ConDrvReleaseConsole(IN struct _CONSOLE* /* PCONSOLE */ Console,
+                     IN BOOLEAN WasConsoleLocked);
+
+typedef struct _FRONTEND FRONTEND, *PFRONTEND;
+typedef struct _CONSOLE_INFO CONSOLE_INFO, *PCONSOLE_INFO;
+
+NTSTATUS NTAPI
+ConDrvInitConsole(OUT struct _CONSOLE** /* PCONSOLE* */ NewConsole,
+                  // IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+                  IN PCONSOLE_INFO ConsoleInfo,
+                  IN ULONG ConsoleLeaderProcessId);
+NTSTATUS NTAPI
+ConDrvRegisterFrontEnd(IN struct _CONSOLE* /* PCONSOLE */ Console,
+                       IN PFRONTEND FrontEnd);
+NTSTATUS NTAPI
+ConDrvDeregisterFrontEnd(IN struct _CONSOLE* /* PCONSOLE */ Console);
+VOID NTAPI
+ConDrvDeleteConsole(IN struct _CONSOLE* /* PCONSOLE */ Console);
+
 /* EOF */
diff --git a/reactos/win32ss/user/consrv/frontendctl.c b/reactos/win32ss/user/consrv/frontendctl.c
new file mode 100644 (file)
index 0000000..454702f
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Console Server DLL
+ * FILE:            win32ss/user/consrv/frontendctl.c
+ * PURPOSE:         Terminal Front-Ends Control
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "conoutput.h"
+#include "console.h"
+#include "handle.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+
+/* PUBLIC SERVER APIS *********************************************************/
+
+/**********************************************************************
+ *  HardwareStateProperty
+ *
+ *  DESCRIPTION
+ *      Set/Get the value of the HardwareState and switch
+ *      between direct video buffer ouput and GDI windowed
+ *      output.
+ *  ARGUMENTS
+ *      Client hands us a CONSOLE_GETSETHWSTATE object.
+ *      We use the same object to Request.
+ *  NOTE
+ *      ConsoleHwState has the correct size to be compatible
+ *      with NT's, but values are not.
+ */
+#if 0
+static NTSTATUS FASTCALL
+SetConsoleHardwareState(PCONSOLE Console, ULONG ConsoleHwState)
+{
+    DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
+
+    if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
+            ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
+    {
+        if (Console->HardwareState != ConsoleHwState)
+        {
+            /* TODO: implement switching from full screen to windowed mode */
+            /* TODO: or back; now simply store the hardware state */
+            Console->HardwareState = ConsoleHwState;
+        }
+
+        return STATUS_SUCCESS;
+    }
+
+    return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
+}
+#endif
+
+CSR_API(SrvGetConsoleHardwareState)
+{
+#if 0
+    NTSTATUS Status;
+    PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
+    PCONSOLE_SCREEN_BUFFER Buff;
+    PCONSOLE Console;
+
+    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                   HardwareStateRequest->OutputHandle,
+                                   &Buff,
+                                   GENERIC_READ,
+                                   TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
+        return Status;
+    }
+
+    Console = Buff->Header.Console;
+    HardwareStateRequest->State = Console->HardwareState;
+
+    ConSrvReleaseScreenBuffer(Buff, TRUE);
+    return Status;
+#else
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+#endif
+}
+
+CSR_API(SrvSetConsoleHardwareState)
+{
+#if 0
+    NTSTATUS Status;
+    PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
+    PCONSOLE_SCREEN_BUFFER Buff;
+    PCONSOLE Console;
+
+    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                   HardwareStateRequest->OutputHandle,
+                                   &Buff,
+                                   GENERIC_WRITE,
+                                   TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
+        return Status;
+    }
+
+    DPRINT("Setting console hardware state.\n");
+    Console = Buff->Header.Console;
+    Status = SetConsoleHardwareState(Console, HardwareStateRequest->State);
+
+    ConSrvReleaseScreenBuffer(Buff, TRUE);
+    return Status;
+#else
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+#endif
+}
+
+CSR_API(SrvGetConsoleDisplayMode)
+{
+    NTSTATUS Status;
+    PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
+    PCONSOLE Console;
+
+    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                              &Console, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    GetDisplayModeRequest->DisplayMode = ConioGetDisplayMode(Console);
+
+    ConSrvReleaseConsole(Console, TRUE);
+    return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleDisplayMode)
+{
+    NTSTATUS Status;
+    PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
+    PCONSOLE Console;
+    PCONSOLE_SCREEN_BUFFER Buff;
+
+    Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                   SetDisplayModeRequest->OutputHandle,
+                                   &Buff,
+                                   GENERIC_WRITE,
+                                   TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+
+    if (ConioSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode))
+    {
+        SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
+        Status = STATUS_SUCCESS;
+    }
+    else
+    {
+        Status = STATUS_INVALID_PARAMETER;
+    }
+
+    ConSrvReleaseScreenBuffer(Buff, TRUE);
+    return Status;
+}
+
+CSR_API(SrvGetLargestConsoleWindowSize)
+{
+    NTSTATUS Status;
+    PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetLargestWindowSizeRequest;
+    PCONSOLE_SCREEN_BUFFER Buff;
+    PCONSOLE Console;
+
+    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                   GetLargestWindowSizeRequest->OutputHandle,
+                                   &Buff,
+                                   GENERIC_READ,
+                                   TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+    ConioGetLargestConsoleWindowSize(Console, &GetLargestWindowSizeRequest->Size);
+
+    ConSrvReleaseScreenBuffer(Buff, TRUE);
+    return STATUS_SUCCESS;
+}
+
+CSR_API(SrvShowConsoleCursor)
+{
+    NTSTATUS Status;
+    PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest;
+    PCONSOLE Console;
+    PCONSOLE_SCREEN_BUFFER Buff;
+
+    Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                   ShowCursorRequest->OutputHandle,
+                                   &Buff,
+                                   GENERIC_WRITE,
+                                   TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+
+    ShowCursorRequest->RefCount = ConioShowMouseCursor(Console, ShowCursorRequest->Show);
+
+    ConSrvReleaseScreenBuffer(Buff, TRUE);
+    return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleCursor)
+{
+    NTSTATUS Status;
+    BOOL Success;
+    PCONSOLE_SETCURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
+    PCONSOLE Console;
+    PCONSOLE_SCREEN_BUFFER Buff;
+
+    // FIXME: Tests show that this function is used only for graphics screen buffers
+    // and otherwise it returns false + set last error to invalid handle.
+    // NOTE: I find that behaviour is ridiculous but ok, let's accept that at the moment...
+    Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                     SetCursorRequest->OutputHandle,
+                                     &Buff,
+                                     GENERIC_WRITE,
+                                     TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+
+    Success = ConioSetMouseCursor(Console, SetCursorRequest->hCursor);
+
+    ConSrvReleaseScreenBuffer(Buff, TRUE);
+    return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
+}
+
+CSR_API(SrvConsoleMenuControl)
+{
+    NTSTATUS Status;
+    PCONSOLE_MENUCONTROL MenuControlRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.MenuControlRequest;
+    PCONSOLE Console;
+    PCONSOLE_SCREEN_BUFFER Buff;
+
+    Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                   MenuControlRequest->OutputHandle,
+                                   &Buff,
+                                   GENERIC_WRITE,
+                                   TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+
+    MenuControlRequest->hMenu = ConioMenuControl(Console,
+                                                 MenuControlRequest->dwCmdIdLow,
+                                                 MenuControlRequest->dwCmdIdHigh);
+
+    ConSrvReleaseScreenBuffer(Buff, TRUE);
+    return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleMenuClose)
+{
+    NTSTATUS Status;
+    BOOL Success;
+    PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetMenuCloseRequest;
+    PCONSOLE Console;
+
+    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                              &Console, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Success = ConioSetMenuClose(Console, SetMenuCloseRequest->Enable);
+
+    ConSrvReleaseConsole(Console, TRUE);
+    return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
+}
+
+CSR_API(SrvSetConsoleWindowInfo)
+{
+    NTSTATUS Status;
+    PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetWindowInfoRequest;
+    PCONSOLE_SCREEN_BUFFER Buff;
+    SMALL_RECT WindowRect = SetWindowInfoRequest->WindowRect;
+
+    DPRINT("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
+            SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
+            WindowRect.Left, WindowRect.Top, WindowRect.Right, WindowRect.Bottom);
+
+    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                     SetWindowInfoRequest->OutputHandle,
+                                     &Buff,
+                                     GENERIC_READ,
+                                     TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    if (SetWindowInfoRequest->Absolute == FALSE)
+    {
+        /* Relative positions given. Transform them to absolute ones */
+        WindowRect.Left   += Buff->ViewOrigin.X;
+        WindowRect.Top    += Buff->ViewOrigin.Y;
+        WindowRect.Right  += Buff->ViewOrigin.X + Buff->ViewSize.X - 1;
+        WindowRect.Bottom += Buff->ViewOrigin.Y + Buff->ViewSize.Y - 1;
+    }
+
+    /* See MSDN documentation on SetConsoleWindowInfo about the performed checks */
+    if ( (WindowRect.Left < 0) || (WindowRect.Top < 0)   ||
+         (WindowRect.Right  >= Buff->ScreenBufferSize.X) ||
+         (WindowRect.Bottom >= Buff->ScreenBufferSize.Y) ||
+         (WindowRect.Right  <= WindowRect.Left)          ||
+         (WindowRect.Bottom <= WindowRect.Top) )
+    {
+        ConSrvReleaseScreenBuffer(Buff, TRUE);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Buff->ViewOrigin.X = WindowRect.Left;
+    Buff->ViewOrigin.Y = WindowRect.Top;
+
+    Buff->ViewSize.X = WindowRect.Right - WindowRect.Left + 1;
+    Buff->ViewSize.Y = WindowRect.Bottom - WindowRect.Top + 1;
+
+    ConSrvReleaseScreenBuffer(Buff, TRUE);
+    return STATUS_SUCCESS;
+}
+
+CSR_API(SrvGetConsoleWindow)
+{
+    NTSTATUS Status;
+    PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest;
+    PCONSOLE Console;
+
+    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    GetWindowRequest->WindowHandle = ConioGetConsoleWindowHandle(Console);
+
+    ConSrvReleaseConsole(Console, TRUE);
+    return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleIcon)
+{
+    NTSTATUS Status;
+    PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest;
+    PCONSOLE Console;
+
+    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Status = (ConioChangeIcon(Console, SetIconRequest->WindowIcon)
+                ? STATUS_SUCCESS
+                : STATUS_UNSUCCESSFUL);
+
+    ConSrvReleaseConsole(Console, TRUE);
+    return Status;
+}
+
+CSR_API(SrvGetConsoleSelectionInfo)
+{
+    NTSTATUS Status;
+    PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest;
+    PCONSOLE Console;
+
+    Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+    if (NT_SUCCESS(Status))
+    {
+        memset(&GetSelectionInfoRequest->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
+        if (Console->Selection.dwFlags != 0)
+            GetSelectionInfoRequest->Info = Console->Selection;
+        ConSrvReleaseConsole(Console, TRUE);
+    }
+
+    return Status;
+}
+
+/* EOF */
index 53485d4..07398ea 100644 (file)
 
 /* INCLUDES *******************************************************************/
 
+#define COBJMACROS
+#define NONAMELESSUNION
+
 #include "consrv.h"
 #include "include/conio.h"
 #include "include/console.h"
 #include "include/settings.h"
+#include "conoutput.h"
 #include "guiterm.h"
 #include "guisettings.h"
 #include "resource.h"
 
 #include <windowsx.h>
 
+#include <shlwapi.h>
+#include <shlobj.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -49,6 +56,13 @@ PrivateCsrssManualGuiCheck(LONG Check)
 
 /* GLOBALS ********************************************************************/
 
+typedef struct _GUI_INIT_INFO
+{
+    PCONSOLE_INFO ConsoleInfo;
+    PCONSOLE_START_INFO ConsoleStartInfo;
+    ULONG ProcessId;
+} GUI_INIT_INFO, *PGUI_INIT_INFO;
+
 /**************************************************************\
 \** Define the Console Leader Process for the console window **/
 #define GWLP_CONSOLEWND_ALLOC  (2 * sizeof(LONG_PTR))
@@ -212,7 +226,7 @@ GuiConsolePaste(PGUI_CONSOLE_DATA GuiData);
 static VOID
 GuiConsoleUpdateSelection(PCONSOLE Console, PCOORD coord);
 static VOID WINAPI
-GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region);
+GuiDrawRegion(IN OUT PFRONTEND This, SMALL_RECT* Region);
 static VOID
 GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData);
 
@@ -224,12 +238,12 @@ GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM
     PCONSOLE Console = GuiData->Console;
     PCONSOLE_SCREEN_BUFFER ActiveBuffer;
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
     {
         Ret = FALSE;
         goto Quit;
     }
-    ActiveBuffer = Console->ActiveBuffer;
+    ActiveBuffer = ConDrvGetActiveScreenBuffer(Console);
 
     /*
      * In case the selected menu item belongs to the user-reserved menu id range,
@@ -354,7 +368,7 @@ static VOID
 GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData)
 {
     PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+    PCONSOLE_SCREEN_BUFFER Buff = ConDrvGetActiveScreenBuffer(Console);
     SCROLLINFO sInfo;
 
     DWORD Width, Height;
@@ -421,7 +435,7 @@ GuiConsoleSwitchFullScreen(PGUI_CONSOLE_DATA GuiData)
     PCONSOLE Console = GuiData->Console;
     // DEVMODE dmScreenSettings;
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 
     /* Switch to full-screen or to windowed mode */
     GuiData->GuiInfo.FullScreen = !GuiData->GuiInfo.FullScreen;
@@ -559,7 +573,7 @@ static VOID
 SmallRectToRect(PGUI_CONSOLE_DATA GuiData, PRECT Rect, PSMALL_RECT SmallRect)
 {
     PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+    PCONSOLE_SCREEN_BUFFER Buffer = ConDrvGetActiveScreenBuffer(Console);
     UINT WidthUnit, HeightUnit;
 
     if (GetType(Buffer) == TEXTMODE_BUFFER)
@@ -661,12 +675,12 @@ GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData)
     HDC hDC;
     PAINTSTRUCT ps;
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
     {
         Success = FALSE;
         goto Quit;
     }
-    ActiveBuffer = Console->ActiveBuffer;
+    ActiveBuffer = ConDrvGetActiveScreenBuffer(Console);
 
     hDC = BeginPaint(GuiData->hWindow, &ps);
     if (hDC != NULL &&
@@ -745,9 +759,9 @@ GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM l
     PCONSOLE Console = GuiData->Console;
     PCONSOLE_SCREEN_BUFFER ActiveBuffer;
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 
-    ActiveBuffer = Console->ActiveBuffer;
+    ActiveBuffer = ConDrvGetActiveScreenBuffer(Console);
 
     if (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS)
     {
@@ -903,10 +917,10 @@ Quit:
 }
 
 static VOID
-GuiInvalidateCell(PCONSOLE Console, SHORT x, SHORT y)
+GuiInvalidateCell(IN OUT PFRONTEND This, SHORT x, SHORT y)
 {
     SMALL_RECT CellRect = { x, y, x, y };
-    GuiDrawRegion(Console, &CellRect);
+    GuiDrawRegion(This, &CellRect);
 }
 
 static VOID
@@ -917,13 +931,13 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData)
 
     SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CURSOR_BLINK_TIME, NULL);
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 
-    Buff = Console->ActiveBuffer;
+    Buff = ConDrvGetActiveScreenBuffer(Console);
 
     if (GetType(Buff) == TEXTMODE_BUFFER)
     {
-        GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+        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))
@@ -1006,35 +1020,36 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData)
     LeaveCriticalSection(&Console->Lock);
 }
 
-static VOID
+static BOOL
 GuiConsoleHandleClose(PGUI_CONSOLE_DATA GuiData)
 {
     PCONSOLE Console = GuiData->Console;
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+
+    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.
      */
-    ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT);
+    ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT);
 
     LeaveCriticalSection(&Console->Lock);
+    return FALSE;
 }
 
 static LRESULT
 GuiConsoleHandleNcDestroy(HWND hWnd)
 {
-    // PGUI_CONSOLE_DATA GuiData;
-
     KillTimer(hWnd, CONGUI_UPDATE_TIMER);
     GetSystemMenu(hWnd, TRUE);
 
     /* Free the GuiData registration */
     SetWindowLongPtrW(hWnd, GWLP_USERDATA, (DWORD_PTR)NULL);
-    // GuiData->hWindow = NULL;
 
-    // return 0;
     return DefWindowProcW(hWnd, WM_NCDESTROY, 0, 0);
 }
 
@@ -1042,7 +1057,7 @@ static COORD
 PointToCoord(PGUI_CONSOLE_DATA GuiData, LPARAM lParam)
 {
     PCONSOLE Console = GuiData->Console;
-    PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+    PCONSOLE_SCREEN_BUFFER Buffer = ConDrvGetActiveScreenBuffer(Console);
     COORD Coord;
     UINT  WidthUnit, HeightUnit;
 
@@ -1103,7 +1118,7 @@ GuiConsoleHandleMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM
         goto Quit;
     }
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
     {
         Err = TRUE;
         goto Quit;
@@ -1330,7 +1345,7 @@ GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
     if (OpenClipboard(GuiData->hWindow) == TRUE)
     {
         PCONSOLE Console = GuiData->Console;
-        PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+        PCONSOLE_SCREEN_BUFFER Buffer = ConDrvGetActiveScreenBuffer(Console);
 
         if (GetType(Buffer) == TEXTMODE_BUFFER)
         {
@@ -1358,7 +1373,7 @@ GuiConsolePaste(PGUI_CONSOLE_DATA GuiData)
     if (OpenClipboard(GuiData->hWindow) == TRUE)
     {
         PCONSOLE Console = GuiData->Console;
-        PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+        PCONSOLE_SCREEN_BUFFER Buffer = ConDrvGetActiveScreenBuffer(Console);
 
         if (GetType(Buffer) == TEXTMODE_BUFFER)
         {
@@ -1381,9 +1396,9 @@ GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData, PMINMAXINFO minMaxInfo)
     DWORD windx, windy;
     UINT  WidthUnit, HeightUnit;
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 
-    ActiveBuffer = Console->ActiveBuffer;
+    ActiveBuffer = ConDrvGetActiveScreenBuffer(Console);
 
     if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
     {
@@ -1419,12 +1434,12 @@ GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
 {
     PCONSOLE Console = GuiData->Console;
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
 
     if ((GuiData->WindowSizeLock == FALSE) &&
         (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED))
     {
-        PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+        PCONSOLE_SCREEN_BUFFER Buff = ConDrvGetActiveScreenBuffer(Console);
         DWORD windx, windy, charx, chary;
         UINT  WidthUnit, HeightUnit;
 
@@ -1525,9 +1540,9 @@ GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData, UINT uMsg, WPARAM wParam)
     int old_pos, Maximum;
     PSHORT pShowXY;
 
-    if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
 
-    Buff = Console->ActiveBuffer;
+    Buff = ConDrvGetActiveScreenBuffer(Console);
 
     if (uMsg == WM_HSCROLL)
     {
@@ -1659,7 +1674,7 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
      * If there is no data, just go away.
      */
     GuiData = GuiGetGuiData(hWnd);
-    if (GuiData == NULL) return 0;
+    if (GuiData == NULL) return DefWindowProcW(hWnd, msg, wParam, lParam);
 
     /*
      * Just retrieve a pointer to the console in case somebody needs it.
@@ -1678,7 +1693,7 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
         }
 
         case WM_CLOSE:
-            GuiConsoleHandleClose(GuiData);
+            if (GuiConsoleHandleClose(GuiData)) goto Default;
             break;
 
         case WM_PAINT:
@@ -1846,7 +1861,7 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
                                 IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));
             }
 
-            if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+            if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
             {
                 GuiSendMenuEvent(Console, WM_INITMENU);
                 LeaveCriticalSection(&Console->Lock);
@@ -1858,7 +1873,7 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
         {
             if (HIWORD(wParam) == 0xFFFF) // Allow all the menu flags
             {
-                if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+                if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
                 {
                     GuiSendMenuEvent(Console, WM_MENUSELECT);
                     LeaveCriticalSection(&Console->Lock);
@@ -1877,7 +1892,7 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
         case WM_SETFOCUS:
         case WM_KILLFOCUS:
         {
-            if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+            if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
             {
                 INPUT_RECORD er;
                 er.EventType = FOCUS_EVENT;
@@ -1913,7 +1928,7 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
         case PM_APPLY_CONSOLE_INFO:
         {
-            if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+            if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
             {
                 GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam);
                 LeaveCriticalSection(&Console->Lock);
@@ -2219,9 +2234,190 @@ GuiInit(VOID)
  ******************************************************************************/
 
 static VOID WINAPI
-GuiCleanupConsole(PCONSOLE Console)
+GuiDeinitFrontEnd(IN OUT PFRONTEND This);
+
+NTSTATUS NTAPI
+GuiInitFrontEnd(IN OUT PFRONTEND This,
+                IN PCONSOLE Console)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    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)
+        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;
+
+
+    /* Terminal data allocation */
+    GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
+    if (!GuiData)
+    {
+        DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+    /* HACK */ Console->TermIFace.Data = (PVOID)GuiData; /* HACK */
+    GuiData->Console = Console;
+    GuiData->hWindow = NULL;
+
+    /* The console can be resized */
+    Console->FixedSize = FALSE;
+
+    InitializeCriticalSection(&GuiData->Lock);
+
+
+    /*
+     * Load terminal settings
+     */
+
+    /* 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->ShowWindow;
+        }
+        if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
+        {
+            TermInfo.AutoPosition = FALSE;
+            TermInfo.WindowOrigin = ConsoleStartInfo->ConsoleWindowOrigin;
+        }
+        if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
+        {
+            TermInfo.FullScreen = TRUE;
+        }
+    }
+
+
+    /*
+     * Set up GUI data
+     */
+
+    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;
+        }
+    }
+
+    /* Mouse is shown by default with its default cursor shape */
+    GuiData->hCursor = ghDefaultCursor;
+    GuiData->MouseCursorRefCount = 0;
+
+    /* A priori don't ignore mouse signals */
+    GuiData->IgnoreNextMouseSignal = FALSE;
+
+    /* Close button and the corresponding system menu item are enabled by default */
+    GuiData->IsCloseButtonEnabled = TRUE;
+
+    /* There is no user-reserved menu id range by default */
+    GuiData->cmdIdLow = GuiData->cmdIdHigh = 0;
+
+    /*
+     * 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);
+
+    DPRINT("GUI - Checkpoint\n");
+
+    /* Create the terminal window */
+    PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, GuiData->GuiInfo.ShowWindow, (LPARAM)GuiData);
+
+    /* Wait until initialization has finished */
+    WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
+    DPRINT("OK we created the console window\n");
+    CloseHandle(GuiData->hGuiInitEvent);
+    GuiData->hGuiInitEvent = NULL;
+
+    /* Check whether we really succeeded in initializing the terminal window */
+    if (GuiData->hWindow == NULL)
+    {
+        DPRINT("GuiInitConsole - We failed at creating a new terminal window\n");
+        GuiDeinitFrontEnd(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 WINAPI
+GuiDeinitFrontEnd(IN OUT PFRONTEND This)
+{
+    PGUI_CONSOLE_DATA GuiData = This->Data;
 
     SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
 
@@ -2238,17 +2434,18 @@ GuiCleanupConsole(PCONSOLE Console)
         DestroyIcon(GuiData->hIconSm);
     }
 
-    Console->TermIFace.Data = NULL;
+    This->Data = NULL;
     DeleteCriticalSection(&GuiData->Lock);
     ConsoleFreeHeap(GuiData);
 
-    DPRINT("Quit GuiCleanupConsole\n");
+    DPRINT("Quit GuiDeinitFrontEnd\n");
 }
 
 static VOID WINAPI
-GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
+GuiDrawRegion(IN OUT PFRONTEND This,
+              SMALL_RECT* Region)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
     RECT RegionRect;
 
     SmallRectToRect(GuiData, &RegionRect, Region);
@@ -2257,15 +2454,22 @@ GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
 }
 
 static VOID WINAPI
-GuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
-               UINT ScrolledLines, PWCHAR Buffer, UINT Length)
+GuiWriteStream(IN OUT PFRONTEND This,
+               SMALL_RECT* Region,
+               SHORT CursorStartX,
+               SHORT CursorStartY,
+               UINT ScrolledLines,
+               PWCHAR Buffer,
+               UINT Length)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
-    PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PCONSOLE_SCREEN_BUFFER Buff;
     SHORT CursorEndX, CursorEndY;
     RECT ScrollRect;
 
     if (NULL == GuiData || NULL == GuiData->hWindow) return;
+
+    Buff = ConDrvGetActiveScreenBuffer(GuiData->Console);
     if (GetType(Buff) != TEXTMODE_BUFFER) return;
 
     if (0 != ScrolledLines)
@@ -2285,12 +2489,12 @@ GuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT C
                        SW_INVALIDATE);
     }
 
-    GuiDrawRegion(Console, Region);
+    GuiDrawRegion(This, Region);
 
     if (CursorStartX < Region->Left || Region->Right < CursorStartX
             || CursorStartY < Region->Top || Region->Bottom < CursorStartY)
     {
-        GuiInvalidateCell(Console, CursorStartX, CursorStartY);
+        GuiInvalidateCell(This, CursorStartX, CursorStartY);
     }
 
     CursorEndX = Buff->CursorPosition.X;
@@ -2299,7 +2503,7 @@ GuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT C
             || CursorEndY < Region->Top || Region->Bottom < CursorEndY)
             && (CursorEndX != CursorStartX || CursorEndY != CursorStartY))
     {
-        GuiInvalidateCell(Console, CursorEndX, CursorEndY);
+        GuiInvalidateCell(This, CursorEndX, CursorEndY);
     }
 
     // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
@@ -2309,34 +2513,42 @@ GuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT C
 }
 
 static BOOL WINAPI
-GuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
+GuiSetCursorInfo(IN OUT PFRONTEND This,
+                 PCONSOLE_SCREEN_BUFFER Buff)
 {
-    if (Console->ActiveBuffer == Buff)
+    PGUI_CONSOLE_DATA GuiData = This->Data;
+
+    if (ConDrvGetActiveScreenBuffer(GuiData->Console) == Buff)
     {
-        GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+        GuiInvalidateCell(This, Buff->CursorPosition.X, Buff->CursorPosition.Y);
     }
 
     return TRUE;
 }
 
 static BOOL WINAPI
-GuiSetScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, SHORT OldCursorX, SHORT OldCursorY)
+GuiSetScreenInfo(IN OUT PFRONTEND This,
+                 PCONSOLE_SCREEN_BUFFER Buff,
+                 SHORT OldCursorX,
+                 SHORT OldCursorY)
 {
-    if (Console->ActiveBuffer == Buff)
+    PGUI_CONSOLE_DATA GuiData = This->Data;
+
+    if (ConDrvGetActiveScreenBuffer(GuiData->Console) == Buff)
     {
         /* Redraw char at old position (remove cursor) */
-        GuiInvalidateCell(Console, OldCursorX, OldCursorY);
+        GuiInvalidateCell(This, OldCursorX, OldCursorY);
         /* Redraw char at new position (show cursor) */
-        GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+        GuiInvalidateCell(This, Buff->CursorPosition.X, Buff->CursorPosition.Y);
     }
 
     return TRUE;
 }
 
 static VOID WINAPI
-GuiResizeTerminal(PCONSOLE Console)
+GuiResizeTerminal(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
 
     /* Resize the window to the user's values */
     // GuiData->WindowSizeLock = TRUE;
@@ -2348,7 +2560,12 @@ GuiResizeTerminal(PCONSOLE Console)
 }
 
 static BOOL WINAPI
-GuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD ShiftState, UINT VirtualKeyCode, BOOL Down)
+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))
@@ -2361,12 +2578,13 @@ GuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD Shift
 }
 
 static BOOL WINAPI
-GuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor);
+GuiSetMouseCursor(IN OUT PFRONTEND This,
+                  HCURSOR hCursor);
 
 static VOID WINAPI
-GuiRefreshInternalInfo(PCONSOLE Console)
+GuiRefreshInternalInfo(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
 
     /* Update the console leader information held by the window */
     SetConsoleWndConsoleLeaderCID(GuiData);
@@ -2382,21 +2600,22 @@ GuiRefreshInternalInfo(PCONSOLE Console)
 
     /* Mouse is shown by default with its default cursor shape */
     GuiData->MouseCursorRefCount = 0; // Reinitialize the reference counter
-    GuiSetMouseCursor(Console, NULL);
+    GuiSetMouseCursor(This, NULL);
 }
 
 static VOID WINAPI
-GuiChangeTitle(PCONSOLE Console)
+GuiChangeTitle(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
     // PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0);
-    SetWindowText(GuiData->hWindow, Console->Title.Buffer);
+    SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
 }
 
 static BOOL WINAPI
-GuiChangeIcon(PCONSOLE Console, HICON hWindowIcon)
+GuiChangeIcon(IN OUT PFRONTEND This,
+              HICON hWindowIcon)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
     HICON hIcon, hIconSm;
 
     if (hWindowIcon == NULL)
@@ -2438,16 +2657,18 @@ GuiChangeIcon(PCONSOLE Console, HICON hWindowIcon)
 }
 
 static HWND WINAPI
-GuiGetConsoleWindowHandle(PCONSOLE Console)
+GuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
     return GuiData->hWindow;
 }
 
 static VOID WINAPI
-GuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize)
+GuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
+                               PCOORD pSize)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
+    PCONSOLE_SCREEN_BUFFER ActiveBuffer;
     RECT WorkArea;
     LONG width, height;
     UINT WidthUnit, HeightUnit;
@@ -2460,14 +2681,15 @@ GuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize)
         return;
     }
 
-    if (Console->ActiveBuffer)
+    ActiveBuffer = ConDrvGetActiveScreenBuffer(GuiData->Console);
+    if (ActiveBuffer)
     {
-        if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
+        if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
         {
             WidthUnit  = GuiData->CharWidth ;
             HeightUnit = GuiData->CharHeight;
         }
-        else /* if (GetType(Console->ActiveBuffer) == GRAPHICS_BUFFER) */
+        else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
         {
             WidthUnit  = 1;
             HeightUnit = 1;
@@ -2494,9 +2716,9 @@ GuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize)
 }
 
 static ULONG WINAPI
-GuiGetDisplayMode(PCONSOLE Console)
+GuiGetDisplayMode(IN OUT PFRONTEND This)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
     ULONG DisplayMode = 0;
 
     if (GuiData->GuiInfo.FullScreen)
@@ -2508,9 +2730,10 @@ GuiGetDisplayMode(PCONSOLE Console)
 }
 
 static BOOL WINAPI
-GuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
+GuiSetDisplayMode(IN OUT PFRONTEND This,
+                  ULONG NewMode)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
 
     if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
         return FALSE;
@@ -2521,9 +2744,10 @@ GuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
 }
 
 static INT WINAPI
-GuiShowMouseCursor(PCONSOLE Console, BOOL Show)
+GuiShowMouseCursor(IN OUT PFRONTEND This,
+                   BOOL Show)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
 
     /* Set the reference count */
     if (Show) ++GuiData->MouseCursorRefCount;
@@ -2536,9 +2760,10 @@ GuiShowMouseCursor(PCONSOLE Console, BOOL Show)
 }
 
 static BOOL WINAPI
-GuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor)
+GuiSetMouseCursor(IN OUT PFRONTEND This,
+                  HCURSOR hCursor)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
 
     /*
      * Set the cursor's handle. If the given handle is NULL,
@@ -2553,9 +2778,11 @@ GuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor)
 }
 
 static HMENU WINAPI
-GuiMenuControl(PCONSOLE Console, UINT cmdIdLow, UINT cmdIdHigh)
+GuiMenuControl(IN OUT PFRONTEND This,
+               UINT cmdIdLow,
+               UINT cmdIdHigh)
 {
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
 
     GuiData->cmdIdLow  = cmdIdLow ;
     GuiData->cmdIdHigh = cmdIdHigh;
@@ -2564,7 +2791,8 @@ GuiMenuControl(PCONSOLE Console, UINT cmdIdLow, UINT cmdIdHigh)
 }
 
 static BOOL WINAPI
-GuiSetMenuClose(PCONSOLE Console, BOOL Enable)
+GuiSetMenuClose(IN OUT PFRONTEND This,
+                BOOL Enable)
 {
     /*
      * NOTE: See http://www.mail-archive.com/harbour@harbour-project.org/msg27509.html
@@ -2572,7 +2800,7 @@ GuiSetMenuClose(PCONSOLE Console, BOOL Enable)
      * for more information.
      */
 
-    PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+    PGUI_CONSOLE_DATA GuiData = This->Data;
     HMENU hSysMenu = GetSystemMenu(GuiData->hWindow, FALSE);
 
     if (hSysMenu == NULL) return FALSE;
@@ -2585,7 +2813,8 @@ GuiSetMenuClose(PCONSOLE Console, BOOL Enable)
 
 static FRONTEND_VTBL GuiVtbl =
 {
-    GuiCleanupConsole,
+    GuiInitFrontEnd,
+    GuiDeinitFrontEnd,
     GuiDrawRegion,
     GuiWriteStream,
     GuiSetCursorInfo,
@@ -2605,164 +2834,167 @@ static FRONTEND_VTBL GuiVtbl =
     GuiSetMenuClose,
 };
 
-NTSTATUS FASTCALL
-GuiInitConsole(PCONSOLE Console,
-               /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo,
-               PCONSOLE_INFO ConsoleInfo,
-               DWORD ProcessId,
-               LPCWSTR IconPath,
-               INT IconIndex)
+
+static BOOL
+LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+                         IN OUT PCONSOLE_INFO ConsoleInfo)
 {
-    PGUI_CONSOLE_DATA GuiData;
-    GUI_CONSOLE_INFO TermInfo;
-    SIZE_T Length = 0;
+#define PATH_SEPARATOR L'\\'
 
-    if (Console == NULL || ConsoleInfo == NULL)
-        return STATUS_INVALID_PARAMETER;
+    BOOL    RetVal   = FALSE;
+    HRESULT hRes     = S_OK;
+    LPWSTR  LinkName = NULL;
+    SIZE_T  Length   = 0;
 
-    /* Initialize the GUI terminal emulator */
-    if (!GuiInit()) return STATUS_UNSUCCESSFUL;
+    if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+        return FALSE;
 
-    /* Initialize the console */
-    Console->TermIFace.Vtbl = &GuiVtbl;
+    ConsoleStartInfo->IconPath[0] = L'\0';
+    ConsoleStartInfo->IconIndex   = 0;
 
-    GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
-    if (!GuiData)
+    /* 1- Find the last path separator if any */
+    LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
+    if (LinkName == NULL)
     {
-        DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
-        return STATUS_UNSUCCESSFUL;
+        LinkName = ConsoleStartInfo->ConsoleTitle;
     }
-    Console->TermIFace.Data = (PVOID)GuiData;
-    GuiData->Console = Console;
-    GuiData->hWindow = NULL;
-
-    /* The console can be resized */
-    Console->FixedSize = FALSE;
-
-    InitializeCriticalSection(&GuiData->Lock);
-
-
-    /*
-     * Load the terminal settings
-     */
-
-    /***********************************************
-     * Adapted from ConSrvInitConsole in console.c *
-     ***********************************************/
-
-    /* 1. Load the default settings */
-    GuiConsoleGetDefaultSettings(&TermInfo, ProcessId);
-
-    /* 2. Load the remaining console settings via the registry. */
-    if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+    else
     {
-        /* Load the terminal infos from the registry. */
-        GuiConsoleReadUserSettings(&TermInfo, ConsoleInfo->ConsoleTitle, ProcessId);
+        /* Skip the path separator */
+        ++LinkName;
+    }
 
-        /*
-         * 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->ShowWindow;
-        }
-        if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
-        {
-            TermInfo.AutoPosition = FALSE;
-            TermInfo.WindowOrigin = ConsoleStartInfo->ConsoleWindowOrigin;
-        }
-        if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
+    /* 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;
+
+    /* 3- It may be a link. Try to retrieve some properties */
+    hRes = CoInitialize(NULL);
+    if (SUCCEEDED(hRes))
+    {
+        /* 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))
         {
-            TermInfo.FullScreen = TRUE;
+            /* Get a pointer to the IPersistFile interface */
+            IPersistFile* ppf = NULL;
+            hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
+            if (SUCCEEDED(hRes))
+            {
+                /* 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->ShowWindow = (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);
+            }
+            IShellLinkW_Release(pshl);
         }
     }
+    CoUninitialize();
 
+    return RetVal;
+}
 
-    /*
-     * Set up the GUI data
-     */
+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;
 
-    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;
+    if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleStartInfo == NULL)
+        return STATUS_INVALID_PARAMETER;
 
-    /* Initialize the icon handles to their default values */
-    GuiData->hIcon   = ghDefaultIcon;
-    GuiData->hIconSm = ghDefaultIconSm;
+    /* Initialize GUI terminal emulator common functionalities */
+    if (!GuiInit()) return STATUS_UNSUCCESSFUL;
 
-    /* Get the associated icon, if any */
-    if (IconPath == NULL || *IconPath == L'\0')
-    {
-        IconPath  = ConsoleStartInfo->AppPath;
-        IconIndex = 0;
-    }
-    DPRINT("IconPath = %S ; IconIndex = %lu\n", (IconPath ? IconPath : L"n/a"), IconIndex);
-    if (IconPath)
+    /*
+     * 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)
     {
-        HICON hIcon = NULL, hIconSm = NULL;
-        PrivateExtractIconExW(IconPath,
-                              IconIndex,
-                              &hIcon,
-                              &hIconSm,
-                              1);
-        DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
-        if (hIcon != NULL)
+        if (!LoadShellLinkConsoleInfo(ConsoleStartInfo, ConsoleInfo))
         {
-            DPRINT("Effectively set the icons\n");
-            GuiData->hIcon   = hIcon;
-            GuiData->hIconSm = hIconSm;
+            ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
         }
     }
 
-    /* Mouse is shown by default with its default cursor shape */
-    GuiData->hCursor = ghDefaultCursor;
-    GuiData->MouseCursorRefCount = 0;
-
-    /* A priori don't ignore mouse signals */
-    GuiData->IgnoreNextMouseSignal = FALSE;
-
-    /* Close button and the corresponding system menu item are enabled by default */
-    GuiData->IsCloseButtonEnabled = TRUE;
-
-    /* There is no user-reserved menu id range by default */
-    GuiData->cmdIdLow = GuiData->cmdIdHigh = 0;
-
     /*
-     * 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.
+     * Initialize a private initialization info structure for later use.
+     * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
      */
-    GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_INIT_INFO));
+    if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
 
-    /* Create the terminal window */
-    PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, GuiData->GuiInfo.ShowWindow, (LPARAM)GuiData);
+    // HACK: We suppose that the pointers will be valid in GuiInitFrontEnd...
+    GuiInitInfo->ConsoleInfo      = ConsoleInfo;
+    GuiInitInfo->ConsoleStartInfo = ConsoleStartInfo;
+    GuiInitInfo->ProcessId        = ProcessId;
 
-    /* Wait until initialization has finished */
-    WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
-    DPRINT("OK we created the console window\n");
-    CloseHandle(GuiData->hGuiInitEvent);
-    GuiData->hGuiInitEvent = NULL;
+    /* Finally, initialize the frontend structure */
+    FrontEnd->Vtbl    = &GuiVtbl;
+    FrontEnd->Data    = NULL;
+    FrontEnd->OldData = GuiInitInfo;
 
-    /* Check whether we really succeeded in initializing the terminal window */
-    if (GuiData->hWindow == NULL)
-    {
-        DPRINT("GuiInitConsole - We failed at creating a new terminal window\n");
-        // ConioCleanupConsole(Console);
-        GuiCleanupConsole(Console);
-        return STATUS_UNSUCCESSFUL;
-    }
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
+{
+    if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
+
+    if (FrontEnd->Data)    GuiDeinitFrontEnd(FrontEnd);
+    if (FrontEnd->OldData) ConsoleFreeHeap(FrontEnd->OldData);
 
     return STATUS_SUCCESS;
 }
diff --git a/reactos/win32ss/user/consrv/frontends/input.c b/reactos/win32ss/user/consrv/frontends/input.c
new file mode 100644 (file)
index 0000000..b457ce8
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Console Server DLL
+ * FILE:            win32ss/user/consrv/frontends/input.c
+ * PURPOSE:         Common Front-Ends Input functions
+ * PROGRAMMERS:     Jeffrey Morlan
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "coninput.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static DWORD FASTCALL
+ConioGetShiftState(PBYTE KeyState, LPARAM lParam)
+{
+    DWORD ssOut = 0;
+
+    if (KeyState[VK_CAPITAL] & 0x01)
+        ssOut |= CAPSLOCK_ON;
+
+    if (KeyState[VK_NUMLOCK] & 0x01)
+        ssOut |= NUMLOCK_ON;
+
+    if (KeyState[VK_SCROLL] & 0x01)
+        ssOut |= SCROLLLOCK_ON;
+
+    if (KeyState[VK_SHIFT] & 0x80)
+        ssOut |= SHIFT_PRESSED;
+
+    if (KeyState[VK_LCONTROL] & 0x80)
+        ssOut |= LEFT_CTRL_PRESSED;
+    if (KeyState[VK_RCONTROL] & 0x80)
+        ssOut |= RIGHT_CTRL_PRESSED;
+
+    if (KeyState[VK_LMENU] & 0x80)
+        ssOut |= LEFT_ALT_PRESSED;
+    if (KeyState[VK_RMENU] & 0x80)
+        ssOut |= RIGHT_ALT_PRESSED;
+
+    /* See WM_CHAR MSDN documentation for instance */
+    if (lParam & 0x01000000)
+        ssOut |= ENHANCED_KEY;
+
+    return ssOut;
+}
+
+VOID WINAPI
+ConioProcessKey(PCONSOLE Console, MSG* msg)
+{
+    static BYTE KeyState[256] = { 0 };
+    /* MSDN mentions that you should use the last virtual key code received
+     * when putting a virtual key identity to a WM_CHAR message since multiple
+     * or translated keys may be involved. */
+    static UINT LastVirtualKey = 0;
+    DWORD ShiftState;
+    WCHAR UnicodeChar;
+    UINT VirtualKeyCode;
+    UINT VirtualScanCode;
+    BOOL Down = FALSE;
+    BOOLEAN Fake;          // synthesized, not a real event
+    BOOLEAN NotChar;       // message should not be used to return a character
+
+    if (NULL == Console)
+    {
+        DPRINT1("No Active Console!\n");
+        return;
+    }
+
+    VirtualScanCode = HIWORD(msg->lParam) & 0xFF;
+    Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
+           msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
+
+    GetKeyboardState(KeyState);
+    ShiftState = ConioGetShiftState(KeyState, msg->lParam);
+
+    if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
+    {
+        VirtualKeyCode = LastVirtualKey;
+        UnicodeChar = msg->wParam;
+    }
+    else
+    {
+        WCHAR Chars[2];
+        INT RetChars = 0;
+
+        VirtualKeyCode = msg->wParam;
+        RetChars = ToUnicodeEx(VirtualKeyCode,
+                               VirtualScanCode,
+                               KeyState,
+                               Chars,
+                               2,
+                               0,
+                               NULL);
+        UnicodeChar = (1 == RetChars ? Chars[0] : 0);
+    }
+
+    if (ConioProcessKeyCallback(Console,
+                                msg,
+                                KeyState[VK_MENU],
+                                ShiftState,
+                                VirtualKeyCode,
+                                Down))
+    {
+        return;
+    }
+
+    Fake = UnicodeChar &&
+            (msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
+             msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
+    NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
+    if (NotChar) LastVirtualKey = msg->wParam;
+
+    DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
+           Down ? "down" : "up  ",
+           (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
+           "char" : "key ",
+           Fake ? "fake" : "real",
+           NotChar ? "notc" : "char",
+           VirtualScanCode,
+           VirtualKeyCode,
+           (UnicodeChar >= L' ') ? UnicodeChar : L'.',
+           ShiftState);
+
+    if (Fake) return;
+
+    /* Send the key press to the console driver */
+    ConDrvProcessKey(Console,
+                     Down,
+                     VirtualKeyCode,
+                     VirtualScanCode,
+                     UnicodeChar,
+                     ShiftState,
+                     KeyState[VK_CONTROL]);
+}
+
+/* EOF */
index 022c844..451ca9a 100644 (file)
@@ -9,6 +9,8 @@
  *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
  */
 
+#ifdef TUITERM_COMPILE
+
 #include "consrv.h"
 #include "include/conio.h"
 #include "include/console.h"
@@ -274,7 +276,7 @@ TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
         case WM_KEYUP:
         case WM_SYSKEYUP:
         {
-            if (ConSrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
+            if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
             {
                 MSG Message;
                 Message.hwnd = hWnd;
@@ -290,7 +292,7 @@ TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
         case WM_ACTIVATE:
         {
-            if (ConSrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
+            if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
             {
                 if (LOWORD(wParam) != WA_INACTIVE)
                 {
@@ -440,9 +442,90 @@ Quit:
  ******************************************************************************/
 
 static VOID WINAPI
-TuiCleanupConsole(PCONSOLE Console)
+TuiDeinitFrontEnd(IN OUT PFRONTEND This /*,
+                  IN PCONSOLE Console */);
+
+NTSTATUS NTAPI
+TuiInitFrontEnd(IN OUT PFRONTEND This,
+                IN PCONSOLE Console)
 {
-    PTUI_CONSOLE_DATA TuiData = Console->TermIFace.Data;
+    PTUI_CONSOLE_DATA TuiData;
+    HANDLE ThreadHandle;
+
+    if (This == NULL || Console == NULL)
+        return STATUS_INVALID_PARAMETER;
+
+    // if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
+        // return STATUS_INVALID_PARAMETER;
+
+    // /* Initialize the console */
+    // Console->TermIFace.Vtbl = &TuiVtbl;
+
+    TuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(TUI_CONSOLE_DATA));
+    if (!TuiData)
+    {
+        DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+    // Console->TermIFace.Data = (PVOID)TuiData;
+    TuiData->Console = Console;
+    TuiData->hWindow = NULL;
+
+    InitializeCriticalSection(&TuiData->Lock);
+
+    /*
+     * HACK: Resize the console since we don't support for now changing
+     * the console size when we display it with the hardware.
+     */
+    // Console->ConsoleSize = PhysicalConsoleSize;
+    // ConioResizeBuffer(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), PhysicalConsoleSize);
+
+    // /* The console cannot be resized anymore */
+    // Console->FixedSize = TRUE; // MUST be placed AFTER the call to ConioResizeBuffer !!
+    // // ConioResizeTerminal(Console);
+
+    /*
+     * Contrary to what we do in the GUI front-end, here we create
+     * an input thread for each console. It will dispatch all the
+     * input messages to the proper console (on the GUI it is done
+     * via the default GUI dispatch thread).
+     */
+    ThreadHandle = CreateThread(NULL,
+                                0,
+                                TuiConsoleThread,
+                                (PVOID)TuiData,
+                                0,
+                                NULL);
+    if (NULL == ThreadHandle)
+    {
+        DPRINT1("CONSRV: Unable to create console thread\n");
+        // TuiDeinitFrontEnd(Console);
+        TuiDeinitFrontEnd(This);
+        return STATUS_UNSUCCESSFUL;
+    }
+    CloseHandle(ThreadHandle);
+
+    /*
+     * Insert the newly created console in the list of virtual consoles
+     * and activate it (give it the focus).
+     */
+    EnterCriticalSection(&ActiveVirtConsLock);
+    InsertTailList(&VirtConsList, &TuiData->Entry);
+    ActiveConsole = TuiData;
+    LeaveCriticalSection(&ActiveVirtConsLock);
+
+    /* Finally, initialize the frontend structure */
+    This->Data = TuiData;
+    This->OldData = NULL;
+
+    return STATUS_SUCCESS;
+}
+
+static VOID WINAPI
+TuiDeinitFrontEnd(IN OUT PFRONTEND This)
+{
+    // PCONSOLE Console = This->Console;
+    PTUI_CONSOLE_DATA TuiData = This->Data; // Console->TermIFace.Data;
 
     /* Close the notification window */
     DestroyWindow(TuiData->hWindow);
@@ -473,13 +556,15 @@ TuiCleanupConsole(PCONSOLE Console)
     /* Switch to the next console */
     if (NULL != ActiveConsole) ConioDrawConsole(ActiveConsole->Console);
 
-    Console->TermIFace.Data = NULL;
+    // Console->TermIFace.Data = NULL;
+    This->Data = NULL;
     DeleteCriticalSection(&TuiData->Lock);
     ConsoleFreeHeap(TuiData);
 }
 
 static VOID WINAPI
-TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
+TuiDrawRegion(IN OUT PFRONTEND This,
+              SMALL_RECT* Region)
 {
     DWORD BytesReturned;
     PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
@@ -517,8 +602,13 @@ TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
 }
 
 static VOID WINAPI
-TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
-               UINT ScrolledLines, PWCHAR Buffer, UINT Length)
+TuiWriteStream(IN OUT PFRONTEND This,
+               SMALL_RECT* Region,
+               SHORT CursorStartX,
+               SHORT CursorStartY,
+               UINT ScrolledLines,
+               PWCHAR Buffer,
+               UINT Length)
 {
     PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
     PCHAR NewBuffer;
@@ -546,7 +636,8 @@ TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT C
 }
 
 static BOOL WINAPI
-TuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
+TuiSetCursorInfo(IN OUT PFRONTEND This,
+                 PCONSOLE_SCREEN_BUFFER Buff)
 {
     CONSOLE_CURSOR_INFO Info;
     DWORD BytesReturned;
@@ -567,7 +658,10 @@ TuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
 }
 
 static BOOL WINAPI
-TuiSetScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, SHORT OldCursorX, SHORT OldCursorY)
+TuiSetScreenInfo(IN OUT PFRONTEND This,
+                 PCONSOLE_SCREEN_BUFFER Buff,
+                 SHORT OldCursorX,
+                 SHORT OldCursorY)
 {
     CONSOLE_SCREEN_BUFFER_INFO Info;
     DWORD BytesReturned;
@@ -590,12 +684,17 @@ TuiSetScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, SHORT OldCursorX
 }
 
 static VOID WINAPI
-TuiResizeTerminal(PCONSOLE Console)
+TuiResizeTerminal(IN OUT PFRONTEND This)
 {
 }
 
 static BOOL WINAPI
-TuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD ShiftState, UINT VirtualKeyCode, BOOL Down)
+TuiProcessKeyCallback(IN OUT PFRONTEND This,
+                      MSG* msg,
+                      BYTE KeyStateMenu,
+                      DWORD ShiftState,
+                      UINT VirtualKeyCode,
+                      BOOL Down)
 {
     if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) &&
         VK_TAB == VirtualKeyCode)
@@ -616,43 +715,46 @@ TuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD Shift
 }
 
 static VOID WINAPI
-TuiRefreshInternalInfo(PCONSOLE Console)
+TuiRefreshInternalInfo(IN OUT PFRONTEND This)
 {
 }
 
 static VOID WINAPI
-TuiChangeTitle(PCONSOLE Console)
+TuiChangeTitle(IN OUT PFRONTEND This)
 {
 }
 
 static BOOL WINAPI
-TuiChangeIcon(PCONSOLE Console, HICON hWindowIcon)
+TuiChangeIcon(IN OUT PFRONTEND This,
+              HICON hWindowIcon)
 {
     return TRUE;
 }
 
 static HWND WINAPI
-TuiGetConsoleWindowHandle(PCONSOLE Console)
+TuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
 {
-    PTUI_CONSOLE_DATA TuiData = Console->TermIFace.Data;
+    PTUI_CONSOLE_DATA TuiData = This->Data;
     return TuiData->hWindow;
 }
 
 static VOID WINAPI
-TuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize)
+TuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
+                               PCOORD pSize)
 {
     if (!pSize) return;
     *pSize = PhysicalConsoleSize;
 }
 
 static ULONG WINAPI
-TuiGetDisplayMode(PCONSOLE Console)
+TuiGetDisplayMode(IN OUT PFRONTEND This)
 {
     return CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN;
 }
 
 static BOOL WINAPI
-TuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
+TuiSetDisplayMode(IN OUT PFRONTEND This,
+                  ULONG NewMode)
 {
     // if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
     //     return FALSE;
@@ -660,32 +762,38 @@ TuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
 }
 
 static INT WINAPI
-TuiShowMouseCursor(PCONSOLE Console, BOOL Show)
+TuiShowMouseCursor(IN OUT PFRONTEND This,
+                   BOOL Show)
 {
     return 0;
 }
 
 static BOOL WINAPI
-TuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor)
+TuiSetMouseCursor(IN OUT PFRONTEND This,
+                  HCURSOR hCursor)
 {
     return TRUE;
 }
 
 static HMENU WINAPI
-TuiMenuControl(PCONSOLE Console, UINT cmdIdLow, UINT cmdIdHigh)
+TuiMenuControl(IN OUT PFRONTEND This,
+               UINT cmdIdLow,
+               UINT cmdIdHigh)
 {
     return NULL;
 }
 
 static BOOL WINAPI
-TuiSetMenuClose(PCONSOLE Console, BOOL Enable)
+TuiSetMenuClose(IN OUT PFRONTEND This,
+                BOOL Enable)
 {
     return TRUE;
 }
 
 static FRONTEND_VTBL TuiVtbl =
 {
-    TuiCleanupConsole,
+    TuiInitFrontEnd,
+    TuiDeinitFrontEnd,
     TuiDrawRegion,
     TuiWriteStream,
     TuiSetCursorInfo,
@@ -705,80 +813,49 @@ static FRONTEND_VTBL TuiVtbl =
     TuiSetMenuClose,
 };
 
-NTSTATUS FASTCALL
-TuiInitConsole(PCONSOLE Console,
-               /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo,
-               PCONSOLE_INFO ConsoleInfo,
-               DWORD ProcessId)
+// static BOOL
+// DtbgIsDesktopVisible(VOID)
+// {
+    // return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
+// }
+static BOOLEAN
+IsConsoleMode(VOID)
 {
-    PTUI_CONSOLE_DATA TuiData;
-    HANDLE ThreadHandle;
+    return (BOOLEAN)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE);
+}
 
-    if (Console == NULL || ConsoleInfo == NULL)
+NTSTATUS NTAPI
+TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+                IN OUT PCONSOLE_INFO ConsoleInfo,
+                IN OUT PVOID ExtraConsoleInfo,
+                IN ULONG ProcessId)
+{
+    if (FrontEnd == NULL || ConsoleInfo == NULL)
         return STATUS_INVALID_PARAMETER;
 
-    if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
-        return STATUS_INVALID_PARAMETER;
+    /* We must be in console mode already */
+    if (!IsConsoleMode()) return STATUS_UNSUCCESSFUL;
 
     /* Initialize the TUI terminal emulator */
-    if (!TuiInit(Console->CodePage)) return STATUS_UNSUCCESSFUL;
-
-    /* Initialize the console */
-    Console->TermIFace.Vtbl = &TuiVtbl;
-
-    TuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(TUI_CONSOLE_DATA));
-    if (!TuiData)
-    {
-        DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
-        return STATUS_UNSUCCESSFUL;
-    }
-    Console->TermIFace.Data = (PVOID)TuiData;
-    TuiData->Console = Console;
-    TuiData->hWindow = NULL;
-
-    InitializeCriticalSection(&TuiData->Lock);
-
-    /*
-     * HACK: Resize the console since we don't support for now changing
-     * the console size when we display it with the hardware.
-     */
-    Console->ConsoleSize = PhysicalConsoleSize;
-    ConioResizeBuffer(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), PhysicalConsoleSize);
+    if (!TuiInit(ConsoleInfo->CodePage)) return STATUS_UNSUCCESSFUL;
 
-    /* The console cannot be resized anymore */
-    Console->FixedSize = TRUE; // MUST be placed AFTER the call to ConioResizeBuffer !!
-    // ConioResizeTerminal(Console);
+    /* Finally, initialize the frontend structure */
+    FrontEnd->Vtbl    = &TuiVtbl;
+    FrontEnd->Data    = NULL;
+    FrontEnd->OldData = NULL;
 
-    /*
-     * Contrary to what we do in the GUI front-end, here we create
-     * an input thread for each console. It will dispatch all the
-     * input messages to the proper console (on the GUI it is done
-     * via the default GUI dispatch thread).
-     */
-    ThreadHandle = CreateThread(NULL,
-                                0,
-                                TuiConsoleThread,
-                                (PVOID)TuiData,
-                                0,
-                                NULL);
-    if (NULL == ThreadHandle)
-    {
-        DPRINT1("CONSRV: Unable to create console thread\n");
-        TuiCleanupConsole(Console);
-        return STATUS_UNSUCCESSFUL;
-    }
-    CloseHandle(ThreadHandle);
+    return STATUS_SUCCESS;
+}
 
-    /*
-     * Insert the newly created console in the list of virtual consoles
-     * and activate it (give it the focus).
-     */
-    EnterCriticalSection(&ActiveVirtConsLock);
-    InsertTailList(&VirtConsList, &TuiData->Entry);
-    ActiveConsole = TuiData;
-    LeaveCriticalSection(&ActiveVirtConsLock);
+NTSTATUS NTAPI
+TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
+{
+    if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
+    if (FrontEnd->Data)   TuiDeinitFrontEnd(FrontEnd);
 
     return STATUS_SUCCESS;
 }
 
+#endif
+
 /* EOF */
index 37c6868..71889f2 100644 (file)
@@ -443,7 +443,7 @@ ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData,
 
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
 
-    if (ConSrvValidateConsole(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
+    if (ConDrvValidateConsole(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
     {
         _InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
 
@@ -492,7 +492,9 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
     ConSrvFreeHandlesTable(ProcessData);
 
     /* Initialize a new Console owned by this process */
-    Status = ConSrvInitConsole(&ProcessData->Console, ConsoleStartInfo, ProcessData->Process);
+    Status = ConSrvInitConsole(&ProcessData->Console,
+                               ConsoleStartInfo,
+                               HandleToUlong(ProcessData->Process->ClientId.UniqueProcess));
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Console initialization failed\n");
@@ -551,7 +553,7 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
     NTSTATUS Status = STATUS_SUCCESS;
 
     /* Validate and lock the console */
-    if (!ConSrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
+    if (!ConDrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
     {
         // FIXME: Find another status code
         return STATUS_UNSUCCESSFUL;
@@ -629,7 +631,7 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
     // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
 
     /* Validate and lock the console */
-    if (ConSrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
+    if (ConDrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
     {
         DPRINT("ConSrvRemoveConsole - Locking OK\n");
 
index bcada38..d254e45 100644 (file)
@@ -70,7 +70,7 @@ struct _CONSOLE_SCREEN_BUFFER
     COORD   OldScreenBufferSize;        /* Old size of this screen buffer */
     COORD   OldViewSize;                /* Old associated view size */
 
-    COORD  ViewOrigin;                  /* Beginning offset for the actual display area */
+    COORD   ViewOrigin;                 /* Beginning offset for the actual display area */
 
 /***** Put that VV in TEXTMODE_SCREEN_BUFFER ?? *****/
     USHORT  VirtualY;                   /* Top row of buffer being displayed, reported to callers */
@@ -173,79 +173,85 @@ typedef struct _CONSOLE_INPUT_BUFFER
     USHORT      Mode;               /* Input buffer modes */
 } CONSOLE_INPUT_BUFFER, *PCONSOLE_INPUT_BUFFER;
 
+
+typedef struct _FRONTEND FRONTEND, *PFRONTEND;
+/* HACK: */ typedef struct _CONSOLE_INFO *PCONSOLE_INFO;
 typedef struct _FRONTEND_VTBL
 {
     /*
      * Internal interface (functions called by the console server only)
      */
-    // BOOL (WINAPI *Init)();
-    VOID (WINAPI *CleanupConsole)(struct _CONSOLE* Console);
+    NTSTATUS (WINAPI *InitFrontEnd)(IN OUT PFRONTEND This,
+                                    IN struct _CONSOLE* Console);
+    VOID (WINAPI *DeinitFrontEnd)(IN OUT PFRONTEND This);
+
     /* Interface used for both text-mode and graphics screen buffers */
-    VOID (WINAPI *DrawRegion)(struct _CONSOLE* Console,
+    VOID (WINAPI *DrawRegion)(IN OUT PFRONTEND This,
                               SMALL_RECT* Region);
     /* Interface used only for text-mode screen buffers */
-    VOID (WINAPI *WriteStream)(struct _CONSOLE* Console,
+    VOID (WINAPI *WriteStream)(IN OUT PFRONTEND This,
                                SMALL_RECT* Block,
                                SHORT CursorStartX,
                                SHORT CursorStartY,
                                UINT ScrolledLines,
                                PWCHAR Buffer,
                                UINT Length);
-    BOOL (WINAPI *SetCursorInfo)(struct _CONSOLE* Console,
+    BOOL (WINAPI *SetCursorInfo)(IN OUT PFRONTEND This,
                                  PCONSOLE_SCREEN_BUFFER ScreenBuffer);
-    BOOL (WINAPI *SetScreenInfo)(struct _CONSOLE* Console,
+    BOOL (WINAPI *SetScreenInfo)(IN OUT PFRONTEND This,
                                  PCONSOLE_SCREEN_BUFFER ScreenBuffer,
                                  SHORT OldCursorX,
                                  SHORT OldCursorY);
-    VOID (WINAPI *ResizeTerminal)(struct _CONSOLE* Console);
-    BOOL (WINAPI *ProcessKeyCallback)(struct _CONSOLE* Console,
+    VOID (WINAPI *ResizeTerminal)(IN OUT PFRONTEND This);
+    BOOL (WINAPI *ProcessKeyCallback)(IN OUT PFRONTEND This,
                                       MSG* msg,
                                       BYTE KeyStateMenu,
                                       DWORD ShiftState,
                                       UINT VirtualKeyCode,
                                       BOOL Down);
-    VOID (WINAPI *RefreshInternalInfo)(struct _CONSOLE* Console);
+    VOID (WINAPI *RefreshInternalInfo)(IN OUT PFRONTEND This);
 
     /*
      * External interface (functions corresponding to the Console API)
      */
-    VOID (WINAPI *ChangeTitle)(struct _CONSOLE* Console);
-    BOOL (WINAPI *ChangeIcon)(struct _CONSOLE* Console,
+    VOID (WINAPI *ChangeTitle)(IN OUT PFRONTEND This);
+    BOOL (WINAPI *ChangeIcon)(IN OUT PFRONTEND This,
                               HICON hWindowIcon);
-    HWND (WINAPI *GetConsoleWindowHandle)(struct _CONSOLE* Console);
-    VOID (WINAPI *GetLargestConsoleWindowSize)(struct _CONSOLE* Console,
+    HWND (WINAPI *GetConsoleWindowHandle)(IN OUT PFRONTEND This);
+    VOID (WINAPI *GetLargestConsoleWindowSize)(IN OUT PFRONTEND This,
                                                PCOORD pSize);
-    ULONG (WINAPI *GetDisplayMode)(struct _CONSOLE* Console);
-    BOOL  (WINAPI *SetDisplayMode)(struct _CONSOLE* Console,
+    ULONG (WINAPI *GetDisplayMode)(IN OUT PFRONTEND This);
+    BOOL  (WINAPI *SetDisplayMode)(IN OUT PFRONTEND This,
                                    ULONG NewMode);
-    INT   (WINAPI *ShowMouseCursor)(struct _CONSOLE* Console,
+    INT   (WINAPI *ShowMouseCursor)(IN OUT PFRONTEND This,
                                     BOOL Show);
-    BOOL  (WINAPI *SetMouseCursor)(struct _CONSOLE* Console,
+    BOOL  (WINAPI *SetMouseCursor)(IN OUT PFRONTEND This,
                                    HCURSOR hCursor);
-    HMENU (WINAPI *MenuControl)(struct _CONSOLE* Console,
+    HMENU (WINAPI *MenuControl)(IN OUT PFRONTEND This,
                                 UINT cmdIdLow,
                                 UINT cmdIdHigh);
-    BOOL  (WINAPI *SetMenuClose)(struct _CONSOLE* Console,
+    BOOL  (WINAPI *SetMenuClose)(IN OUT PFRONTEND This,
                                  BOOL Enable);
 
 #if 0 // Possible future front-end interface
-    BOOL (WINAPI *GetFrontEndProperty)(struct _CONSOLE* Console,
+    BOOL (WINAPI *GetFrontEndProperty)(IN OUT PFRONTEND This,
                                        ULONG Flag,
                                        PVOID Info,
                                        ULONG Size);
-    BOOL (WINAPI *SetFrontEndProperty)(struct _CONSOLE* Console,
+    BOOL (WINAPI *SetFrontEndProperty)(IN OUT PFRONTEND This,
                                        ULONG Flag,
                                        PVOID Info /*,
                                        ULONG Size */);
 #endif
 } FRONTEND_VTBL, *PFRONTEND_VTBL;
 
-typedef struct _FRONTEND_IFACE
+struct _FRONTEND
 {
-    PFRONTEND_VTBL Vtbl;    /* Virtual table */
-    PVOID Data;             /* Private data  */
-    PVOID OldData;          /* Reserved      */
-} FRONTEND_IFACE, *PFRONTEND_IFACE;
+    PFRONTEND_VTBL Vtbl;        /* Virtual table */
+    struct _CONSOLE* Console;   /* Console to which the frontend is attached to */
+    PVOID Data;                 /* Private data  */
+    PVOID OldData;              /* Reserved      */
+};
 
 /*
  * WARNING: Change the state of the console ONLY when the console is locked !
@@ -267,7 +273,7 @@ typedef struct _CONSOLE
     LIST_ENTRY Entry;                       /* Entry in the list of consoles */
     LIST_ENTRY ProcessList;                 /* List of processes owning the console. The first one is the so-called "Console Leader Process" */
 
-    FRONTEND_IFACE TermIFace;               /* Frontend-specific interface */
+    FRONTEND TermIFace;                     /* Frontend-specific interface */
 
 /**************************** Input buffer and data ***************************/
     CONSOLE_INPUT_BUFFER InputBuffer;               /* Input buffer of the console */
@@ -324,9 +330,11 @@ typedef struct _CONSOLE
 /* console.c */
 VOID FASTCALL ConioPause(PCONSOLE Console, UINT Flags);
 VOID FASTCALL ConioUnpause(PCONSOLE Console, UINT Flags);
-ULONG FASTCALL ConSrvConsoleProcessCtrlEvent(PCONSOLE Console,
-                                             ULONG ProcessGroupId,
-                                             DWORD Event);
+
+NTSTATUS NTAPI
+ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console,
+                              IN ULONG ProcessGroupId,
+                              IN ULONG Event);
 
 /* coninput.c */
 VOID WINAPI ConioProcessKey(PCONSOLE Console, MSG* msg);
index 09e4b33..5a12ecd 100644 (file)
@@ -8,14 +8,21 @@
 
 #pragma once
 
-BOOL FASTCALL ConSrvValidateConsolePointer(PCONSOLE Console);
-BOOL FASTCALL ConSrvValidateConsoleState(PCONSOLE Console,
-                                         CONSOLE_STATE ExpectedState);
-BOOL FASTCALL ConSrvValidateConsoleUnsafe(PCONSOLE Console,
-                                          CONSOLE_STATE ExpectedState,
-                                          BOOL LockConsole);
-BOOL FASTCALL ConSrvValidateConsole(PCONSOLE Console,
-                                    CONSOLE_STATE ExpectedState,
-                                    BOOL LockConsole);
+BOOLEAN NTAPI
+ConDrvValidateConsolePointer(IN PCONSOLE Console);
+
+BOOLEAN NTAPI
+ConDrvValidateConsoleState(IN PCONSOLE Console,
+                           IN CONSOLE_STATE ExpectedState);
+
+BOOLEAN NTAPI
+ConDrvValidateConsoleUnsafe(IN PCONSOLE Console,
+                            IN CONSOLE_STATE ExpectedState,
+                            IN BOOLEAN LockConsole);
+
+BOOLEAN NTAPI
+ConDrvValidateConsole(IN PCONSOLE Console,
+                      IN CONSOLE_STATE ExpectedState,
+                      IN BOOLEAN LockConsole);
 
 /* EOF */
index fd59850..6791837 100644 (file)
@@ -365,7 +365,7 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess,
         PCONSOLE_PROCESS_DATA SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
 
         /* Validate and lock the parent's console */
-        if (ConSrvValidateConsole(SourceProcessData->Console, CONSOLE_RUNNING, TRUE))
+        if (ConDrvValidateConsole(SourceProcessData->Console, CONSOLE_RUNNING, TRUE))
         {
             /* Inherit the parent's handles table */
             Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
@@ -508,7 +508,7 @@ CSR_SERVER_DLL_INIT(ConServerDllInitialization)
     if (!ConSrvHeap) return STATUS_NO_MEMORY;
 */
 
-    ConSrvInitConsoleSupport();
+    ConDrvInitConsoleSupport();
 
     /* Setup the DLL Object */
     LoadedServerDll->ApiBase = CONSRV_FIRST_API_NUMBER;