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