[MMIXER] Fix additional data size initialization for different audio formats (#6753)
[reactos.git] / win32ss / user / winsrv / consrv / frontends / tui / tuiterm.c
index d03cf22..e0ecef0 100644 (file)
@@ -4,25 +4,69 @@
  * FILE:            win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c
  * PURPOSE:         TUI Terminal Front-End - Virtual Consoles...
  * PROGRAMMERS:     David Welch
- *                  Gé van Geldorp
+ *                  Gé van Geldorp
  *                  Jeffrey Morlan
  *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
  */
 
 #ifdef TUITERM_COMPILE
 
-#include "consrv.h"
+#include <consrv.h>
+
 // #include "include/conio.h"
 #include "include/console.h"
 #include "include/settings.h"
 #include "tuiterm.h"
+
+#include <ndk/iofuncs.h>
+#include <ndk/setypes.h>
 #include <drivers/blue/ntddblue.h>
 
 #define NDEBUG
 #include <debug.h>
 
 
-/* GLOBALS ********************************************************************/
+/* CAB FILE STRUCTURES ******************************************************/
+
+typedef struct _CFHEADER
+{
+    ULONG Signature;        // File signature 'MSCF' (CAB_SIGNATURE)
+    ULONG Reserved1;        // Reserved field
+    ULONG CabinetSize;      // Cabinet file size
+    ULONG Reserved2;        // Reserved field
+    ULONG FileTableOffset;  // Offset of first CFFILE
+    ULONG Reserved3;        // Reserved field
+    USHORT Version;         // Cabinet version (CAB_VERSION)
+    USHORT FolderCount;     // Number of folders
+    USHORT FileCount;       // Number of files
+    USHORT Flags;           // Cabinet flags (CAB_FLAG_*)
+    USHORT SetID;           // Cabinet set id
+    USHORT CabinetNumber;   // Zero-based cabinet number
+} CFHEADER, *PCFHEADER;
+
+typedef struct _CFFILE
+{
+    ULONG FileSize;         // Uncompressed file size in bytes
+    ULONG FileOffset;       // Uncompressed offset of file in the folder
+    USHORT FileControlID;   // File control ID (CAB_FILE_*)
+    USHORT FileDate;        // File date stamp, as used by DOS
+    USHORT FileTime;        // File time stamp, as used by DOS
+    USHORT Attributes;      // File attributes (CAB_ATTRIB_*)
+    /* After this is the NULL terminated filename */
+    // CHAR FileName[ANYSIZE_ARRAY];
+} CFFILE, *PCFFILE;
+
+#define CAB_SIGNATURE       0x4643534D // "MSCF"
+#define CAB_VERSION         0x0103
+
+
+/* GLOBALS ******************************************************************/
+
+#define ConsoleOutputUnicodeToAnsiChar(Console, dChar, sWChar) \
+do { \
+    ASSERT((ULONG_PTR)(dChar) != (ULONG_PTR)(sWChar)); \
+    WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL); \
+} while (0)
 
 /* TUI Console Window Class name */
 #define TUI_CONSOLE_WINDOW_CLASS L"TuiConsoleWindowClass"
@@ -32,10 +76,12 @@ typedef struct _TUI_CONSOLE_DATA
     CRITICAL_SECTION Lock;
     LIST_ENTRY Entry;           /* Entry in the list of virtual consoles */
     // HANDLE hTuiInitEvent;
+    // HANDLE hTuiTermEvent;
 
-    HWND hWindow;               /* Handle to the console's window (used for the window's procedure */
+    HWND hWindow;               /* Handle to the console's window (used for the window's procedure) */
 
     PCONSRV_CONSOLE Console;           /* Pointer to the owned console */
+    PCONSOLE_SCREEN_BUFFER ActiveBuffer;    /* Pointer to the active screen buffer (then maybe the previous Console member is redundant?? Or not...) */
     // TUI_CONSOLE_INFO TuiInfo;   /* TUI terminal settings */
 } TUI_CONSOLE_DATA, *PTUI_CONSOLE_DATA;
 
@@ -164,6 +210,7 @@ done:
 /**\
 \******************************************************************************/
 
+#if 0
 static BOOL
 TuiSwapConsole(INT Next)
 {
@@ -230,6 +277,7 @@ TuiSwapConsole(INT Next)
         return FALSE;
     }
 }
