[CRT] Remove useless #undef abort from process.h
[reactos.git] / win32ss / user / winsrv / 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/winsrv/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 #ifdef TUITERM_COMPILE
13
14 #include <consrv.h>
15
16 // #include "include/conio.h"
17 #include "include/console.h"
18 #include "include/settings.h"
19 #include "tuiterm.h"
20
21 #include <ndk/iofuncs.h>
22 #include <ndk/setypes.h>
23 #include <drivers/blue/ntddblue.h>
24
25 #define NDEBUG
26 #include <debug.h>
27
28
29 /* GLOBALS ********************************************************************/
30
31 #define ConsoleOutputUnicodeToAnsiChar(Console, dChar, sWChar) \
32 do { \
33 ASSERT((ULONG_PTR)(dChar) != (ULONG_PTR)(sWChar)); \
34 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL); \
35 } while (0)
36
37 /* TUI Console Window Class name */
38 #define TUI_CONSOLE_WINDOW_CLASS L"TuiConsoleWindowClass"
39
40 typedef struct _TUI_CONSOLE_DATA
41 {
42 CRITICAL_SECTION Lock;
43 LIST_ENTRY Entry; /* Entry in the list of virtual consoles */
44 // HANDLE hTuiInitEvent;
45 // HANDLE hTuiTermEvent;
46
47 HWND hWindow; /* Handle to the console's window (used for the window's procedure) */
48
49 PCONSRV_CONSOLE Console; /* Pointer to the owned console */
50 PCONSOLE_SCREEN_BUFFER ActiveBuffer; /* Pointer to the active screen buffer (then maybe the previous Console member is redundant?? Or not...) */
51 // TUI_CONSOLE_INFO TuiInfo; /* TUI terminal settings */
52 } TUI_CONSOLE_DATA, *PTUI_CONSOLE_DATA;
53
54 #define GetNextConsole(Console) \
55 CONTAINING_RECORD(Console->Entry.Flink, TUI_CONSOLE_DATA, Entry)
56
57 #define GetPrevConsole(Console) \
58 CONTAINING_RECORD(Console->Entry.Blink, TUI_CONSOLE_DATA, Entry)
59
60
61 /* List of the maintained virtual consoles and its lock */
62 static LIST_ENTRY VirtConsList;
63 static PTUI_CONSOLE_DATA ActiveConsole; /* The active console on screen */
64 static CRITICAL_SECTION ActiveVirtConsLock;
65
66 static COORD PhysicalConsoleSize;
67 static HANDLE ConsoleDeviceHandle;
68
69 static BOOL ConsInitialized = FALSE;
70
71 /******************************************************************************\
72 |** BlueScreen Driver management **|
73 \**/
74 /* Code taken and adapted from base/system/services/driver.c */
75 static DWORD
76 ScmLoadDriver(LPCWSTR lpServiceName)
77 {
78 NTSTATUS Status = STATUS_SUCCESS;
79 BOOLEAN WasPrivilegeEnabled = FALSE;
80 PWSTR pszDriverPath;
81 UNICODE_STRING DriverPath;
82
83 /* Build the driver path */
84 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
85 pszDriverPath = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
86 (52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR));
87 if (pszDriverPath == NULL)
88 return ERROR_NOT_ENOUGH_MEMORY;
89
90 wcscpy(pszDriverPath,
91 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
92 wcscat(pszDriverPath,
93 lpServiceName);
94
95 RtlInitUnicodeString(&DriverPath,
96 pszDriverPath);
97
98 DPRINT(" Path: %wZ\n", &DriverPath);
99
100 /* Acquire driver-loading privilege */
101 Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
102 TRUE,
103 FALSE,
104 &WasPrivilegeEnabled);
105 if (!NT_SUCCESS(Status))
106 {
107 /* We encountered a failure, exit properly */
108 DPRINT1("CONSRV: Cannot acquire driver-loading privilege, Status = 0x%08lx\n", Status);
109 goto done;
110 }
111
112 Status = NtLoadDriver(&DriverPath);
113
114 /* Release driver-loading privilege */
115 RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
116 WasPrivilegeEnabled,
117 FALSE,
118 &WasPrivilegeEnabled);
119
120 done:
121 ConsoleFreeHeap(pszDriverPath);
122 return RtlNtStatusToDosError(Status);
123 }
124
125 #ifdef BLUESCREEN_DRIVER_UNLOADING
126 static DWORD
127 ScmUnloadDriver(LPCWSTR lpServiceName)
128 {
129 NTSTATUS Status = STATUS_SUCCESS;
130 BOOLEAN WasPrivilegeEnabled = FALSE;
131 PWSTR pszDriverPath;
132 UNICODE_STRING DriverPath;
133
134 /* Build the driver path */
135 /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
136 pszDriverPath = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
137 (52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR));
138 if (pszDriverPath == NULL)
139 return ERROR_NOT_ENOUGH_MEMORY;
140
141 wcscpy(pszDriverPath,
142 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
143 wcscat(pszDriverPath,
144 lpServiceName);
145
146 RtlInitUnicodeString(&DriverPath,
147 pszDriverPath);
148
149 DPRINT(" Path: %wZ\n", &DriverPath);
150
151 /* Acquire driver-unloading privilege */
152 Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
153 TRUE,
154 FALSE,
155 &WasPrivilegeEnabled);
156 if (!NT_SUCCESS(Status))
157 {
158 /* We encountered a failure, exit properly */
159 DPRINT1("CONSRV: Cannot acquire driver-unloading privilege, Status = 0x%08lx\n", Status);
160 goto done;
161 }
162
163 Status = NtUnloadDriver(&DriverPath);
164
165 /* Release driver-unloading privilege */
166 RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
167 WasPrivilegeEnabled,
168 FALSE,
169 &WasPrivilegeEnabled);
170
171 done:
172 ConsoleFreeHeap(pszDriverPath);
173 return RtlNtStatusToDosError(Status);
174 }
175 #endif
176 /**\
177 \******************************************************************************/
178
179 #if 0
180 static BOOL
181 TuiSwapConsole(INT Next)
182 {
183 static PTUI_CONSOLE_DATA SwapConsole = NULL; /* Console we are thinking about swapping with */
184 DWORD BytesReturned;
185 ANSI_STRING Title;
186 PVOID Buffer;
187 PCOORD pos;
188
189 if (0 != Next)
190 {
191 /*
192 * Alt-Tab, swap consoles.
193 * move SwapConsole to next console, and print its title.
194 */
195 EnterCriticalSection(&ActiveVirtConsLock);
196 if (!SwapConsole) SwapConsole = ActiveConsole;
197
198 SwapConsole = (0 < Next ? GetNextConsole(SwapConsole) : GetPrevConsole(SwapConsole));
199 Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Console->Title);
200 Title.Length = 0;
201 Buffer = ConsoleAllocHeap(0, sizeof(COORD) + Title.MaximumLength);
202 pos = (PCOORD)Buffer;
203 Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(COORD));
204
205 RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Console->Title, FALSE);
206 pos->X = (PhysicalConsoleSize.X - Title.Length) / 2;
207 pos->Y = PhysicalConsoleSize.Y / 2;
208 /* Redraw the console to clear off old title */
209 ConioDrawConsole(ActiveConsole->Console);
210 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
211 NULL, 0, Buffer, sizeof(COORD) + Title.Length,
212 &BytesReturned, NULL))
213 {
214 DPRINT1( "Error writing to console\n" );
215 }
216 ConsoleFreeHeap(Buffer);
217 LeaveCriticalSection(&ActiveVirtConsLock);
218
219 return TRUE;
220 }
221 else if (NULL != SwapConsole)
222 {
223 EnterCriticalSection(&ActiveVirtConsLock);
224 if (SwapConsole != ActiveConsole)
225 {
226 /* First remove swapconsole from the list */
227 SwapConsole->Entry.Blink->Flink = SwapConsole->Entry.Flink;
228 SwapConsole->Entry.Flink->Blink = SwapConsole->Entry.Blink;
229 /* Now insert before activeconsole */
230 SwapConsole->Entry.Flink = &ActiveConsole->Entry;
231 SwapConsole->Entry.Blink = ActiveConsole->Entry.Blink;
232 ActiveConsole->Entry.Blink->Flink = &SwapConsole->Entry;
233 ActiveConsole->Entry.Blink = &SwapConsole->Entry;
234 }
235 ActiveConsole = SwapConsole;
236 SwapConsole = NULL;
237 ConioDrawConsole(ActiveConsole->Console);
238 LeaveCriticalSection(&ActiveVirtConsLock);
239 return TRUE;
240 }
241 else
242 {
243 return FALSE;
244 }
245 }
246 #endif
247
248 static VOID
249 TuiCopyRect(PCHAR Dest, PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* Region)
250 {
251 UINT SrcDelta, DestDelta;
252 LONG i;
253 PCHAR_INFO Src, SrcEnd;
254
255 Src = ConioCoordToPointer(Buff, Region->Left, Region->Top);
256 SrcDelta = Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
257 SrcEnd = Buff->Buffer + Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
258 DestDelta = ConioRectWidth(Region) * 2 /* 2 == sizeof(CHAR) + sizeof(BYTE) */;
259 for (i = Region->Top; i <= Region->Bottom; i++)
260 {
261 ConsoleOutputUnicodeToAnsiChar(Buff->Header.Console, (PCHAR)Dest, &Src->Char.UnicodeChar);
262 *(PBYTE)(Dest + 1) = (BYTE)Src->Attributes;
263
264 Src += SrcDelta;
265 if (SrcEnd <= Src)
266 {
267 Src -= Buff->ScreenBufferSize.Y * Buff->ScreenBufferSize.X * sizeof(CHAR_INFO);
268 }
269 Dest += DestDelta;
270 }
271 }
272
273 static LRESULT CALLBACK
274 TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
275 {
276 /*
277 PTUI_CONSOLE_DATA TuiData = NULL;
278 PCONSRV_CONSOLE Console = NULL;
279
280 TuiData = TuiGetGuiData(hWnd);
281 if (TuiData == NULL) return 0;
282 */
283
284 switch (msg)
285 {
286 case WM_CHAR:
287 case WM_SYSCHAR:
288 case WM_KEYDOWN:
289 case WM_SYSKEYDOWN:
290 case WM_KEYUP:
291 case WM_SYSKEYUP:
292 {
293 #if 0
294 if ((HIWORD(lParam) & KF_ALTDOWN) && wParam == VK_TAB)
295 {
296 // if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT)
297 TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1);
298
299 break;
300 }
301 else if (wParam == VK_MENU /* && !Down */)
302 {
303 TuiSwapConsole(0);
304 break;
305 }
306 #endif
307
308 if (ConDrvValidateConsoleUnsafe((PCONSOLE)ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
309 {
310 MSG Message;
311 Message.hwnd = hWnd;
312 Message.message = msg;
313 Message.wParam = wParam;
314 Message.lParam = lParam;
315
316 ConioProcessKey(ActiveConsole->Console, &Message);
317 LeaveCriticalSection(&ActiveConsole->Console->Lock);
318 }
319 break;
320 }
321
322 case WM_ACTIVATE:
323 {
324 if (ConDrvValidateConsoleUnsafe((PCONSOLE)ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
325 {
326 if (LOWORD(wParam) != WA_INACTIVE)
327 {
328 SetFocus(hWnd);
329 ConioDrawConsole(ActiveConsole->Console);
330 }
331 LeaveCriticalSection(&ActiveConsole->Console->Lock);
332 }
333 break;
334 }
335
336 default:
337 break;
338 }
339
340 return DefWindowProcW(hWnd, msg, wParam, lParam);
341 }
342
343 static DWORD NTAPI
344 TuiConsoleThread(PVOID Param)
345 {
346 PTUI_CONSOLE_DATA TuiData = (PTUI_CONSOLE_DATA)Param;
347 PCONSRV_CONSOLE Console = TuiData->Console;
348 HWND NewWindow;
349 MSG msg;
350
351 NewWindow = CreateWindowW(TUI_CONSOLE_WINDOW_CLASS,
352 Console->Title.Buffer,
353 0,
354 -32000, -32000, 0, 0,
355 NULL, NULL,
356 ConSrvDllInstance,
357 (PVOID)Console);
358 if (NULL == NewWindow)
359 {
360 DPRINT1("CONSRV: Unable to create console window\n");
361 return 1;
362 }
363 TuiData->hWindow = NewWindow;
364
365 SetForegroundWindow(TuiData->hWindow);
366 NtUserConsoleControl(ConsoleAcquireDisplayOwnership, NULL, 0);
367
368 while (GetMessageW(&msg, NULL, 0, 0))
369 {
370 TranslateMessage(&msg);
371 DispatchMessageW(&msg);
372 }
373
374 return 0;
375 }
376
377 static BOOL
378 TuiInit(DWORD OemCP)
379 {
380 BOOL Success;
381 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
382 DWORD BytesReturned;
383 WNDCLASSEXW wc;
384 ATOM ConsoleClassAtom;
385 USHORT TextAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
386
387 /* Exit if we were already initialized */
388 if (ConsInitialized) return TRUE;
389
390 /*
391 * Initialize the TUI front-end:
392 * - load the console driver,
393 * - open BlueScreen device and enable it,
394 * - set default screen attributes,
395 * - grab the console size.
396 */
397 ScmLoadDriver(L"Blue");
398
399 ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen",
400 FILE_ALL_ACCESS,
401 0, NULL,
402 OPEN_EXISTING,
403 0, NULL);
404 if (ConsoleDeviceHandle == INVALID_HANDLE_VALUE)
405 {
406 DPRINT1("Failed to open BlueScreen.\n");
407 return FALSE;
408 }
409
410 Success = TRUE;
411 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_RESET_SCREEN,
412 &Success, sizeof(Success), NULL, 0,
413 &BytesReturned, NULL))
414 {
415 DPRINT1("Failed to enable the screen.\n");
416 CloseHandle(ConsoleDeviceHandle);
417 return FALSE;
418 }
419
420 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT,
421 &OemCP, sizeof(OemCP), NULL, 0,
422 &BytesReturned, NULL))
423 {
424 DPRINT1("Failed to load the font for codepage %d\n", OemCP);
425 /* Let's suppose the font is good enough to continue */
426 }
427
428 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
429 &TextAttribute, sizeof(TextAttribute), NULL, 0,
430 &BytesReturned, NULL))
431 {
432 DPRINT1("Failed to set text attribute.\n");
433 }
434
435 ActiveConsole = NULL;
436 InitializeListHead(&VirtConsList);
437 InitializeCriticalSection(&ActiveVirtConsLock);
438
439 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
440 NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL))
441 {
442 DPRINT1("Failed to get console info.\n");
443 Success = FALSE;
444 goto Quit;
445 }
446 PhysicalConsoleSize = ScrInfo.dwSize;
447
448 /* Register the TUI notification window class */
449 RtlZeroMemory(&wc, sizeof(WNDCLASSEXW));
450 wc.cbSize = sizeof(WNDCLASSEXW);
451 wc.lpszClassName = TUI_CONSOLE_WINDOW_CLASS;
452 wc.lpfnWndProc = TuiConsoleWndProc;
453 wc.cbWndExtra = 0;
454 wc.hInstance = ConSrvDllInstance;
455
456 ConsoleClassAtom = RegisterClassExW(&wc);
457 if (ConsoleClassAtom == 0)
458 {
459 DPRINT1("Failed to register TUI console wndproc.\n");
460 Success = FALSE;
461 }
462 else
463 {
464 Success = TRUE;
465 }
466
467 Quit:
468 if (!Success)
469 {
470 DeleteCriticalSection(&ActiveVirtConsLock);
471 CloseHandle(ConsoleDeviceHandle);
472 }
473
474 ConsInitialized = Success;
475 return Success;
476 }
477
478
479
480 /******************************************************************************
481 * TUI Console Driver *
482 ******************************************************************************/
483
484 static VOID NTAPI
485 TuiDeinitFrontEnd(IN OUT PFRONTEND This /*,
486 IN PCONSRV_CONSOLE Console */);
487
488 static NTSTATUS NTAPI
489 TuiInitFrontEnd(IN OUT PFRONTEND This,
490 IN PCONSRV_CONSOLE Console)
491 {
492 PTUI_CONSOLE_DATA TuiData;
493 HANDLE ThreadHandle;
494
495 if (This == NULL || Console == NULL)
496 return STATUS_INVALID_PARAMETER;
497
498 if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
499 return STATUS_INVALID_PARAMETER;
500
501 TuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(TUI_CONSOLE_DATA));
502 if (!TuiData)
503 {
504 DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
505 return STATUS_UNSUCCESSFUL;
506 }
507 // Console->FrontEndIFace.Context = (PVOID)TuiData;
508 TuiData->Console = Console;
509 TuiData->ActiveBuffer = Console->ActiveBuffer;
510 TuiData->hWindow = NULL;
511
512 InitializeCriticalSection(&TuiData->Lock);
513
514 /*
515 * HACK: Resize the console since we don't support for now changing
516 * the console size when we display it with the hardware.
517 */
518 // Console->ConsoleSize = PhysicalConsoleSize;
519 // ConioResizeBuffer(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), PhysicalConsoleSize);
520
521 // /* The console cannot be resized anymore */
522 // Console->FixedSize = TRUE; // MUST be placed AFTER the call to ConioResizeBuffer !!
523 // // TermResizeTerminal(Console);
524
525 /*
526 * Contrary to what we do in the GUI front-end, here we create
527 * an input thread for each console. It will dispatch all the
528 * input messages to the proper console (on the GUI it is done
529 * via the default GUI dispatch thread).
530 */
531 ThreadHandle = CreateThread(NULL,
532 0,
533 TuiConsoleThread,
534 (PVOID)TuiData,
535 0,
536 NULL);
537 if (NULL == ThreadHandle)
538 {
539 DPRINT1("CONSRV: Unable to create console thread\n");
540 // TuiDeinitFrontEnd(Console);
541 TuiDeinitFrontEnd(This);
542 return STATUS_UNSUCCESSFUL;
543 }
544 CloseHandle(ThreadHandle);
545
546 /*
547 * Insert the newly created console in the list of virtual consoles
548 * and activate it (give it the focus).
549 */
550 EnterCriticalSection(&ActiveVirtConsLock);
551 InsertTailList(&VirtConsList, &TuiData->Entry);
552 ActiveConsole = TuiData;
553 LeaveCriticalSection(&ActiveVirtConsLock);
554
555 /* Finally, initialize the frontend structure */
556 This->Context = TuiData;
557 This->Context2 = NULL;
558
559 return STATUS_SUCCESS;
560 }
561
562 static VOID NTAPI
563 TuiDeinitFrontEnd(IN OUT PFRONTEND This)
564 {
565 // PCONSRV_CONSOLE Console = This->Console;
566 PTUI_CONSOLE_DATA TuiData = This->Context;
567
568 /* Close the notification window */
569 DestroyWindow(TuiData->hWindow);
570
571 /*
572 * Set the active console to the next one
573 * and remove the console from the list.
574 */
575 EnterCriticalSection(&ActiveVirtConsLock);
576 ActiveConsole = GetNextConsole(TuiData);
577 RemoveEntryList(&TuiData->Entry);
578
579 // /* Switch to next console */
580 // if (ActiveConsole == TuiData)
581 // if (ActiveConsole->Console == Console)
582 // {
583 // ActiveConsole = (TuiData->Entry.Flink != TuiData->Entry ? GetNextConsole(TuiData) : NULL);
584 // }
585
586 // if (GetNextConsole(TuiData) != TuiData)
587 // {
588 // TuiData->Entry.Blink->Flink = TuiData->Entry.Flink;
589 // TuiData->Entry.Flink->Blink = TuiData->Entry.Blink;
590 // }
591
592 LeaveCriticalSection(&ActiveVirtConsLock);
593
594 /* Switch to the next console */
595 if (NULL != ActiveConsole) ConioDrawConsole(ActiveConsole->Console);
596
597 This->Context = NULL;
598 DeleteCriticalSection(&TuiData->Lock);
599 ConsoleFreeHeap(TuiData);
600 }
601
602 static VOID NTAPI
603 TuiDrawRegion(IN OUT PFRONTEND This,
604 SMALL_RECT* Region)
605 {
606 PTUI_CONSOLE_DATA TuiData = This->Context;
607 PCONSOLE_SCREEN_BUFFER Buff = TuiData->Console->ActiveBuffer;
608 PCONSOLE_DRAW ConsoleDraw;
609 DWORD BytesReturned;
610 UINT ConsoleDrawSize;
611
612 if (TuiData != ActiveConsole) return;
613 if (GetType(Buff) != TEXTMODE_BUFFER) return;
614
615 ConsoleDrawSize = sizeof(CONSOLE_DRAW) +
616 (ConioRectWidth(Region) * ConioRectHeight(Region)) * 2;
617 ConsoleDraw = ConsoleAllocHeap(0, ConsoleDrawSize);
618 if (NULL == ConsoleDraw)
619 {
620 DPRINT1("ConsoleAllocHeap failed\n");
621 return;
622 }
623 ConsoleDraw->X = Region->Left;
624 ConsoleDraw->Y = Region->Top;
625 ConsoleDraw->SizeX = ConioRectWidth(Region);
626 ConsoleDraw->SizeY = ConioRectHeight(Region);
627 ConsoleDraw->CursorX = Buff->CursorPosition.X;
628 ConsoleDraw->CursorY = Buff->CursorPosition.Y;
629
630 TuiCopyRect((PCHAR)(ConsoleDraw + 1), (PTEXTMODE_SCREEN_BUFFER)Buff, Region);
631
632 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW,
633 NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL))
634 {
635 DPRINT1("Failed to draw console\n");
636 ConsoleFreeHeap(ConsoleDraw);
637 return;
638 }
639
640 ConsoleFreeHeap(ConsoleDraw);
641 }
642
643 static VOID NTAPI
644 TuiWriteStream(IN OUT PFRONTEND This,
645 SMALL_RECT* Region,
646 SHORT CursorStartX,
647 SHORT CursorStartY,
648 UINT ScrolledLines,
649 PWCHAR Buffer,
650 UINT Length)
651 {
652 PTUI_CONSOLE_DATA TuiData = This->Context;
653 PCONSOLE_SCREEN_BUFFER Buff = TuiData->Console->ActiveBuffer;
654 PCHAR NewBuffer;
655 ULONG NewLength;
656 DWORD BytesWritten;
657
658 if (TuiData != ActiveConsole) return;
659 if (GetType(Buff) != TEXTMODE_BUFFER) return;
660
661 NewLength = WideCharToMultiByte(TuiData->Console->OutputCodePage, 0,
662 Buffer, Length,
663 NULL, 0, NULL, NULL);
664 NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewLength * sizeof(CHAR));
665 if (!NewBuffer) return;
666
667 WideCharToMultiByte(TuiData->Console->OutputCodePage, 0,
668 Buffer, Length,
669 NewBuffer, NewLength, NULL, NULL);
670
671 if (!WriteFile(ConsoleDeviceHandle, NewBuffer, NewLength * sizeof(CHAR), &BytesWritten, NULL))
672 {
673 DPRINT1("Error writing to BlueScreen\n");
674 }
675
676 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
677 }
678
679 static VOID NTAPI
680 TuiRingBell(IN OUT PFRONTEND This)
681 {
682 Beep(800, 200);
683 }
684
685 static BOOL NTAPI
686 TuiSetCursorInfo(IN OUT PFRONTEND This,
687 PCONSOLE_SCREEN_BUFFER Buff)
688 {
689 PTUI_CONSOLE_DATA TuiData = This->Context;
690 CONSOLE_CURSOR_INFO Info;
691 DWORD BytesReturned;
692
693 if (TuiData != ActiveConsole) return TRUE;
694 if (TuiData->Console->ActiveBuffer != Buff) return TRUE;
695 if (GetType(Buff) != TEXTMODE_BUFFER) return FALSE;
696
697 Info.dwSize = ConioEffectiveCursorSize(TuiData->Console, 100);
698 Info.bVisible = Buff->CursorInfo.bVisible;
699
700 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO,
701 &Info, sizeof(Info), NULL, 0, &BytesReturned, NULL))
702 {
703 DPRINT1( "Failed to set cursor info\n" );
704 return FALSE;
705 }
706
707 return TRUE;
708 }
709
710 static BOOL NTAPI
711 TuiSetScreenInfo(IN OUT PFRONTEND This,
712 PCONSOLE_SCREEN_BUFFER Buff,
713 SHORT OldCursorX,
714 SHORT OldCursorY)
715 {
716 PTUI_CONSOLE_DATA TuiData = This->Context;
717 CONSOLE_SCREEN_BUFFER_INFO Info;
718 DWORD BytesReturned;
719
720 if (TuiData != ActiveConsole) return TRUE;
721 if (TuiData->Console->ActiveBuffer != Buff) return TRUE;
722 if (GetType(Buff) != TEXTMODE_BUFFER) return FALSE;
723
724 Info.dwCursorPosition = Buff->CursorPosition;
725 Info.wAttributes = ((PTEXTMODE_SCREEN_BUFFER)Buff)->ScreenDefaultAttrib;
726
727 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
728 &Info, sizeof(CONSOLE_SCREEN_BUFFER_INFO), NULL, 0,
729 &BytesReturned, NULL))
730 {
731 DPRINT1( "Failed to set cursor position\n" );
732 return FALSE;
733 }
734
735 return TRUE;
736 }
737
738 static VOID NTAPI
739 TuiResizeTerminal(IN OUT PFRONTEND This)
740 {
741 }
742
743 static VOID NTAPI
744 TuiSetActiveScreenBuffer(IN OUT PFRONTEND This)
745 {
746 // PGUI_CONSOLE_DATA GuiData = This->Context;
747 // PCONSOLE_SCREEN_BUFFER ActiveBuffer;
748 // HPALETTE hPalette;
749
750 // EnterCriticalSection(&GuiData->Lock);
751 // GuiData->WindowSizeLock = TRUE;
752
753 // InterlockedExchangePointer(&GuiData->ActiveBuffer,
754 // ConDrvGetActiveScreenBuffer(GuiData->Console));
755
756 // GuiData->WindowSizeLock = FALSE;
757 // LeaveCriticalSection(&GuiData->Lock);
758
759 // ActiveBuffer = GuiData->ActiveBuffer;
760
761 // /* Change the current palette */
762 // if (ActiveBuffer->PaletteHandle == NULL)
763 // {
764 // hPalette = GuiData->hSysPalette;
765 // }
766 // else
767 // {
768 // hPalette = ActiveBuffer->PaletteHandle;
769 // }
770
771 // DPRINT("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette);
772
773 // /* Set the new palette for the framebuffer */
774 // SelectPalette(GuiData->hMemDC, hPalette, FALSE);
775
776 // /* Specify the use of the system palette for the framebuffer */
777 // SetSystemPaletteUse(GuiData->hMemDC, ActiveBuffer->PaletteUsage);
778
779 // /* Realize the (logical) palette */
780 // RealizePalette(GuiData->hMemDC);
781
782 // GuiResizeTerminal(This);
783 // // ConioDrawConsole(Console);
784 }
785
786 static VOID NTAPI
787 TuiReleaseScreenBuffer(IN OUT PFRONTEND This,
788 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
789 {
790 // PGUI_CONSOLE_DATA GuiData = This->Context;
791
792 // /*
793 // * If we were notified to release a screen buffer that is not actually
794 // * ours, then just ignore the notification...
795 // */
796 // if (ScreenBuffer != GuiData->ActiveBuffer) return;
797
798 // /*
799 // * ... else, we must release our active buffer. Two cases are present:
800 // * - If ScreenBuffer (== GuiData->ActiveBuffer) IS NOT the console
801 // * active screen buffer, then we can safely switch to it.
802 // * - If ScreenBuffer IS the console active screen buffer, we must release
803 // * it ONLY.
804 // */
805
806 // /* Release the old active palette and set the default one */
807 // if (GetCurrentObject(GuiData->hMemDC, OBJ_PAL) == ScreenBuffer->PaletteHandle)
808 // {
809 // /* Set the new palette */
810 // SelectPalette(GuiData->hMemDC, GuiData->hSysPalette, FALSE);
811 // }
812
813 // /* Set the adequate active screen buffer */
814 // if (ScreenBuffer != GuiData->Console->ActiveBuffer)
815 // {
816 // GuiSetActiveScreenBuffer(This);
817 // }
818 // else
819 // {
820 // EnterCriticalSection(&GuiData->Lock);
821 // GuiData->WindowSizeLock = TRUE;
822
823 // InterlockedExchangePointer(&GuiData->ActiveBuffer, NULL);
824
825 // GuiData->WindowSizeLock = FALSE;
826 // LeaveCriticalSection(&GuiData->Lock);
827 // }
828 }
829
830 static VOID NTAPI
831 TuiRefreshInternalInfo(IN OUT PFRONTEND This)
832 {
833 }
834
835 static VOID NTAPI
836 TuiChangeTitle(IN OUT PFRONTEND This)
837 {
838 }
839
840 static BOOL NTAPI
841 TuiChangeIcon(IN OUT PFRONTEND This,
842 HICON IconHandle)
843 {
844 return TRUE;
845 }
846
847 static HDESK NTAPI
848 TuiGetThreadConsoleDesktop(IN OUT PFRONTEND This)
849 {
850 // PTUI_CONSOLE_DATA TuiData = This->Context;
851 return NULL;
852 }
853
854 static HWND NTAPI
855 TuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
856 {
857 PTUI_CONSOLE_DATA TuiData = This->Context;
858 return TuiData->hWindow;
859 }
860
861 static VOID NTAPI
862 TuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
863 PCOORD pSize)
864 {
865 if (!pSize) return;
866 *pSize = PhysicalConsoleSize;
867 }
868
869 static BOOL NTAPI
870 TuiGetSelectionInfo(IN OUT PFRONTEND This,
871 PCONSOLE_SELECTION_INFO pSelectionInfo)
872 {
873 return TRUE;
874 }
875
876 static BOOL NTAPI
877 TuiSetPalette(IN OUT PFRONTEND This,
878 HPALETTE PaletteHandle,
879 UINT PaletteUsage)
880 {
881 return TRUE;
882 }
883
884 static ULONG NTAPI
885 TuiGetDisplayMode(IN OUT PFRONTEND This)
886 {
887 return CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN;
888 }
889
890 static BOOL NTAPI
891 TuiSetDisplayMode(IN OUT PFRONTEND This,
892 ULONG NewMode)
893 {
894 // if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
895 // return FALSE;
896 return TRUE;
897 }
898
899 static INT NTAPI
900 TuiShowMouseCursor(IN OUT PFRONTEND This,
901 BOOL Show)
902 {
903 return 0;
904 }
905
906 static BOOL NTAPI
907 TuiSetMouseCursor(IN OUT PFRONTEND This,
908 HCURSOR CursorHandle)
909 {
910 return TRUE;
911 }
912
913 static HMENU NTAPI
914 TuiMenuControl(IN OUT PFRONTEND This,
915 UINT CmdIdLow,
916 UINT CmdIdHigh)
917 {
918 return NULL;
919 }
920
921 static BOOL NTAPI
922 TuiSetMenuClose(IN OUT PFRONTEND This,
923 BOOL Enable)
924 {
925 return TRUE;
926 }
927
928 static FRONTEND_VTBL TuiVtbl =
929 {
930 TuiInitFrontEnd,
931 TuiDeinitFrontEnd,
932 TuiDrawRegion,
933 TuiWriteStream,
934 TuiRingBell,
935 TuiSetCursorInfo,
936 TuiSetScreenInfo,
937 TuiResizeTerminal,
938 TuiSetActiveScreenBuffer,
939 TuiReleaseScreenBuffer,
940 TuiRefreshInternalInfo,
941 TuiChangeTitle,
942 TuiChangeIcon,
943 TuiGetThreadConsoleDesktop,
944 TuiGetConsoleWindowHandle,
945 TuiGetLargestConsoleWindowSize,
946 TuiGetSelectionInfo,
947 TuiSetPalette,
948 TuiGetDisplayMode,
949 TuiSetDisplayMode,
950 TuiShowMouseCursor,
951 TuiSetMouseCursor,
952 TuiMenuControl,
953 TuiSetMenuClose,
954 };
955
956 static BOOLEAN
957 IsConsoleMode(VOID)
958 {
959 return (BOOLEAN)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE);
960 }
961
962 NTSTATUS NTAPI
963 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
964 IN OUT PCONSOLE_STATE_INFO ConsoleInfo,
965 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
966 IN HANDLE ConsoleLeaderProcessHandle)
967 {
968 if (FrontEnd == NULL || ConsoleInfo == NULL)
969 return STATUS_INVALID_PARAMETER;
970
971 /* We must be in console mode already */
972 if (!IsConsoleMode()) return STATUS_UNSUCCESSFUL;
973
974 /* Initialize the TUI terminal emulator */
975 if (!TuiInit(ConsoleInfo->CodePage)) return STATUS_UNSUCCESSFUL;
976
977 /* Finally, initialize the frontend structure */
978 FrontEnd->Vtbl = &TuiVtbl;
979 FrontEnd->Context = NULL;
980 FrontEnd->Context2 = NULL;
981
982 return STATUS_SUCCESS;
983 }
984
985 NTSTATUS NTAPI
986 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
987 {
988 if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
989 if (FrontEnd->Context) TuiDeinitFrontEnd(FrontEnd);
990
991 return STATUS_SUCCESS;
992 }
993
994 #endif
995
996 /* EOF */