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
9 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
12 #ifdef TUITERM_COMPILE
16 // #include "include/conio.h"
17 #include "include/console.h"
18 #include "include/settings.h"
21 #include <ndk/iofuncs.h>
22 #include <ndk/setypes.h>
23 #include <drivers/blue/ntddblue.h>
29 /* GLOBALS ********************************************************************/
31 #define ConsoleOutputUnicodeToAnsiChar(Console, dChar, sWChar) \
33 ASSERT((ULONG_PTR)(dChar) != (ULONG_PTR)(sWChar)); \
34 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL); \
37 /* TUI Console Window Class name */
38 #define TUI_CONSOLE_WINDOW_CLASS L"TuiConsoleWindowClass"
40 typedef struct _TUI_CONSOLE_DATA
42 CRITICAL_SECTION Lock
;
43 LIST_ENTRY Entry
; /* Entry in the list of virtual consoles */
44 // HANDLE hTuiInitEvent;
45 // HANDLE hTuiTermEvent;
47 HWND hWindow
; /* Handle to the console's window (used for the window's procedure) */
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
;
54 #define GetNextConsole(Console) \
55 CONTAINING_RECORD(Console->Entry.Flink, TUI_CONSOLE_DATA, Entry)
57 #define GetPrevConsole(Console) \
58 CONTAINING_RECORD(Console->Entry.Blink, TUI_CONSOLE_DATA, Entry)
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
;
66 static COORD PhysicalConsoleSize
;
67 static HANDLE ConsoleDeviceHandle
;
69 static BOOL ConsInitialized
= FALSE
;
71 /******************************************************************************\
72 |** BlueScreen Driver management **|
74 /* Code taken and adapted from base/system/services/driver.c */
76 ScmLoadDriver(LPCWSTR lpServiceName
)
78 NTSTATUS Status
= STATUS_SUCCESS
;
79 BOOLEAN WasPrivilegeEnabled
= FALSE
;
81 UNICODE_STRING DriverPath
;
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
;
91 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
95 RtlInitUnicodeString(&DriverPath
,
98 DPRINT(" Path: %wZ\n", &DriverPath
);
100 /* Acquire driver-loading privilege */
101 Status
= RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE
,
104 &WasPrivilegeEnabled
);
105 if (!NT_SUCCESS(Status
))
107 /* We encountered a failure, exit properly */
108 DPRINT1("CONSRV: Cannot acquire driver-loading privilege, Status = 0x%08lx\n", Status
);
112 Status
= NtLoadDriver(&DriverPath
);
114 /* Release driver-loading privilege */
115 RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE
,
118 &WasPrivilegeEnabled
);
121 ConsoleFreeHeap(pszDriverPath
);
122 return RtlNtStatusToDosError(Status
);
125 #ifdef BLUESCREEN_DRIVER_UNLOADING
127 ScmUnloadDriver(LPCWSTR lpServiceName
)
129 NTSTATUS Status
= STATUS_SUCCESS
;
130 BOOLEAN WasPrivilegeEnabled
= FALSE
;
132 UNICODE_STRING DriverPath
;
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
;
141 wcscpy(pszDriverPath
,
142 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
143 wcscat(pszDriverPath
,
146 RtlInitUnicodeString(&DriverPath
,
149 DPRINT(" Path: %wZ\n", &DriverPath
);
151 /* Acquire driver-unloading privilege */
152 Status
= RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE
,
155 &WasPrivilegeEnabled
);
156 if (!NT_SUCCESS(Status
))
158 /* We encountered a failure, exit properly */
159 DPRINT1("CONSRV: Cannot acquire driver-unloading privilege, Status = 0x%08lx\n", Status
);
163 Status
= NtUnloadDriver(&DriverPath
);
165 /* Release driver-unloading privilege */
166 RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE
,
169 &WasPrivilegeEnabled
);
172 ConsoleFreeHeap(pszDriverPath
);
173 return RtlNtStatusToDosError(Status
);
177 \******************************************************************************/
181 TuiSwapConsole(INT Next
)
183 static PTUI_CONSOLE_DATA SwapConsole
= NULL
; /* Console we are thinking about swapping with */
192 * Alt-Tab, swap consoles.
193 * move SwapConsole to next console, and print its title.
195 EnterCriticalSection(&ActiveVirtConsLock
);
196 if (!SwapConsole
) SwapConsole
= ActiveConsole
;
198 SwapConsole
= (0 < Next
? GetNextConsole(SwapConsole
) : GetPrevConsole(SwapConsole
));
199 Title
.MaximumLength
= RtlUnicodeStringToAnsiSize(&SwapConsole
->Console
->Title
);
201 Buffer
= ConsoleAllocHeap(0, sizeof(COORD
) + Title
.MaximumLength
);
202 pos
= (PCOORD
)Buffer
;
203 Title
.Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ sizeof(COORD
));
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
))
214 DPRINT1( "Error writing to console\n" );
216 ConsoleFreeHeap(Buffer
);
217 LeaveCriticalSection(&ActiveVirtConsLock
);
221 else if (NULL
!= SwapConsole
)
223 EnterCriticalSection(&ActiveVirtConsLock
);
224 if (SwapConsole
!= ActiveConsole
)
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
;
235 ActiveConsole
= SwapConsole
;
237 ConioDrawConsole(ActiveConsole
->Console
);
238 LeaveCriticalSection(&ActiveVirtConsLock
);
249 TuiCopyRect(PCHAR Dest
, PTEXTMODE_SCREEN_BUFFER Buff
, SMALL_RECT
* Region
)
251 UINT SrcDelta
, DestDelta
;
253 PCHAR_INFO Src
, SrcEnd
;
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
++)
261 ConsoleOutputUnicodeToAnsiChar(Buff
->Header
.Console
, (PCHAR
)Dest
, &Src
->Char
.UnicodeChar
);
262 *(PBYTE
)(Dest
+ 1) = (BYTE
)Src
->Attributes
;
267 Src
-= Buff
->ScreenBufferSize
.Y
* Buff
->ScreenBufferSize
.X
* sizeof(CHAR_INFO
);
273 static LRESULT CALLBACK
274 TuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
277 PTUI_CONSOLE_DATA TuiData = NULL;
278 PCONSRV_CONSOLE Console = NULL;
280 TuiData = TuiGetGuiData(hWnd);
281 if (TuiData == NULL) return 0;
294 if ((HIWORD(lParam
) & KF_ALTDOWN
) && wParam
== VK_TAB
)
296 // if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT)
297 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
301 else if (wParam
== VK_MENU
/* && !Down */)
308 if (ConDrvValidateConsoleUnsafe((PCONSOLE
)ActiveConsole
->Console
, CONSOLE_RUNNING
, TRUE
))
312 Message
.message
= msg
;
313 Message
.wParam
= wParam
;
314 Message
.lParam
= lParam
;
316 ConioProcessKey(ActiveConsole
->Console
, &Message
);
317 LeaveCriticalSection(&ActiveConsole
->Console
->Lock
);
324 if (ConDrvValidateConsoleUnsafe((PCONSOLE
)ActiveConsole
->Console
, CONSOLE_RUNNING
, TRUE
))
326 if (LOWORD(wParam
) != WA_INACTIVE
)
329 ConioDrawConsole(ActiveConsole
->Console
);
331 LeaveCriticalSection(&ActiveConsole
->Console
->Lock
);
340 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
344 TuiConsoleThread(PVOID Param
)
346 PTUI_CONSOLE_DATA TuiData
= (PTUI_CONSOLE_DATA
)Param
;
347 PCONSRV_CONSOLE Console
= TuiData
->Console
;
351 NewWindow
= CreateWindowW(TUI_CONSOLE_WINDOW_CLASS
,
352 Console
->Title
.Buffer
,
354 -32000, -32000, 0, 0,
358 if (NULL
== NewWindow
)
360 DPRINT1("CONSRV: Unable to create console window\n");
363 TuiData
->hWindow
= NewWindow
;
365 SetForegroundWindow(TuiData
->hWindow
);
366 NtUserConsoleControl(ConsoleAcquireDisplayOwnership
, NULL
, 0);
368 while (GetMessageW(&msg
, NULL
, 0, 0))
370 TranslateMessage(&msg
);
371 DispatchMessageW(&msg
);
381 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
384 ATOM ConsoleClassAtom
;
385 USHORT TextAttribute
= FOREGROUND_BLUE
| FOREGROUND_GREEN
| FOREGROUND_RED
;
387 /* Exit if we were already initialized */
388 if (ConsInitialized
) return TRUE
;
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.
397 ScmLoadDriver(L
"Blue");
399 ConsoleDeviceHandle
= CreateFileW(L
"\\\\.\\BlueScreen",
404 if (ConsoleDeviceHandle
== INVALID_HANDLE_VALUE
)
406 DPRINT1("Failed to open BlueScreen.\n");
411 if (!DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_RESET_SCREEN
,
412 &Success
, sizeof(Success
), NULL
, 0,
413 &BytesReturned
, NULL
))
415 DPRINT1("Failed to enable the screen.\n");
416 CloseHandle(ConsoleDeviceHandle
);
420 if (!DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_LOADFONT
,
421 &OemCP
, sizeof(OemCP
), NULL
, 0,
422 &BytesReturned
, NULL
))
424 DPRINT1("Failed to load the font for codepage %d\n", OemCP
);
425 /* Let's suppose the font is good enough to continue */
428 if (!DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
,
429 &TextAttribute
, sizeof(TextAttribute
), NULL
, 0,
430 &BytesReturned
, NULL
))
432 DPRINT1("Failed to set text attribute.\n");
435 ActiveConsole
= NULL
;
436 InitializeListHead(&VirtConsList
);
437 InitializeCriticalSection(&ActiveVirtConsLock
);
439 if (!DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
,
440 NULL
, 0, &ScrInfo
, sizeof(ScrInfo
), &BytesReturned
, NULL
))
442 DPRINT1("Failed to get console info.\n");
446 PhysicalConsoleSize
= ScrInfo
.dwSize
;
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
;
454 wc
.hInstance
= ConSrvDllInstance
;
456 ConsoleClassAtom
= RegisterClassExW(&wc
);
457 if (ConsoleClassAtom
== 0)
459 DPRINT1("Failed to register TUI console wndproc.\n");
470 DeleteCriticalSection(&ActiveVirtConsLock
);
471 CloseHandle(ConsoleDeviceHandle
);
474 ConsInitialized
= Success
;
480 /******************************************************************************
481 * TUI Console Driver *
482 ******************************************************************************/
485 TuiDeinitFrontEnd(IN OUT PFRONTEND This
/*,
486 IN PCONSRV_CONSOLE Console */);
488 static NTSTATUS NTAPI
489 TuiInitFrontEnd(IN OUT PFRONTEND This
,
490 IN PCONSRV_CONSOLE Console
)
492 PTUI_CONSOLE_DATA TuiData
;
495 if (This
== NULL
|| Console
== NULL
)
496 return STATUS_INVALID_PARAMETER
;
498 if (GetType(Console
->ActiveBuffer
) != TEXTMODE_BUFFER
)
499 return STATUS_INVALID_PARAMETER
;
501 TuiData
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, sizeof(TUI_CONSOLE_DATA
));
504 DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
505 return STATUS_UNSUCCESSFUL
;
507 // Console->FrontEndIFace.Context = (PVOID)TuiData;
508 TuiData
->Console
= Console
;
509 TuiData
->ActiveBuffer
= Console
->ActiveBuffer
;
510 TuiData
->hWindow
= NULL
;
512 InitializeCriticalSection(&TuiData
->Lock
);
515 * HACK: Resize the console since we don't support for now changing
516 * the console size when we display it with the hardware.
518 // Console->ConsoleSize = PhysicalConsoleSize;
519 // ConioResizeBuffer(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), PhysicalConsoleSize);
521 // /* The console cannot be resized anymore */
522 // Console->FixedSize = TRUE; // MUST be placed AFTER the call to ConioResizeBuffer !!
523 // // TermResizeTerminal(Console);
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).
531 ThreadHandle
= CreateThread(NULL
,
537 if (NULL
== ThreadHandle
)
539 DPRINT1("CONSRV: Unable to create console thread\n");
540 // TuiDeinitFrontEnd(Console);
541 TuiDeinitFrontEnd(This
);
542 return STATUS_UNSUCCESSFUL
;
544 CloseHandle(ThreadHandle
);
547 * Insert the newly created console in the list of virtual consoles
548 * and activate it (give it the focus).
550 EnterCriticalSection(&ActiveVirtConsLock
);
551 InsertTailList(&VirtConsList
, &TuiData
->Entry
);
552 ActiveConsole
= TuiData
;
553 LeaveCriticalSection(&ActiveVirtConsLock
);
555 /* Finally, initialize the frontend structure */
556 This
->Context
= TuiData
;
557 This
->Context2
= NULL
;
559 return STATUS_SUCCESS
;
563 TuiDeinitFrontEnd(IN OUT PFRONTEND This
)
565 // PCONSRV_CONSOLE Console = This->Console;
566 PTUI_CONSOLE_DATA TuiData
= This
->Context
;
568 /* Close the notification window */
569 DestroyWindow(TuiData
->hWindow
);
572 * Set the active console to the next one
573 * and remove the console from the list.
575 EnterCriticalSection(&ActiveVirtConsLock
);
576 ActiveConsole
= GetNextConsole(TuiData
);
577 RemoveEntryList(&TuiData
->Entry
);
579 // /* Switch to next console */
580 // if (ActiveConsole == TuiData)
581 // if (ActiveConsole->Console == Console)
583 // ActiveConsole = (TuiData->Entry.Flink != TuiData->Entry ? GetNextConsole(TuiData) : NULL);
586 // if (GetNextConsole(TuiData) != TuiData)
588 // TuiData->Entry.Blink->Flink = TuiData->Entry.Flink;
589 // TuiData->Entry.Flink->Blink = TuiData->Entry.Blink;
592 LeaveCriticalSection(&ActiveVirtConsLock
);
594 /* Switch to the next console */
595 if (NULL
!= ActiveConsole
) ConioDrawConsole(ActiveConsole
->Console
);
597 This
->Context
= NULL
;
598 DeleteCriticalSection(&TuiData
->Lock
);
599 ConsoleFreeHeap(TuiData
);
603 TuiDrawRegion(IN OUT PFRONTEND This
,
606 PTUI_CONSOLE_DATA TuiData
= This
->Context
;
607 PCONSOLE_SCREEN_BUFFER Buff
= TuiData
->Console
->ActiveBuffer
;
608 PCONSOLE_DRAW ConsoleDraw
;
610 UINT ConsoleDrawSize
;
612 if (TuiData
!= ActiveConsole
) return;
613 if (GetType(Buff
) != TEXTMODE_BUFFER
) return;
615 ConsoleDrawSize
= sizeof(CONSOLE_DRAW
) +
616 (ConioRectWidth(Region
) * ConioRectHeight(Region
)) * 2;
617 ConsoleDraw
= ConsoleAllocHeap(0, ConsoleDrawSize
);
618 if (NULL
== ConsoleDraw
)
620 DPRINT1("ConsoleAllocHeap failed\n");
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
;
630 TuiCopyRect((PCHAR
)(ConsoleDraw
+ 1), (PTEXTMODE_SCREEN_BUFFER
)Buff
, Region
);
632 if (!DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_DRAW
,
633 NULL
, 0, ConsoleDraw
, ConsoleDrawSize
, &BytesReturned
, NULL
))
635 DPRINT1("Failed to draw console\n");
636 ConsoleFreeHeap(ConsoleDraw
);
640 ConsoleFreeHeap(ConsoleDraw
);
644 TuiWriteStream(IN OUT PFRONTEND This
,
652 PTUI_CONSOLE_DATA TuiData
= This
->Context
;
653 PCONSOLE_SCREEN_BUFFER Buff
= TuiData
->Console
->ActiveBuffer
;
658 if (TuiData
!= ActiveConsole
) return;
659 if (GetType(Buff
) != TEXTMODE_BUFFER
) return;
661 NewLength
= WideCharToMultiByte(TuiData
->Console
->OutputCodePage
, 0,
663 NULL
, 0, NULL
, NULL
);
664 NewBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, NewLength
* sizeof(CHAR
));
665 if (!NewBuffer
) return;
667 WideCharToMultiByte(TuiData
->Console
->OutputCodePage
, 0,
669 NewBuffer
, NewLength
, NULL
, NULL
);
671 if (!WriteFile(ConsoleDeviceHandle
, NewBuffer
, NewLength
* sizeof(CHAR
), &BytesWritten
, NULL
))
673 DPRINT1("Error writing to BlueScreen\n");
676 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer
);
680 TuiRingBell(IN OUT PFRONTEND This
)
686 TuiSetCursorInfo(IN OUT PFRONTEND This
,
687 PCONSOLE_SCREEN_BUFFER Buff
)
689 PTUI_CONSOLE_DATA TuiData
= This
->Context
;
690 CONSOLE_CURSOR_INFO Info
;
693 if (TuiData
!= ActiveConsole
) return TRUE
;
694 if (TuiData
->Console
->ActiveBuffer
!= Buff
) return TRUE
;
695 if (GetType(Buff
) != TEXTMODE_BUFFER
) return FALSE
;
697 Info
.dwSize
= ConioEffectiveCursorSize(TuiData
->Console
, 100);
698 Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
700 if (!DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_SET_CURSOR_INFO
,
701 &Info
, sizeof(Info
), NULL
, 0, &BytesReturned
, NULL
))
703 DPRINT1( "Failed to set cursor info\n" );
711 TuiSetScreenInfo(IN OUT PFRONTEND This
,
712 PCONSOLE_SCREEN_BUFFER Buff
,
716 PTUI_CONSOLE_DATA TuiData
= This
->Context
;
717 CONSOLE_SCREEN_BUFFER_INFO Info
;
720 if (TuiData
!= ActiveConsole
) return TRUE
;
721 if (TuiData
->Console
->ActiveBuffer
!= Buff
) return TRUE
;
722 if (GetType(Buff
) != TEXTMODE_BUFFER
) return FALSE
;
724 Info
.dwCursorPosition
= Buff
->CursorPosition
;
725 Info
.wAttributes
= ((PTEXTMODE_SCREEN_BUFFER
)Buff
)->ScreenDefaultAttrib
;
727 if (!DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
,
728 &Info
, sizeof(CONSOLE_SCREEN_BUFFER_INFO
), NULL
, 0,
729 &BytesReturned
, NULL
))
731 DPRINT1( "Failed to set cursor position\n" );
739 TuiResizeTerminal(IN OUT PFRONTEND This
)
744 TuiSetActiveScreenBuffer(IN OUT PFRONTEND This
)
746 // PGUI_CONSOLE_DATA GuiData = This->Context;
747 // PCONSOLE_SCREEN_BUFFER ActiveBuffer;
748 // HPALETTE hPalette;
750 // EnterCriticalSection(&GuiData->Lock);
751 // GuiData->WindowSizeLock = TRUE;
753 // InterlockedExchangePointer(&GuiData->ActiveBuffer,
754 // ConDrvGetActiveScreenBuffer(GuiData->Console));
756 // GuiData->WindowSizeLock = FALSE;
757 // LeaveCriticalSection(&GuiData->Lock);
759 // ActiveBuffer = GuiData->ActiveBuffer;
761 // /* Change the current palette */
762 // if (ActiveBuffer->PaletteHandle == NULL)
764 // hPalette = GuiData->hSysPalette;
768 // hPalette = ActiveBuffer->PaletteHandle;
771 // DPRINT("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette);
773 // /* Set the new palette for the framebuffer */
774 // SelectPalette(GuiData->hMemDC, hPalette, FALSE);
776 // /* Specify the use of the system palette for the framebuffer */
777 // SetSystemPaletteUse(GuiData->hMemDC, ActiveBuffer->PaletteUsage);
779 // /* Realize the (logical) palette */
780 // RealizePalette(GuiData->hMemDC);
782 // GuiResizeTerminal(This);
783 // // ConioDrawConsole(Console);
787 TuiReleaseScreenBuffer(IN OUT PFRONTEND This
,
788 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
790 // PGUI_CONSOLE_DATA GuiData = This->Context;
793 // * If we were notified to release a screen buffer that is not actually
794 // * ours, then just ignore the notification...
796 // if (ScreenBuffer != GuiData->ActiveBuffer) return;
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
806 // /* Release the old active palette and set the default one */
807 // if (GetCurrentObject(GuiData->hMemDC, OBJ_PAL) == ScreenBuffer->PaletteHandle)
809 // /* Set the new palette */
810 // SelectPalette(GuiData->hMemDC, GuiData->hSysPalette, FALSE);
813 // /* Set the adequate active screen buffer */
814 // if (ScreenBuffer != GuiData->Console->ActiveBuffer)
816 // GuiSetActiveScreenBuffer(This);
820 // EnterCriticalSection(&GuiData->Lock);
821 // GuiData->WindowSizeLock = TRUE;
823 // InterlockedExchangePointer(&GuiData->ActiveBuffer, NULL);
825 // GuiData->WindowSizeLock = FALSE;
826 // LeaveCriticalSection(&GuiData->Lock);
831 TuiRefreshInternalInfo(IN OUT PFRONTEND This
)
836 TuiChangeTitle(IN OUT PFRONTEND This
)
841 TuiChangeIcon(IN OUT PFRONTEND This
,
848 TuiGetThreadConsoleDesktop(IN OUT PFRONTEND This
)
850 // PTUI_CONSOLE_DATA TuiData = This->Context;
855 TuiGetConsoleWindowHandle(IN OUT PFRONTEND This
)
857 PTUI_CONSOLE_DATA TuiData
= This
->Context
;
858 return TuiData
->hWindow
;
862 TuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This
,
866 *pSize
= PhysicalConsoleSize
;
870 TuiGetSelectionInfo(IN OUT PFRONTEND This
,
871 PCONSOLE_SELECTION_INFO pSelectionInfo
)
877 TuiSetPalette(IN OUT PFRONTEND This
,
878 HPALETTE PaletteHandle
,
885 TuiGetDisplayMode(IN OUT PFRONTEND This
)
887 return CONSOLE_FULLSCREEN_HARDWARE
; // CONSOLE_FULLSCREEN;
891 TuiSetDisplayMode(IN OUT PFRONTEND This
,
894 // if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
900 TuiShowMouseCursor(IN OUT PFRONTEND This
,
907 TuiSetMouseCursor(IN OUT PFRONTEND This
,
908 HCURSOR CursorHandle
)
914 TuiMenuControl(IN OUT PFRONTEND This
,
922 TuiSetMenuClose(IN OUT PFRONTEND This
,
928 static FRONTEND_VTBL TuiVtbl
=
938 TuiSetActiveScreenBuffer
,
939 TuiReleaseScreenBuffer
,
940 TuiRefreshInternalInfo
,
943 TuiGetThreadConsoleDesktop
,
944 TuiGetConsoleWindowHandle
,
945 TuiGetLargestConsoleWindowSize
,
959 return (BOOLEAN
)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE
);
963 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
964 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
965 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
966 IN HANDLE ConsoleLeaderProcessHandle
)
968 if (FrontEnd
== NULL
|| ConsoleInfo
== NULL
)
969 return STATUS_INVALID_PARAMETER
;
971 /* We must be in console mode already */
972 if (!IsConsoleMode()) return STATUS_UNSUCCESSFUL
;
974 /* Initialize the TUI terminal emulator */
975 if (!TuiInit(ConsoleInfo
->CodePage
)) return STATUS_UNSUCCESSFUL
;
977 /* Finally, initialize the frontend structure */
978 FrontEnd
->Vtbl
= &TuiVtbl
;
979 FrontEnd
->Context
= NULL
;
980 FrontEnd
->Context2
= NULL
;
982 return STATUS_SUCCESS
;
986 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
)
988 if (FrontEnd
== NULL
) return STATUS_INVALID_PARAMETER
;
989 if (FrontEnd
->Context
) TuiDeinitFrontEnd(FrontEnd
);
991 return STATUS_SUCCESS
;