+#endif
 
 static VOID
 TuiCopyRect(PCHAR Dest, PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
@@ -244,7 +292,7 @@ TuiCopyRect(PCHAR Dest, PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
     DestDelta = ConioRectWidth(Region) * 2 /* 2 == sizeof(CHAR) + sizeof(BYTE) */;
     for (i = Region->Top; i <= Region->Bottom; i++)
     {
-        ConsoleUnicodeCharToAnsiChar(Buff->Header.Console, (PCHAR)Dest, &Src->Char.UnicodeChar);
+        ConsoleOutputUnicodeToAnsiChar(Buff->Header.Console, (PCHAR)Dest, &Src->Char.UnicodeChar);
         *(PBYTE)(Dest + 1) = (BYTE)Src->Attributes;
 
         Src += SrcDelta;
@@ -291,7 +339,7 @@ TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
             }
 #endif
 
-            if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
+            if (ConDrvValidateConsoleUnsafe((PCONSOLE)ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
             {
                 MSG Message;
                 Message.hwnd = hWnd;
@@ -307,7 +355,7 @@ TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
         case WM_ACTIVATE:
         {
-            if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
+            if (ConDrvValidateConsoleUnsafe((PCONSOLE)ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
             {
                 if (LOWORD(wParam) != WA_INACTIVE)
                 {
@@ -327,9 +375,9 @@ TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 }
 
 static DWORD NTAPI
-TuiConsoleThread(PVOID Data)
+TuiConsoleThread(PVOID Param)
 {
-    PTUI_CONSOLE_DATA TuiData = (PTUI_CONSOLE_DATA)Data;
+    PTUI_CONSOLE_DATA TuiData = (PTUI_CONSOLE_DATA)Param;
     PCONSRV_CONSOLE Console = TuiData->Console;
     HWND NewWindow;
     MSG msg;
@@ -360,10 +408,224 @@ TuiConsoleThread(PVOID Data)
     return 0;
 }
 
+static BOOLEAN
+TuiSetConsoleOutputCP(
+    IN HANDLE hNtConddHandle,
+    IN UINT CodePage)
+{
+    static UINT LastLoadedCodepage = 0;
+    UNICODE_STRING FontFile = RTL_CONSTANT_STRING(L"\\SystemRoot\\vgafonts.cab");
+    CHAR FontName[20];
+
+    NTSTATUS Status;
+    HANDLE FileHandle;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    // ULONG ReadCP;
+    PUCHAR FontBitField = NULL;
+
+    /* CAB-specific data */
+    HANDLE FileSectionHandle;
+    PUCHAR FileBuffer = NULL;
+    SIZE_T FileSize = 0;
+    PCFHEADER CabFileHeader;
+    union
+    {
+        PCFFILE CabFile;
+        PVOID Buffer;
+    } Data;
+    PCFFILE FoundFile = NULL;
+    PSTR FileName;
+    USHORT Index;
+
+    if (CodePage == LastLoadedCodepage)
+        return TRUE;
+
+    /*
+     * Open the *uncompressed* fonts archive file.
+     */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &FontFile,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenFile(&FileHandle,
+                        GENERIC_READ | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Error: Cannot open '%wZ' (0x%lx)\n", &FontFile, Status);
+        return FALSE;
+    }
+
+    /*
+     * Load it.
+     */
+    Status = NtCreateSection(&FileSectionHandle,
+                             SECTION_ALL_ACCESS,
+                             0, 0,
+                             PAGE_READONLY,
+                             SEC_COMMIT,
+                             FileHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtCreateSection failed (0x%lx)\n", Status);
+        goto Exit;
+    }
+
+    Status = NtMapViewOfSection(FileSectionHandle,
+                                NtCurrentProcess(),
+                                (PVOID*)&FileBuffer,
+                                0, 0, NULL,
+                                &FileSize,
+                                ViewUnmap,
+                                0,
+                                PAGE_READONLY);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtMapViewOfSection failed (0x%lx)\n", Status);
+        goto Exit;
+    }
+
+    /* Wrap in SEH to protect against ill-formed file */
+    _SEH2_TRY
+    {
+        DPRINT("Cabinet file '%wZ' opened and mapped to 0x%p\n",
+               &FontFile, FileBuffer);
+
+        CabFileHeader = (PCFHEADER)FileBuffer;
+
+        /* Validate the CAB file */
+        if (FileSize <= sizeof(CFHEADER) ||
+            CabFileHeader->Signature != CAB_SIGNATURE ||
+            CabFileHeader->Version != CAB_VERSION ||
+            CabFileHeader->FolderCount == 0 ||
+            CabFileHeader->FileCount == 0 ||
+            CabFileHeader->FileTableOffset < sizeof(CFHEADER))
+        {
+            DPRINT1("Cabinet file '%wZ' has an invalid header\n", &FontFile);
+            Status = STATUS_UNSUCCESSFUL;
+            _SEH2_YIELD(goto Exit);
+        }
+
+        /*
+         * Find the font file within the archive.
+         */
+        RtlStringCbPrintfA(FontName, sizeof(FontName),
+                           "%u-8x8.bin", CodePage);
+
+        /* Read the file table, find the file of interest and the end of the table */
+        Data.CabFile = (PCFFILE)(FileBuffer + CabFileHeader->FileTableOffset);
+        for (Index = 0; Index < CabFileHeader->FileCount; ++Index)
+        {
+            FileName = (PSTR)(Data.CabFile + 1);
+
+            if (!FoundFile)
+            {
+                // Status = RtlCharToInteger(FileName, 0, &ReadCP);
+                // if (NT_SUCCESS(Status) && (ReadCP == CodePage))
+                if (_stricmp(FontName, FileName) == 0)
+                {
+                    /* We've got the correct file. Save the offset and
+                     * loop through the rest of the file table to find
+                     * the position, where the actual data starts. */
+                    FoundFile = Data.CabFile;
+                }
+            }
+
+            /* Move to the next file (go past the filename NULL terminator) */
+            Data.CabFile = (PCFFILE)(strchr(FileName, 0) + 1);
+        }
+
+        if (!FoundFile)
+        {
+            DPRINT("File '%S' not found in cabinet '%wZ'\n",
+                   FontName, &FontFile);
+            Status = STATUS_OBJECT_NAME_NOT_FOUND;
+            _SEH2_YIELD(goto Exit);
+        }
+
+        /*
+         * Extract the font file.
+         */
+        /* Verify the font file size; we only support a fixed 256-char 8-bit font */
+        if (FoundFile->FileSize != 256 * 8)
+        {
+            DPRINT1("File of size %lu is not of the expected size %lu\n",
+                    FoundFile->FileSize, 256 * 8);
+            Status = STATUS_INVALID_BUFFER_SIZE;
+            _SEH2_YIELD(goto Exit);
+        }
+
+        FontBitField = RtlAllocateHeap(RtlGetProcessHeap(), 0, FoundFile->FileSize);
+        if (!FontBitField)
+        {
+            DPRINT1("ExAllocatePoolWithTag(%lu) failed\n", FoundFile->FileSize);
+            Status = STATUS_NO_MEMORY;
+            _SEH2_YIELD(goto Exit);
+        }
+
+        /* 8 = Size of a CFFOLDER structure (see cabman). As we don't need
+         * the values of that structure, just increase the offset here. */
+        Data.Buffer = (PVOID)((ULONG_PTR)Data.Buffer + 8); // sizeof(CFFOLDER);
+        Data.Buffer = (PVOID)((ULONG_PTR)Data.Buffer + FoundFile->FileOffset);
+
+        /* Data.Buffer now points to the actual data of the RAW font */
+        RtlCopyMemory(FontBitField, Data.Buffer, FoundFile->FileSize);
+        Status = STATUS_SUCCESS;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+        DPRINT1("TuiSetConsoleOutputCP - Caught an exception, Status = 0x%08lx\n", Status);
+    }
+    _SEH2_END;
+
+    /*
+     * Load the font.
+     */
+    if (NT_SUCCESS(Status))
+    {
+        ASSERT(FoundFile);
+        ASSERT(FontBitField);
+        Status = NtDeviceIoControlFile(hNtConddHandle,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &IoStatusBlock,
+                                       IOCTL_CONSOLE_LOADFONT,
+                                       FontBitField,
+                                       FoundFile->FileSize,
+                                       NULL,
+                                       0);
+    }
+
+    if (FontBitField)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, FontBitField);
+
+Exit:
+    if (FileBuffer)
+        NtUnmapViewOfSection(NtCurrentProcess(), FileBuffer);
+
+    if (FileSectionHandle)
+        NtClose(FileSectionHandle);
+
+    NtClose(FileHandle);
+
+    if (NT_SUCCESS(Status))
+        LastLoadedCodepage = CodePage;
+
+    return NT_SUCCESS(Status);
+}
+
 static BOOL
-TuiInit(DWORD OemCP)
+TuiInit(IN UINT OemCP)
 {
-    BOOL Ret = FALSE;
+    BOOL Success;
     CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
     DWORD BytesReturned;
     WNDCLASSEXW wc;
@@ -376,6 +638,7 @@ TuiInit(DWORD OemCP)
     /*
      * Initialize the TUI front-end:
      * - load the console driver,
+     * - open BlueScreen device and enable it,
      * - set default screen attributes,
      * - grab the console size.
      */
@@ -386,15 +649,23 @@ TuiInit(DWORD OemCP)
                                       0, NULL,
                                       OPEN_EXISTING,
                                       0, NULL);
-    if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle)
+    if (ConsoleDeviceHandle == INVALID_HANDLE_VALUE)
     {
         DPRINT1("Failed to open BlueScreen.\n");
         return FALSE;
     }
 
-    if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT,
-                         &OemCP, sizeof(OemCP), NULL, 0,
+    Success = TRUE;
+    if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_RESET_SCREEN,
+                         &Success, sizeof(Success), NULL, 0,
                          &BytesReturned, NULL))
+    {
+        DPRINT1("Failed to enable the screen.\n");
+        CloseHandle(ConsoleDeviceHandle);
+        return FALSE;
+    }
+
+    if (!TuiSetConsoleOutputCP(ConsoleDeviceHandle, OemCP))
     {
         DPRINT1("Failed to load the font for codepage %d\n", OemCP);
         /* Let's suppose the font is good enough to continue */
@@ -404,7 +675,7 @@ TuiInit(DWORD OemCP)
                          &TextAttribute, sizeof(TextAttribute), NULL, 0,
                          &BytesReturned, NULL))
     {
-        DPRINT1("Failed to set text attribute\n");
+        DPRINT1("Failed to set text attribute.\n");
     }
 
     ActiveConsole = NULL;
@@ -414,8 +685,8 @@ TuiInit(DWORD OemCP)
     if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
                          NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL))
     {
-        DPRINT1("Failed to get console info\n");
-        Ret = FALSE;
+        DPRINT1("Failed to get console info.\n");
+        Success = FALSE;
         goto Quit;
     }
     PhysicalConsoleSize = ScrInfo.dwSize;
@@ -431,23 +702,23 @@ TuiInit(DWORD OemCP)
     ConsoleClassAtom = RegisterClassExW(&wc);
     if (ConsoleClassAtom == 0)
     {
-        DPRINT1("Failed to register TUI console wndproc\n");
-        Ret = FALSE;
+        DPRINT1("Failed to register TUI console wndproc.\n");
+        Success = FALSE;
     }
     else
     {
-        Ret = TRUE;
+        Success = TRUE;
     }
 
 Quit:
-    if (Ret == FALSE)
+    if (!Success)
     {
         DeleteCriticalSection(&ActiveVirtConsLock);
         CloseHandle(ConsoleDeviceHandle);
     }
 
-    ConsInitialized = Ret;
-    return Ret;
+    ConsInitialized = Success;
+    return Success;
 }
 
 
