mirror of
https://github.com/reactos/reactos.git
synced 2024-10-09 10:48:55 +00:00
818ee21a07
- Start to sort out things that depends only of the internals of a console, and things which are only related to "terminal emulators". Do it especially for (what I will call starting from now) the "GUI terminal emulator". - Temporarily deactivate starting "TUI terminals". - Temporarily break report that the terminal window is held by the current running console application in it (see r58107). This will be fixed later on. svn path=/branches/ros-csrss/; revision=58447
627 lines
17 KiB
C
627 lines
17 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Console Server DLL
|
|
* FILE: win32ss/user/consrv/tuiconsole.c
|
|
* PURPOSE: TUI terminal emulator
|
|
* PROGRAMMERS:
|
|
*/
|
|
|
|
#ifdef TUI_CONSOLE
|
|
|
|
#include "consrv.h"
|
|
#include "settings.h"
|
|
#include "tuiconsole.h"
|
|
#include <drivers/blue/ntddblue.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
/* TUI Console Window Class name */
|
|
#define TUI_CONSOLE_WINDOW_CLASS L"TuiConsoleWindowClass"
|
|
|
|
typedef struct _TUI_CONSOLE_DATA
|
|
{
|
|
CRITICAL_SECTION Lock;
|
|
// HANDLE hTuiInitEvent;
|
|
|
|
HWND hWindow;
|
|
|
|
PCONSOLE Console;
|
|
// TUI_CONSOLE_INFO TuiInfo;
|
|
} TUI_CONSOLE_DATA, *PTUI_CONSOLE_DATA;
|
|
|
|
CRITICAL_SECTION ActiveConsoleLock;
|
|
static COORD PhysicalConsoleSize;
|
|
static HANDLE ConsoleDeviceHandle;
|
|
static PCONSOLE ActiveConsole;
|
|
|
|
static BOOL ConsInitialized = FALSE;
|
|
|
|
/******************************************************************************\
|
|
|** BlueScreen Driver management **|
|
|
\**/
|
|
/* Code taken and adapted from base/system/services/driver.c */
|
|
static DWORD
|
|
ScmLoadDriver(LPCWSTR lpServiceName)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
BOOLEAN WasPrivilegeEnabled = FALSE;
|
|
PWSTR pszDriverPath;
|
|
UNICODE_STRING DriverPath;
|
|
|
|
/* Build the driver path */
|
|
/* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
|
|
pszDriverPath = RtlAllocateHeap(ConSrvHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
(52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR));
|
|
if (pszDriverPath == NULL)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
wcscpy(pszDriverPath,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
|
|
wcscat(pszDriverPath,
|
|
lpServiceName);
|
|
|
|
RtlInitUnicodeString(&DriverPath,
|
|
pszDriverPath);
|
|
|
|
DPRINT(" Path: %wZ\n", &DriverPath);
|
|
|
|
/* Acquire driver-loading privilege */
|
|
Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
|
|
TRUE,
|
|
FALSE,
|
|
&WasPrivilegeEnabled);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* We encountered a failure, exit properly */
|
|
DPRINT1("CONSRV: Cannot acquire driver-loading privilege, Status = 0x%08lx\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = NtLoadDriver(&DriverPath);
|
|
|
|
/* Release driver-loading privilege */
|
|
RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
|
|
WasPrivilegeEnabled,
|
|
FALSE,
|
|
&WasPrivilegeEnabled);
|
|
|
|
done:
|
|
RtlFreeHeap(ConSrvHeap, 0, pszDriverPath);
|
|
return RtlNtStatusToDosError(Status);
|
|
}
|
|
|
|
#ifdef BLUESCREEN_DRIVER_UNLOADING
|
|
static DWORD
|
|
ScmUnloadDriver(LPCWSTR lpServiceName)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
BOOLEAN WasPrivilegeEnabled = FALSE;
|
|
PWSTR pszDriverPath;
|
|
UNICODE_STRING DriverPath;
|
|
|
|
/* Build the driver path */
|
|
/* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
|
|
pszDriverPath = RtlAllocateHeap(ConSrvHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
(52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR));
|
|
if (pszDriverPath == NULL)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
wcscpy(pszDriverPath,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
|
|
wcscat(pszDriverPath,
|
|
lpServiceName);
|
|
|
|
RtlInitUnicodeString(&DriverPath,
|
|
pszDriverPath);
|
|
|
|
DPRINT(" Path: %wZ\n", &DriverPath);
|
|
|
|
/* Acquire driver-unloading privilege */
|
|
Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
|
|
TRUE,
|
|
FALSE,
|
|
&WasPrivilegeEnabled);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* We encountered a failure, exit properly */
|
|
DPRINT1("CONSRV: Cannot acquire driver-unloading privilege, Status = 0x%08lx\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = NtUnloadDriver(&DriverPath);
|
|
|
|
/* Release driver-unloading privilege */
|
|
RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
|
|
WasPrivilegeEnabled,
|
|
FALSE,
|
|
&WasPrivilegeEnabled);
|
|
|
|
done:
|
|
RtlFreeHeap(ConSrvHeap, 0, pszDriverPath);
|
|
return RtlNtStatusToDosError(Status);
|
|
}
|
|
#endif
|
|
/**\
|
|
\******************************************************************************/
|
|
|
|
static LRESULT CALLBACK
|
|
TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (msg == WM_ACTIVATE)
|
|
{
|
|
if (LOWORD(wParam) != WA_INACTIVE)
|
|
{
|
|
SetFocus(hWnd);
|
|
ConioDrawConsole(ActiveConsole);
|
|
}
|
|
}
|
|
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
|
}
|
|
|
|
static BOOL FASTCALL
|
|
TuiSwapConsole(INT Next)
|
|
{
|
|
static PCONSOLE SwapConsole = NULL; /* console we are thinking about swapping with */
|
|
DWORD BytesReturned;
|
|
ANSI_STRING Title;
|
|
PVOID Buffer;
|
|
PCOORD pos;
|
|
|
|
if (0 != Next)
|
|
{
|
|
/* alt-tab, swap consoles */
|
|
/* move SwapConsole to next console, and print its title */
|
|
EnterCriticalSection(&ActiveConsoleLock);
|
|
if (!SwapConsole)
|
|
{
|
|
SwapConsole = ActiveConsole;
|
|
}
|
|
|
|
SwapConsole = (0 < Next ? SwapConsole->Next : SwapConsole->Prev);
|
|
Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Title);
|
|
Title.Length = 0;
|
|
Buffer = RtlAllocateHeap(ConSrvHeap,
|
|
0,
|
|
sizeof(COORD) + Title.MaximumLength);
|
|
pos = (PCOORD )Buffer;
|
|
Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof( COORD ));
|
|
|
|
RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE);
|
|
pos->Y = PhysicalConsoleSize.Y / 2;
|
|
pos->X = (PhysicalConsoleSize.X - Title.Length) / 2;
|
|
/* redraw the console to clear off old title */
|
|
ConioDrawConsole(ActiveConsole);
|
|
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
|
|
NULL, 0, Buffer, sizeof(COORD) + Title.Length,
|
|
&BytesReturned, NULL))
|
|
{
|
|
DPRINT1( "Error writing to console\n" );
|
|
}
|
|
RtlFreeHeap(ConSrvHeap, 0, Buffer);
|
|
LeaveCriticalSection(&ActiveConsoleLock);
|
|
|
|
return TRUE;
|
|
}
|
|
else if (NULL != SwapConsole)
|
|
{
|
|
EnterCriticalSection(&ActiveConsoleLock);
|
|
if (SwapConsole != ActiveConsole)
|
|
{
|
|
/* first remove swapconsole from the list */
|
|
SwapConsole->Prev->Next = SwapConsole->Next;
|
|
SwapConsole->Next->Prev = SwapConsole->Prev;
|
|
/* now insert before activeconsole */
|
|
SwapConsole->Next = ActiveConsole;
|
|
SwapConsole->Prev = ActiveConsole->Prev;
|
|
ActiveConsole->Prev->Next = SwapConsole;
|
|
ActiveConsole->Prev = SwapConsole;
|
|
}
|
|
ActiveConsole = SwapConsole;
|
|
SwapConsole = NULL;
|
|
ConioDrawConsole(ActiveConsole);
|
|
LeaveCriticalSection(&ActiveConsoleLock);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static BOOL WINAPI
|
|
TuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD ShiftState, UINT VirtualKeyCode, BOOL Down)
|
|
{
|
|
if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) &&
|
|
VK_TAB == VirtualKeyCode)
|
|
{
|
|
if (Down)
|
|
{
|
|
TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else if (VK_MENU == VirtualKeyCode && !Down)
|
|
{
|
|
return TuiSwapConsole(0);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL FASTCALL
|
|
TuiInit(DWORD OemCP)
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
|
|
DWORD BytesReturned;
|
|
WNDCLASSEXW wc;
|
|
ATOM ConsoleClassAtom;
|
|
USHORT TextAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
|
|
|
ScmLoadDriver(L"Blue");
|
|
|
|
ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen", FILE_ALL_ACCESS, 0, NULL,
|
|
OPEN_EXISTING, 0, NULL);
|
|
if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle)
|
|
{
|
|
DPRINT1("Failed to open BlueScreen.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT,
|
|
&OemCP, sizeof(OemCP), NULL, 0,
|
|
&BytesReturned, NULL))
|
|
{
|
|
DPRINT1("Failed to load the font for codepage %d\n", OemCP);
|
|
/* Let's suppose the font is good enough to continue */
|
|
}
|
|
|
|
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
|
|
&TextAttribute, sizeof(TextAttribute), NULL, 0,
|
|
&BytesReturned, NULL))
|
|
{
|
|
DPRINT1("Failed to set text attribute\n");
|
|
}
|
|
|
|
ActiveConsole = NULL;
|
|
InitializeCriticalSection(&ActiveConsoleLock);
|
|
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
|
|
NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL))
|
|
{
|
|
DPRINT1("Failed to get console info\n");
|
|
return FALSE;
|
|
}
|
|
PhysicalConsoleSize = ScrInfo.dwSize;
|
|
|
|
RtlZeroMemory(&wc, sizeof(WNDCLASSEXW));
|
|
wc.cbSize = sizeof(WNDCLASSEXW);
|
|
wc.lpszClassName = TUI_CONSOLE_WINDOW_CLASS;
|
|
wc.lpfnWndProc = TuiConsoleWndProc;
|
|
wc.cbWndExtra = GWLP_CONSOLEWND_ALLOC;
|
|
wc.hInstance = ConSrvDllInstance;
|
|
|
|
ConsoleClassAtom = RegisterClassExW(&wc);
|
|
if (ConsoleClassAtom == 0)
|
|
{
|
|
DPRINT1("Failed to register TUI console wndproc\n");
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
NtUserConsoleControl(TuiConsoleWndClassAtom, &ConsoleClassAtom, sizeof(ATOM));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static VOID FASTCALL
|
|
TuiCopyRect(char *Dest, PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
|
|
{
|
|
UINT SrcDelta, DestDelta;
|
|
LONG i;
|
|
PBYTE Src, SrcEnd;
|
|
|
|
Src = ConioCoordToPointer(Buff, Region->Left, Region->Top);
|
|
SrcDelta = Buff->ScreenBufferSize.X * 2;
|
|
SrcEnd = Buff->Buffer + Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * 2;
|
|
DestDelta = ConioRectWidth(Region) * 2;
|
|
for (i = Region->Top; i <= Region->Bottom; i++)
|
|
{
|
|
memcpy(Dest, Src, DestDelta);
|
|
Src += SrcDelta;
|
|
if (SrcEnd <= Src)
|
|
{
|
|
Src -= Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * 2;
|
|
}
|
|
Dest += DestDelta;
|
|
}
|
|
}
|
|
|
|
static VOID WINAPI
|
|
TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
|
|
{
|
|
DWORD BytesReturned;
|
|
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
|
|
PCONSOLE_DRAW ConsoleDraw;
|
|
UINT ConsoleDrawSize;
|
|
|
|
if (ActiveConsole != Console)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ConsoleDrawSize = sizeof(CONSOLE_DRAW) +
|
|
(ConioRectWidth(Region) * ConioRectHeight(Region)) * 2;
|
|
ConsoleDraw = RtlAllocateHeap(ConSrvHeap, 0, ConsoleDrawSize);
|
|
if (NULL == ConsoleDraw)
|
|
{
|
|
DPRINT1("RtlAllocateHeap failed\n");
|
|
return;
|
|
}
|
|
ConsoleDraw->X = Region->Left;
|
|
ConsoleDraw->Y = Region->Top;
|
|
ConsoleDraw->SizeX = ConioRectWidth(Region);
|
|
ConsoleDraw->SizeY = ConioRectHeight(Region);
|
|
ConsoleDraw->CursorX = Buff->CursorPosition.X;
|
|
ConsoleDraw->CursorY = Buff->CursorPosition.Y;
|
|
|
|
TuiCopyRect((char *) (ConsoleDraw + 1), Buff, Region);
|
|
|
|
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW,
|
|
NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL))
|
|
{
|
|
DPRINT1("Failed to draw console\n");
|
|
RtlFreeHeap(ConSrvHeap, 0, ConsoleDraw);
|
|
return;
|
|
}
|
|
|
|
RtlFreeHeap(ConSrvHeap, 0, ConsoleDraw);
|
|
}
|
|
|
|
static VOID WINAPI
|
|
TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, LONG CursorStartX, LONG CursorStartY,
|
|
UINT ScrolledLines, CHAR *Buffer, UINT Length)
|
|
{
|
|
DWORD BytesWritten;
|
|
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
|
|
|
|
if (ActiveConsole->ActiveBuffer != Buff)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL))
|
|
{
|
|
DPRINT1("Error writing to BlueScreen\n");
|
|
}
|
|
}
|
|
|
|
static BOOL WINAPI
|
|
TuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
|
|
{
|
|
CONSOLE_CURSOR_INFO Info;
|
|
DWORD BytesReturned;
|
|
|
|
if (ActiveConsole->ActiveBuffer != Buff)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
Info.dwSize = ConioEffectiveCursorSize(Console, 100);
|
|
Info.bVisible = Buff->CursorInfo.bVisible;
|
|
|
|
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO,
|
|
&Info, sizeof(Info), NULL, 0, &BytesReturned, NULL))
|
|
{
|
|
DPRINT1( "Failed to set cursor info\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL WINAPI
|
|
TuiSetScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY)
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO Info;
|
|
DWORD BytesReturned;
|
|
|
|
if (ActiveConsole->ActiveBuffer != Buff)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
Info.dwCursorPosition = Buff->CursorPosition;
|
|
Info.wAttributes = Buff->ScreenDefaultAttrib;
|
|
|
|
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
|
|
&Info, sizeof(CONSOLE_SCREEN_BUFFER_INFO), NULL, 0,
|
|
&BytesReturned, NULL))
|
|
{
|
|
DPRINT1( "Failed to set cursor position\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL WINAPI
|
|
TuiUpdateScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static VOID WINAPI
|
|
TuiChangeTitle(PCONSOLE Console)
|
|
{
|
|
}
|
|
|
|
static VOID WINAPI
|
|
TuiCleanupConsole(PCONSOLE Console)
|
|
{
|
|
DestroyWindow(Console->hWindow);
|
|
|
|
EnterCriticalSection(&ActiveConsoleLock);
|
|
|
|
/* Switch to next console */
|
|
if (ActiveConsole == Console)
|
|
{
|
|
ActiveConsole = Console->Next != Console ? Console->Next : NULL;
|
|
}
|
|
|
|
if (Console->Next != Console)
|
|
{
|
|
Console->Prev->Next = Console->Next;
|
|
Console->Next->Prev = Console->Prev;
|
|
}
|
|
LeaveCriticalSection(&ActiveConsoleLock);
|
|
|
|
if (NULL != ActiveConsole)
|
|
{
|
|
ConioDrawConsole(ActiveConsole);
|
|
}
|
|
}
|
|
|
|
static BOOL WINAPI
|
|
TuiChangeIcon(PCONSOLE Console, HICON hWindowIcon)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static HWND WINAPI
|
|
TuiGetConsoleWindowHandle(PCONSOLE Console)
|
|
{
|
|
return Console->hWindow;
|
|
}
|
|
|
|
static NTSTATUS WINAPI
|
|
TuiResizeBuffer(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer, COORD Size)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static DWORD WINAPI
|
|
TuiConsoleThread(PVOID Data)
|
|
{
|
|
PCONSOLE Console = (PCONSOLE) Data;
|
|
HWND NewWindow;
|
|
MSG msg;
|
|
|
|
NewWindow = CreateWindowW(TUI_CONSOLE_WINDOW_CLASS,
|
|
Console->Title.Buffer,
|
|
0,
|
|
-32000, -32000, 0, 0,
|
|
NULL, NULL,
|
|
ConSrvDllInstance,
|
|
(PVOID)Console);
|
|
if (NULL == NewWindow)
|
|
{
|
|
DPRINT1("CONSRV: Unable to create console window\n");
|
|
return 1;
|
|
}
|
|
Console->hWindow = NewWindow;
|
|
|
|
SetForegroundWindow(Console->hWindow);
|
|
|
|
while (TRUE)
|
|
{
|
|
GetMessageW(&msg, 0, 0, 0);
|
|
DispatchMessage(&msg);
|
|
TranslateMessage(&msg);
|
|
|
|
if (msg.message == WM_CHAR || msg.message == WM_SYSCHAR ||
|
|
msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN ||
|
|
msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP)
|
|
{
|
|
ConioProcessKey(Console, &msg);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static TERMINAL_VTBL TuiVtbl =
|
|
{
|
|
TuiCleanupConsole,
|
|
TuiWriteStream,
|
|
TuiDrawRegion,
|
|
TuiSetCursorInfo,
|
|
TuiSetScreenInfo,
|
|
TuiUpdateScreenInfo,
|
|
TuiChangeTitle,
|
|
TuiChangeIcon,
|
|
TuiGetConsoleWindowHandle,
|
|
TuiResizeBuffer,
|
|
TuiProcessKeyCallback
|
|
};
|
|
|
|
NTSTATUS FASTCALL
|
|
TuiInitConsole(PCONSOLE Console,
|
|
PCONSOLE_INFO ConsoleInfo)
|
|
{
|
|
HANDLE ThreadHandle;
|
|
|
|
if (!ConsInitialized)
|
|
{
|
|
ConsInitialized = TRUE;
|
|
if (!TuiInit(Console->CodePage))
|
|
{
|
|
ConsInitialized = FALSE;
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
Console->TermIFace.Vtbl = &TuiVtbl;
|
|
Console->hWindow = NULL;
|
|
Console->Size = PhysicalConsoleSize;
|
|
Console->ActiveBuffer->ScreenBufferSize = PhysicalConsoleSize;
|
|
|
|
ThreadHandle = CreateThread(NULL,
|
|
0,
|
|
TuiConsoleThread,
|
|
(PVOID)Console,
|
|
0,
|
|
NULL);
|
|
if (NULL == ThreadHandle)
|
|
{
|
|
DPRINT1("CONSRV: Unable to create console thread\n");
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
CloseHandle(ThreadHandle);
|
|
|
|
EnterCriticalSection(&ActiveConsoleLock);
|
|
if (NULL != ActiveConsole)
|
|
{
|
|
Console->Prev = ActiveConsole;
|
|
Console->Next = ActiveConsole->Next;
|
|
ActiveConsole->Next->Prev = Console;
|
|
ActiveConsole->Next = Console;
|
|
}
|
|
else
|
|
{
|
|
Console->Prev = Console;
|
|
Console->Next = Console;
|
|
}
|
|
ActiveConsole = Console;
|
|
LeaveCriticalSection(&ActiveConsoleLock);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
PCONSOLE FASTCALL
|
|
TuiGetFocusConsole(VOID)
|
|
{
|
|
return ActiveConsole;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* EOF */
|