[CONSRV]
[reactos.git] / win32ss / user / consrv / frontends / tui / tuiterm.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/frontends/tui/tuiterm.c
5 * PURPOSE: TUI Terminal Front-End - Virtual Consoles...
6 * PROGRAMMERS: David Welch
7 * Gé van Geldorp
8 * Jeffrey Morlan
9 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 */
11
12 #include "consrv.h"
13 #include "include/conio.h"
14 #include "include/console.h"
15 #include "include/settings.h"
16 #include "tuiterm.h"
17 #include <drivers/blue/ntddblue.h>
18
19 #define NDEBUG
20 #include <debug.h>
21
22
23 /* GLOBALS ********************************************************************/
24
25 #define GetNextConsole(Console) \
26 CONTAINING_RECORD(Console->Entry.Flink, TUI_CONSOLE_DATA, Entry)
27
28 #define GetPrevConsole(Console) \
29 CONTAINING_RECORD(Console->Entry.Blink, TUI_CONSOLE_DATA, Entry)
30
31
32 /* TUI Console Window Class name */
33 #define TUI_CONSOLE_WINDOW_CLASS L"TuiConsoleWindowClass"
34
35 typedef struct _TUI_CONSOLE_DATA
36 {
37 CRITICAL_SECTION Lock;
38 LIST_ENTRY Entry; /* Entry in the list of virtual consoles */
39 // HANDLE hTuiInitEvent;
40
41 HWND hWindow; /* Handle to the console's window (used for the window's procedure */
42
43 PCONSOLE Console; /* Pointer to the owned console */
44 // TUI_CONSOLE_INFO TuiInfo; /* TUI terminal settings */
45 } TUI_CONSOLE_DATA, *PTUI_CONSOLE_DATA;
46
47 /* List of the maintained virtual consoles and its lock */
48 static LIST_ENTRY VirtConsList;
49 static PTUI_CONSOLE_DATA ActiveConsole; /* The active console on screen */
50 static CRITICAL_SECTION ActiveVirtConsLock;
51
52 static COORD PhysicalConsoleSize;
53 static HANDLE ConsoleDeviceHandle;
54
55 static BOOL ConsInitialized = FALSE;
56
57 /******************************************************************************\
58 |** BlueScreen Driver management **|
59 \**/
60 /* Code taken and adapted from base/system/services/driver.c */
61 static DWORD
62 ScmLoadDriver(LPCWSTR lpServiceName)
63 {
64 NTSTATUS Status = STATUS_SUCCESS;
65 BOOLEAN WasPrivilegeEnabled = FALSE;
66 PWSTR pszDriverPath;
67 UNICODE_STRING DriverPath;
68
69 /* Build the driver path */
70 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
71 pszDriverPath = RtlAllocateHeap(ConSrvHeap,
72 HEAP_ZERO_MEMORY,
73 (52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR));
74 if (pszDriverPath == NULL)
75 return ERROR_NOT_ENOUGH_MEMORY;
76
77 wcscpy(pszDriverPath,
78 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
79 wcscat(pszDriverPath,
80 lpServiceName);
81
82 RtlInitUnicodeString(&DriverPath,
83 pszDriverPath);
84
85 DPRINT(" Path: %wZ\n", &DriverPath);
86
87 /* Acquire driver-loading privilege */
88 Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
89 TRUE,
90 FALSE,
91 &WasPrivilegeEnabled);
92 if (!NT_SUCCESS(Status))
93 {
94 /* We encountered a failure, exit properly */
95 DPRINT1("CONSRV: Cannot acquire driver-loading privilege, Status = 0x%08lx\n", Status);
96 goto done;
97 }
98
99 Status = NtLoadDriver(&DriverPath);
100
101 /* Release driver-loading privilege */
102 RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
103 WasPrivilegeEnabled,
104 FALSE,
105 &WasPrivilegeEnabled);
106
107 done:
108 RtlFreeHeap(ConSrvHeap, 0, pszDriverPath);
109 return RtlNtStatusToDosError(Status);
110 }
111
112 #ifdef BLUESCREEN_DRIVER_UNLOADING
113 static DWORD
114 ScmUnloadDriver(LPCWSTR lpServiceName)
115 {
116 NTSTATUS Status = STATUS_SUCCESS;
117 BOOLEAN WasPrivilegeEnabled = FALSE;
118 PWSTR pszDriverPath;
119 UNICODE_STRING DriverPath;
120
121 /* Build the driver path */
122 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
123 pszDriverPath = RtlAllocateHeap(ConSrvHeap,
124 HEAP_ZERO_MEMORY,
125 (52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR));
126 if (pszDriverPath == NULL)
127 return ERROR_NOT_ENOUGH_MEMORY;
128
129 wcscpy(pszDriverPath,
130 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
131 wcscat(pszDriverPath,
132 lpServiceName);
133
134 RtlInitUnicodeString(&DriverPath,
135 pszDriverPath);
136
137 DPRINT(" Path: %wZ\n", &DriverPath);
138
139 /* Acquire driver-unloading privilege */
140 Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
141 TRUE,
142 FALSE,
143 &WasPrivilegeEnabled);
144 if (!NT_SUCCESS(Status))
145 {
146 /* We encountered a failure, exit properly */
147 DPRINT1("CONSRV: Cannot acquire driver-unloading privilege, Status = 0x%08lx\n", Status);
148 goto done;
149 }
150
151 Status = NtUnloadDriver(&DriverPath);
152
153 /* Release driver-unloading privilege */
154 RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
155 WasPrivilegeEnabled,
156 FALSE,
157 &WasPrivilegeEnabled);
158
159 done:
160 RtlFreeHeap(ConSrvHeap, 0, pszDriverPath);
161 return RtlNtStatusToDosError(Status);
162 }
163 #endif
164 /**\
165 \******************************************************************************/
166
167 static BOOL FASTCALL
168 TuiSwapConsole(INT Next)
169 {
170 static PTUI_CONSOLE_DATA SwapConsole = NULL; /* Console we are thinking about swapping with */
171 DWORD BytesReturned;
172 ANSI_STRING Title;
173 PVOID Buffer;
174 PCOORD pos;
175
176 if (0 != Next)
177 {
178 /*
179 * Alt-Tab, swap consoles.
180 * move SwapConsole to next console, and print its title.
181 */
182 EnterCriticalSection(&ActiveVirtConsLock);
183 if (!SwapConsole) SwapConsole = ActiveConsole;
184
185 SwapConsole = (0 < Next ? GetNextConsole(SwapConsole) : GetPrevConsole(SwapConsole));
186 Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Console->Title);
187 Title.Length = 0;
188 Buffer = RtlAllocateHeap(ConSrvHeap, 0,
189 sizeof(COORD) + Title.MaximumLength);
190 pos = (PCOORD)Buffer;
191 Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(COORD));
192
193 RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Console->Title, FALSE);
194 pos->X = (PhysicalConsoleSize.X - Title.Length) / 2;
195 pos->Y = PhysicalConsoleSize.Y / 2;
196 /* Redraw the console to clear off old title */
197 ConioDrawConsole(ActiveConsole->Console);
198 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
199 NULL, 0, Buffer, sizeof(COORD) + Title.Length,
200 &BytesReturned, NULL))
201 {
202 DPRINT1( "Error writing to console\n" );
203 }
204 RtlFreeHeap(ConSrvHeap, 0, Buffer);
205 LeaveCriticalSection(&ActiveVirtConsLock);
206
207 return TRUE;
208 }
209 else if (NULL != SwapConsole)
210 {
211 EnterCriticalSection(&ActiveVirtConsLock);
212 if (SwapConsole != ActiveConsole)
213 {
214 /* First remove swapconsole from the list */
215 SwapConsole->Entry.Blink->Flink = SwapConsole->Entry.Flink;
216 SwapConsole->Entry.Flink->Blink = SwapConsole->Entry.Blink;
217 /* Now insert before activeconsole */
218 SwapConsole->Entry.Flink = &ActiveConsole->Entry;
219 SwapConsole->Entry.Blink = ActiveConsole->Entry.Blink;
220 ActiveConsole->Entry.Blink->Flink = &SwapConsole->Entry;
221 ActiveConsole->Entry.Blink = &SwapConsole->Entry;
222 }
223 ActiveConsole = SwapConsole;
224 SwapConsole = NULL;
225 ConioDrawConsole(ActiveConsole->Console);
226 LeaveCriticalSection(&ActiveVirtConsLock);
227 return TRUE;
228 }
229 else
230 {
231 return FALSE;
232 }
233 }
234
235 static VOID FASTCALL
236 TuiCopyRect(char *Dest, PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
237 {
238 UINT SrcDelta, DestDelta;
239 LONG i;
240 PBYTE Src, SrcEnd;
241
242 Src = ConioCoordToPointer(Buff, Region->Left, Region->Top);
243 SrcDelta = Buff->ScreenBufferSize.X * 2;
244 SrcEnd = Buff->Buffer + Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * 2;
245 DestDelta = ConioRectWidth(Region) * 2;
246 for (i = Region->Top; i <= Region->Bottom; i++)
247 {
248 memcpy(Dest, Src, DestDelta);
249 Src += SrcDelta;
250 if (SrcEnd <= Src)
251 {
252 Src -= Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * 2;
253 }
254 Dest += DestDelta;
255 }
256 }
257
258 static LRESULT CALLBACK
259 TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
260 {
261 /*
262 PTUI_CONSOLE_DATA TuiData = NULL;
263 PCONSOLE Console = NULL;
264
265 TuiData = TuiGetGuiData(hWnd);
266 if (TuiData == NULL) return 0;
267 */
268
269 switch (msg)
270 {
271 case WM_CHAR:
272 case WM_SYSCHAR:
273 case WM_KEYDOWN:
274 case WM_SYSKEYDOWN:
275 case WM_KEYUP:
276 case WM_SYSKEYUP:
277 {
278 if (ConSrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
279 {
280 MSG Message;
281 Message.hwnd = hWnd;
282 Message.message = msg;
283 Message.wParam = wParam;
284 Message.lParam = lParam;
285
286 ConioProcessKey(ActiveConsole->Console, &Message);
287 LeaveCriticalSection(&ActiveConsole->Console->Lock);
288 }
289 break;
290 }
291
292 case WM_ACTIVATE:
293 {
294 if (ConSrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
295 {
296 if (LOWORD(wParam) != WA_INACTIVE)
297 {
298 SetFocus(hWnd);
299 ConioDrawConsole(ActiveConsole->Console);
300 }
301 LeaveCriticalSection(&ActiveConsole->Console->Lock);
302 }
303 break;
304 }
305
306 default:
307 break;
308 }
309
310 return DefWindowProcW(hWnd, msg, wParam, lParam);
311 }
312
313 static DWORD WINAPI
314 TuiConsoleThread(PVOID Data)
315 {
316 PTUI_CONSOLE_DATA TuiData = (PTUI_CONSOLE_DATA)Data;
317 PCONSOLE Console = TuiData->Console;
318 HWND NewWindow;
319 MSG msg;
320
321 NewWindow = CreateWindowW(TUI_CONSOLE_WINDOW_CLASS,
322 Console->Title.Buffer,
323 0,
324 -32000, -32000, 0, 0,
325 NULL, NULL,
326 ConSrvDllInstance,
327 (PVOID)Console);
328 if (NULL == NewWindow)
329 {
330 DPRINT1("CONSRV: Unable to create console window\n");
331 return 1;
332 }
333 TuiData->hWindow = NewWindow;
334
335 SetForegroundWindow(TuiData->hWindow);
336 NtUserConsoleControl(ConsoleAcquireDisplayOwnership, NULL, 0);
337
338 while (GetMessageW(&msg, NULL, 0, 0))
339 {
340 TranslateMessage(&msg);
341 DispatchMessageW(&msg);
342 }
343
344 return 0;
345 }
346
347 static BOOL
348 TuiInit(DWORD OemCP)
349 {
350 BOOL Ret = FALSE;
351 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
352 DWORD BytesReturned;
353 WNDCLASSEXW wc;
354 ATOM ConsoleClassAtom;
355 USHORT TextAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
356
357 /* Exit if we were already initialized */
358 if (ConsInitialized) return TRUE;
359
360 /*
361 * Initialize the TUI front-end:
362 * - load the console driver,
363 * - set default screen attributes,
364 * - grab the console size.
365 */
366 ScmLoadDriver(L"Blue");
367
368 ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen",
369 FILE_ALL_ACCESS,
370 0, NULL,
371 OPEN_EXISTING,
372 0, NULL);
373 if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle)
374 {
375 DPRINT1("Failed to open BlueScreen.\n");
376 return FALSE;
377 }
378
379 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT,
380 &OemCP, sizeof(OemCP), NULL, 0,
381 &BytesReturned, NULL))
382 {
383 DPRINT1("Failed to load the font for codepage %d\n", OemCP);
384 /* Let's suppose the font is good enough to continue */
385 }
386
387 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
388 &TextAttribute, sizeof(TextAttribute), NULL, 0,
389 &BytesReturned, NULL))
390 {
391 DPRINT1("Failed to set text attribute\n");
392 }
393
394 ActiveConsole = NULL;
395 InitializeListHead(&VirtConsList);
396 InitializeCriticalSection(&ActiveVirtConsLock);
397
398 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
399 NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL))
400 {
401 DPRINT1("Failed to get console info\n");
402 Ret = FALSE;
403 goto Quit;
404 }
405 PhysicalConsoleSize = ScrInfo.dwSize;
406
407 /* Register the TUI notification window class */
408 RtlZeroMemory(&wc, sizeof(WNDCLASSEXW));
409 wc.cbSize = sizeof(WNDCLASSEXW);
410 wc.lpszClassName = TUI_CONSOLE_WINDOW_CLASS;
411 wc.lpfnWndProc = TuiConsoleWndProc;
412 wc.cbWndExtra = 0;
413 wc.hInstance = ConSrvDllInstance;
414
415 ConsoleClassAtom = RegisterClassExW(&wc);
416 if (ConsoleClassAtom == 0)
417 {
418 DPRINT1("Failed to register TUI console wndproc\n");
419 Ret = FALSE;
420 }
421 else
422 {
423 Ret = TRUE;
424 }
425
426 Quit:
427 if (Ret == FALSE)
428 {
429 DeleteCriticalSection(&ActiveVirtConsLock);
430 CloseHandle(ConsoleDeviceHandle);
431 }
432
433 ConsInitialized = Ret;
434 return Ret;
435 }
436
437
438
439 /******************************************************************************
440 * TUI Console Driver *
441 ******************************************************************************/
442
443 static VOID WINAPI
444 TuiCleanupConsole(PCONSOLE Console)
445 {
446 PTUI_CONSOLE_DATA TuiData = Console->TermIFace.Data;
447
448 /* Close the notification window */
449 DestroyWindow(TuiData->hWindow);
450
451 /*
452 * Set the active console to the next one
453 * and remove the console from the list.
454 */
455 EnterCriticalSection(&ActiveVirtConsLock);
456 ActiveConsole = GetNextConsole(TuiData);
457 RemoveEntryList(&TuiData->Entry);
458
459 // /* Switch to next console */
460 // if (ActiveConsole == TuiData)
461 // if (ActiveConsole->Console == Console)
462 // {
463 // ActiveConsole = (TuiData->Entry.Flink != TuiData->Entry ? GetNextConsole(TuiData) : NULL);
464 // }
465
466 // if (GetNextConsole(TuiData) != TuiData)
467 // {
468 // TuiData->Entry.Blink->Flink = TuiData->Entry.Flink;
469 // TuiData->Entry.Flink->Blink = TuiData->Entry.Blink;
470 // }
471
472 LeaveCriticalSection(&ActiveVirtConsLock);
473
474 /* Switch to the next console */
475 if (NULL != ActiveConsole) ConioDrawConsole(ActiveConsole->Console);
476
477 Console->TermIFace.Data = NULL;
478 DeleteCriticalSection(&TuiData->Lock);
479 RtlFreeHeap(ConSrvHeap, 0, TuiData);
480 }
481
482 static VOID WINAPI
483 TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
484 UINT ScrolledLines, CHAR *Buffer, UINT Length)
485 {
486 DWORD BytesWritten;
487 PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
488
489 if (ActiveConsole->Console->ActiveBuffer != Buff) return;
490
491 if (!WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL))
492 {
493 DPRINT1("Error writing to BlueScreen\n");
494 }
495 }
496
497 static VOID WINAPI
498 TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
499 {
500 DWORD BytesReturned;
501 PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
502 PCONSOLE_DRAW ConsoleDraw;
503 UINT ConsoleDrawSize;
504
505 if (ActiveConsole->Console != Console) return;
506
507 ConsoleDrawSize = sizeof(CONSOLE_DRAW) +
508 (ConioRectWidth(Region) * ConioRectHeight(Region)) * 2;
509 ConsoleDraw = RtlAllocateHeap(ConSrvHeap, 0, ConsoleDrawSize);
510 if (NULL == ConsoleDraw)
511 {
512 DPRINT1("RtlAllocateHeap failed\n");
513 return;
514 }
515 ConsoleDraw->X = Region->Left;
516 ConsoleDraw->Y = Region->Top;
517 ConsoleDraw->SizeX = ConioRectWidth(Region);
518 ConsoleDraw->SizeY = ConioRectHeight(Region);
519 ConsoleDraw->CursorX = Buff->CursorPosition.X;
520 ConsoleDraw->CursorY = Buff->CursorPosition.Y;
521
522 TuiCopyRect((char *) (ConsoleDraw + 1), Buff, Region);
523
524 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW,
525 NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL))
526 {
527 DPRINT1("Failed to draw console\n");
528 RtlFreeHeap(ConSrvHeap, 0, ConsoleDraw);
529 return;
530 }
531
532 RtlFreeHeap(ConSrvHeap, 0, ConsoleDraw);
533 }
534
535 static BOOL WINAPI
536 TuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
537 {
538 CONSOLE_CURSOR_INFO Info;
539 DWORD BytesReturned;
540
541 if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE;
542
543 Info.dwSize = ConioEffectiveCursorSize(Console, 100);
544 Info.bVisible = Buff->CursorInfo.bVisible;
545
546 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO,
547 &Info, sizeof(Info), NULL, 0, &BytesReturned, NULL))
548 {
549 DPRINT1( "Failed to set cursor info\n" );
550 return FALSE;
551 }
552
553 return TRUE;
554 }
555
556 static BOOL WINAPI
557 TuiSetScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, SHORT OldCursorX, SHORT OldCursorY)
558 {
559 CONSOLE_SCREEN_BUFFER_INFO Info;
560 DWORD BytesReturned;
561
562 if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE;
563
564 Info.dwCursorPosition = Buff->CursorPosition;
565 Info.wAttributes = Buff->ScreenDefaultAttrib;
566
567 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
568 &Info, sizeof(CONSOLE_SCREEN_BUFFER_INFO), NULL, 0,
569 &BytesReturned, NULL))
570 {
571 DPRINT1( "Failed to set cursor position\n" );
572 return FALSE;
573 }
574
575 return TRUE;
576 }
577
578 static BOOL WINAPI
579 TuiUpdateScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
580 {
581 return TRUE;
582 }
583
584 static BOOL WINAPI
585 TuiIsBufferResizeSupported(PCONSOLE Console)
586 {
587 return (Console && Console->State == CONSOLE_INITIALIZING ? TRUE : FALSE);
588 }
589
590 static VOID WINAPI
591 TuiResizeTerminal(PCONSOLE Console)
592 {
593 }
594
595 static BOOL WINAPI
596 TuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD ShiftState, UINT VirtualKeyCode, BOOL Down)
597 {
598 if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) &&
599 VK_TAB == VirtualKeyCode)
600 {
601 if (Down)
602 {
603 TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1);
604 }
605
606 return TRUE;
607 }
608 else if (VK_MENU == VirtualKeyCode && !Down)
609 {
610 return TuiSwapConsole(0);
611 }
612
613 return FALSE;
614 }
615
616 static VOID WINAPI
617 TuiRefreshInternalInfo(PCONSOLE Console)
618 {
619 }
620
621 static VOID WINAPI
622 TuiChangeTitle(PCONSOLE Console)
623 {
624 }
625
626 static BOOL WINAPI
627 TuiChangeIcon(PCONSOLE Console, HICON hWindowIcon)
628 {
629 return TRUE;
630 }
631
632 static HWND WINAPI
633 TuiGetConsoleWindowHandle(PCONSOLE Console)
634 {
635 PTUI_CONSOLE_DATA TuiData = Console->TermIFace.Data;
636 return TuiData->hWindow;
637 }
638
639 static VOID WINAPI
640 TuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize)
641 {
642 if (!pSize) return;
643 *pSize = PhysicalConsoleSize;
644 }
645
646 static FRONTEND_VTBL TuiVtbl =
647 {
648 TuiCleanupConsole,
649 TuiWriteStream,
650 TuiDrawRegion,
651 TuiSetCursorInfo,
652 TuiSetScreenInfo,
653 TuiUpdateScreenInfo,
654 TuiIsBufferResizeSupported,
655 TuiResizeTerminal,
656 TuiProcessKeyCallback,
657 TuiRefreshInternalInfo,
658 TuiChangeTitle,
659 TuiChangeIcon,
660 TuiGetConsoleWindowHandle,
661 TuiGetLargestConsoleWindowSize
662 };
663
664 NTSTATUS FASTCALL
665 TuiInitConsole(PCONSOLE Console,
666 /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo,
667 PCONSOLE_INFO ConsoleInfo,
668 DWORD ProcessId)
669 {
670 PTUI_CONSOLE_DATA TuiData;
671 HANDLE ThreadHandle;
672
673 if (Console == NULL || ConsoleInfo == NULL)
674 return STATUS_INVALID_PARAMETER;
675
676 /* Initialize the TUI terminal emulator */
677 if (!TuiInit(Console->CodePage)) return STATUS_UNSUCCESSFUL;
678
679 /* Initialize the console */
680 Console->TermIFace.Vtbl = &TuiVtbl;
681
682 TuiData = RtlAllocateHeap(ConSrvHeap, HEAP_ZERO_MEMORY,
683 sizeof(TUI_CONSOLE_DATA));
684 if (!TuiData)
685 {
686 DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
687 return STATUS_UNSUCCESSFUL;
688 }
689 Console->TermIFace.Data = (PVOID)TuiData;
690 TuiData->Console = Console;
691 TuiData->hWindow = NULL;
692
693 InitializeCriticalSection(&TuiData->Lock);
694
695 /*
696 * HACK: Resize the console since we don't support for now changing
697 * the console size when we display it with the hardware.
698 */
699 Console->ConsoleSize = PhysicalConsoleSize;
700 ConioResizeBuffer(Console, Console->ActiveBuffer, PhysicalConsoleSize);
701 Console->ActiveBuffer->DisplayMode |= CONSOLE_FULLSCREEN_MODE;
702 // ConioResizeTerminal(Console);
703
704 /*
705 * Contrary to what we do in the GUI front-end, here we create
706 * an input thread for each console. It will dispatch all the
707 * input messages to the proper console (on the GUI it is done
708 * via the default GUI dispatch thread).
709 */
710 ThreadHandle = CreateThread(NULL,
711 0,
712 TuiConsoleThread,
713 (PVOID)TuiData,
714 0,
715 NULL);
716 if (NULL == ThreadHandle)
717 {
718 DPRINT1("CONSRV: Unable to create console thread\n");
719 TuiCleanupConsole(Console);
720 return STATUS_UNSUCCESSFUL;
721 }
722 CloseHandle(ThreadHandle);
723
724 /*
725 * Insert the newly created console in the list of virtual consoles
726 * and activate it (give it the focus).
727 */
728 EnterCriticalSection(&ActiveVirtConsLock);
729 InsertTailList(&VirtConsList, &TuiData->Entry);
730 ActiveConsole = TuiData;
731 LeaveCriticalSection(&ActiveVirtConsLock);
732
733 return STATUS_SUCCESS;
734 }
735
736 /* EOF */