@@ -470,11 +741,8 @@ TuiInitFrontEnd(IN OUT PFRONTEND This,
     if (This == NULL || Console == NULL)
         return STATUS_INVALID_PARAMETER;
 
-    // if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
-        // return STATUS_INVALID_PARAMETER;
-
-    // /* Initialize the console */
-    // Console->FrontEndIFace.Vtbl = &TuiVtbl;
+    if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
+        return STATUS_INVALID_PARAMETER;
 
     TuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(TUI_CONSOLE_DATA));
     if (!TuiData)
@@ -482,8 +750,9 @@ TuiInitFrontEnd(IN OUT PFRONTEND This,
         DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
         return STATUS_UNSUCCESSFUL;
     }
-    // Console->FrontEndIFace.Data = (PVOID)TuiData;
-    TuiData->Console = Console;
+    // Console->FrontEndIFace.Context = (PVOID)TuiData;
+    TuiData->Console      = Console;
+    TuiData->ActiveBuffer = Console->ActiveBuffer;
     TuiData->hWindow = NULL;
 
     InitializeCriticalSection(&TuiData->Lock);
@@ -530,8 +799,8 @@ TuiInitFrontEnd(IN OUT PFRONTEND This,
     LeaveCriticalSection(&ActiveVirtConsLock);
 
     /* Finally, initialize the frontend structure */
-    This->Data = TuiData;
-    This->OldData = NULL;
+    This->Context  = TuiData;
+    This->Context2 = NULL;
 
     return STATUS_SUCCESS;
 }
@@ -540,7 +809,7 @@ static VOID NTAPI
 TuiDeinitFrontEnd(IN OUT PFRONTEND This)
 {
     // PCONSRV_CONSOLE Console = This->Console;
-    PTUI_CONSOLE_DATA TuiData = This->Data; // Console->FrontEndIFace.Data;
+    PTUI_CONSOLE_DATA TuiData = This->Context;
 
     /* Close the notification window */
     DestroyWindow(TuiData->hWindow);
@@ -571,8 +840,7 @@ TuiDeinitFrontEnd(IN OUT PFRONTEND This)
     /* Switch to the next console */
     if (NULL != ActiveConsole) ConioDrawConsole(ActiveConsole->Console);
 
-    // Console->FrontEndIFace.Data = NULL;
-    This->Data = NULL;
+    This->Context = NULL;
     DeleteCriticalSection(&TuiData->Lock);
     ConsoleFreeHeap(TuiData);
 }
@@ -581,12 +849,14 @@ static VOID NTAPI
 TuiDrawRegion(IN OUT PFRONTEND This,
               SMALL_RECT* Region)
 {
-    DWORD BytesReturned;
-    PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+    PTUI_CONSOLE_DATA TuiData = This->Context;
+    PCONSOLE_SCREEN_BUFFER Buff = TuiData->Console->ActiveBuffer;
     PCONSOLE_DRAW ConsoleDraw;
+    DWORD BytesReturned;
     UINT ConsoleDrawSize;
 
-    if (ActiveConsole->Console != Console || GetType(Buff) != TEXTMODE_BUFFER) return;
+    if (TuiData != ActiveConsole) return;
+    if (GetType(Buff) != TEXTMODE_BUFFER) return;
 
     ConsoleDrawSize = sizeof(CONSOLE_DRAW) +
                       (ConioRectWidth(Region) * ConioRectHeight(Region)) * 2;
@@ -625,20 +895,22 @@ TuiWriteStream(IN OUT PFRONTEND This,
                PWCHAR Buffer,
                UINT Length)
 {
-    PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+    PTUI_CONSOLE_DATA TuiData = This->Context;
+    PCONSOLE_SCREEN_BUFFER Buff = TuiData->Console->ActiveBuffer;
     PCHAR NewBuffer;
     ULONG NewLength;
     DWORD BytesWritten;
 
-    if (ActiveConsole->Console->ActiveBuffer != Buff) return;
+    if (TuiData != ActiveConsole) return;
+    if (GetType(Buff) != TEXTMODE_BUFFER) return;
 
-    NewLength = WideCharToMultiByte(Console->OutputCodePage, 0,
+    NewLength = WideCharToMultiByte(TuiData->Console->OutputCodePage, 0,
                                     Buffer, Length,
                                     NULL, 0, NULL, NULL);
     NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewLength * sizeof(CHAR));
     if (!NewBuffer) return;
 
-    WideCharToMultiByte(Console->OutputCodePage, 0,
+    WideCharToMultiByte(TuiData->Console->OutputCodePage, 0,
                         Buffer, Length,
                         NewBuffer, NewLength, NULL, NULL);
 
@@ -650,16 +922,25 @@ TuiWriteStream(IN OUT PFRONTEND This,
     RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
 }
 
+static VOID NTAPI
+TuiRingBell(IN OUT PFRONTEND This)
+{
+    Beep(800, 200);
+}
+
 static BOOL NTAPI
 TuiSetCursorInfo(IN OUT PFRONTEND This,
                  PCONSOLE_SCREEN_BUFFER Buff)
 {
+    PTUI_CONSOLE_DATA TuiData = This->Context;
     CONSOLE_CURSOR_INFO Info;
     DWORD BytesReturned;
 
-    if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE;
+    if (TuiData != ActiveConsole) return TRUE;
+    if (TuiData->Console->ActiveBuffer != Buff) return TRUE;
+    if (GetType(Buff) != TEXTMODE_BUFFER) return FALSE;
 
-    Info.dwSize = ConioEffectiveCursorSize(Console, 100);
+    Info.dwSize = ConioEffectiveCursorSize(TuiData->Console, 100);
     Info.bVisible = Buff->CursorInfo.bVisible;
 
     if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO,
@@ -678,10 +959,12 @@ TuiSetScreenInfo(IN OUT PFRONTEND This,
                  SHORT OldCursorX,
                  SHORT OldCursorY)
 {
+    PTUI_CONSOLE_DATA TuiData = This->Context;
     CONSOLE_SCREEN_BUFFER_INFO Info;
     DWORD BytesReturned;
 
-    if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE;
+    if (TuiData != ActiveConsole) return TRUE;
+    if (TuiData->Console->ActiveBuffer != Buff) return TRUE;
     if (GetType(Buff) != TEXTMODE_BUFFER) return FALSE;
 
     Info.dwCursorPosition = Buff->CursorPosition;
@@ -703,6 +986,93 @@ TuiResizeTerminal(IN OUT PFRONTEND This)
 {
 }
 
+static VOID NTAPI
+TuiSetActiveScreenBuffer(IN OUT PFRONTEND This)
+{
+    // PGUI_CONSOLE_DATA GuiData = This->Context;
+    // PCONSOLE_SCREEN_BUFFER ActiveBuffer;
+    // HPALETTE hPalette;
+
+    // EnterCriticalSection(&GuiData->Lock);
+    // GuiData->WindowSizeLock = TRUE;
+
+    // InterlockedExchangePointer(&GuiData->ActiveBuffer,
+                               // ConDrvGetActiveScreenBuffer(GuiData->Console));
+
+    // GuiData->WindowSizeLock = FALSE;
+    // LeaveCriticalSection(&GuiData->Lock);
+
+    // ActiveBuffer = GuiData->ActiveBuffer;
+
+    // /* Change the current palette */
+    // if (ActiveBuffer->PaletteHandle == NULL)
+    // {
+        // hPalette = GuiData->hSysPalette;
+    // }
+    // else
+    // {
+        // hPalette = ActiveBuffer->PaletteHandle;
+    // }
+
+    // DPRINT("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette);
+
+    // /* Set the new palette for the framebuffer */
+    // SelectPalette(GuiData->hMemDC, hPalette, FALSE);
+
+    // /* Specify the use of the system palette for the framebuffer */
+    // SetSystemPaletteUse(GuiData->hMemDC, ActiveBuffer->PaletteUsage);
+
+    // /* Realize the (logical) palette */
+    // RealizePalette(GuiData->hMemDC);
+
+    // GuiResizeTerminal(This);
+    // // ConioDrawConsole(Console);
+}
+
+static VOID NTAPI
+TuiReleaseScreenBuffer(IN OUT PFRONTEND This,
+                       IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
+{
+    // PGUI_CONSOLE_DATA GuiData = This->Context;
+
+    // /*
+     // * If we were notified to release a screen buffer that is not actually
+     // * ours, then just ignore the notification...
+     // */
+    // if (ScreenBuffer != GuiData->ActiveBuffer) return;
+
+    // /*
+     // * ... else, we must release our active buffer. Two cases are present:
+     // * - If ScreenBuffer (== GuiData->ActiveBuffer) IS NOT the console
+     // *   active screen buffer, then we can safely switch to it.
+     // * - If ScreenBuffer IS the console active screen buffer, we must release
+     // *   it ONLY.
+     // */
+
+    // /* Release the old active palette and set the default one */
+    // if (GetCurrentObject(GuiData->hMemDC, OBJ_PAL) == ScreenBuffer->PaletteHandle)
+    // {
+        // /* Set the new palette */
+        // SelectPalette(GuiData->hMemDC, GuiData->hSysPalette, FALSE);
+    // }
+
+    // /* Set the adequate active screen buffer */
+    // if (ScreenBuffer != GuiData->Console->ActiveBuffer)
+    // {
+        // GuiSetActiveScreenBuffer(This);
+    // }
+    // else
+    // {
+        // EnterCriticalSection(&GuiData->Lock);
+        // GuiData->WindowSizeLock = TRUE;
+
+        // InterlockedExchangePointer(&GuiData->ActiveBuffer, NULL);
+
+        // GuiData->WindowSizeLock = FALSE;
+        // LeaveCriticalSection(&GuiData->Lock);
+    // }
+}
+
 static VOID NTAPI
 TuiRefreshInternalInfo(IN OUT PFRONTEND This)
 {
@@ -720,10 +1090,17 @@ TuiChangeIcon(IN OUT PFRONTEND This,
     return TRUE;
 }
 
+static HDESK NTAPI
+TuiGetThreadConsoleDesktop(IN OUT PFRONTEND This)
+{
+    // PTUI_CONSOLE_DATA TuiData = This->Context;
+    return NULL;
+}
+
 static HWND NTAPI
 TuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
 {
-    PTUI_CONSOLE_DATA TuiData = This->Data;
+    PTUI_CONSOLE_DATA TuiData = This->Context;
     return TuiData->hWindow;
 }
 
@@ -750,6 +1127,25 @@ TuiSetPalette(IN OUT PFRONTEND This,
     return TRUE;
 }
 
+static BOOL NTAPI
+TuiSetCodePage(IN OUT PFRONTEND This,
+               UINT CodePage)
+{
+    // PTUI_CONSOLE_DATA TuiData = This->Context;
+
+    // TODO: Verify that the console is the visible one.
+    // Only then can we change the output code page font.
+
+    if (!TuiSetConsoleOutputCP(ConsoleDeviceHandle, CodePage))
+    {
+        DPRINT1("Failed to load the font for codepage %d\n", CodePage);
+        /* Let's suppose the font is good enough to continue */
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 static ULONG NTAPI
 TuiGetDisplayMode(IN OUT PFRONTEND This)
 {
@@ -800,16 +1196,21 @@ static FRONTEND_VTBL TuiVtbl =
     TuiDeinitFrontEnd,
     TuiDrawRegion,
     TuiWriteStream,
+    TuiRingBell,
     TuiSetCursorInfo,
     TuiSetScreenInfo,
     TuiResizeTerminal,
+    TuiSetActiveScreenBuffer,
+    TuiReleaseScreenBuffer,
     TuiRefreshInternalInfo,
     TuiChangeTitle,
     TuiChangeIcon,
+    TuiGetThreadConsoleDesktop,
     TuiGetConsoleWindowHandle,
     TuiGetLargestConsoleWindowSize,
     TuiGetSelectionInfo,
     TuiSetPalette,
+    TuiSetCodePage,
     TuiGetDisplayMode,
     TuiSetDisplayMode,
     TuiShowMouseCursor,
@@ -818,11 +1219,6 @@ static FRONTEND_VTBL TuiVtbl =
     TuiSetMenuClose,
 };
 
-// static BOOL
-// DtbgIsDesktopVisible(VOID)
-// {
-    // return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
-// }
 static BOOLEAN
 IsConsoleMode(VOID)
 {
@@ -831,9 +1227,9 @@ IsConsoleMode(VOID)
 
 NTSTATUS NTAPI
 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
-                IN OUT PCONSOLE_INFO ConsoleInfo,
-                IN OUT PVOID ExtraConsoleInfo,
-                IN ULONG ProcessId)
+                IN OUT PCONSOLE_STATE_INFO ConsoleInfo,
+                IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
+                IN HANDLE ConsoleLeaderProcessHandle)
 {
     if (FrontEnd == NULL || ConsoleInfo == NULL)
         return STATUS_INVALID_PARAMETER;
@@ -845,9 +1241,9 @@ TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
     if (!TuiInit(ConsoleInfo->CodePage)) return STATUS_UNSUCCESSFUL;
 
     /* Finally, initialize the frontend structure */
-    FrontEnd->Vtbl    = &TuiVtbl;
-    FrontEnd->Data    = NULL;
-    FrontEnd->OldData = NULL;
+    FrontEnd->Vtbl     = &TuiVtbl;
+    FrontEnd->Context  = NULL;
+    FrontEnd->Context2 = NULL;
 
     return STATUS_SUCCESS;
 }
@@ -856,7 +1252,7 @@ NTSTATUS NTAPI
 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
 {
     if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
-    if (FrontEnd->Data)   TuiDeinitFrontEnd(FrontEnd);
+    if (FrontEnd->Context) TuiDeinitFrontEnd(FrontEnd);
 
     return STATUS_SUCCESS;
 }