2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: frontends/terminal.c
5 * PURPOSE: ConSrv terminal.
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
13 // #include "frontends/gui/guiterm.h"
14 #ifdef TUITERM_COMPILE
15 #include "frontends/tui/tuiterm.h"
25 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
27 /* GLOBALS ********************************************************************/
31 * "The lpMultiByteStr and lpWideCharStr pointers must not be the same.
32 * If they are the same, the function fails, and GetLastError returns
33 * ERROR_INVALID_PARAMETER."
35 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
36 ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \
37 WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
39 #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
40 ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \
41 MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1)
43 typedef struct ConsoleInput_t
46 INPUT_RECORD InputEvent
;
50 /* PRIVATE FUNCTIONS **********************************************************/
55 ConioInputEventToAnsi(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
57 if (InputEvent
->EventType
== KEY_EVENT
)
59 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
60 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
61 ConsoleInputUnicodeCharToAnsiChar(Console
,
62 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
68 ConioInputEventToUnicode(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
70 if (InputEvent
->EventType
== KEY_EVENT
)
72 CHAR AsciiChar
= InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
;
73 InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
= 0;
74 ConsoleInputAnsiCharToUnicodeChar(Console
,
75 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
,
82 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
91 /* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/
94 #ifdef TUITERM_COMPILE
96 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
97 IN OUT PCONSOLE_INFO ConsoleInfo
,
98 IN OUT PVOID ExtraConsoleInfo
,
101 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
);
105 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
106 IN OUT PCONSOLE_INFO ConsoleInfo
,
107 IN OUT PVOID ExtraConsoleInfo
,
110 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd
);
114 NTSTATUS (NTAPI
*FRONTEND_LOAD
)(IN OUT PFRONTEND FrontEnd
,
115 IN OUT PCONSOLE_INFO ConsoleInfo
,
116 IN OUT PVOID ExtraConsoleInfo
,
120 NTSTATUS (NTAPI
*FRONTEND_UNLOAD
)(IN OUT PFRONTEND FrontEnd
);
123 * If we are not in GUI-mode, start the text-mode terminal emulator.
124 * If we fail, try to start the GUI-mode terminal emulator.
126 * Try to open the GUI-mode terminal emulator. Two cases are possible:
127 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
128 * failed and we start GUI-mode terminal emulator.
129 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
130 * succeeded BUT we failed at starting text-mode terminal emulator.
131 * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
132 * terminal emulator (Win32k will automatically switch to graphical mode,
133 * therefore no additional code is needed).
137 * NOTE: Each entry of the table should be retrieved when loading a front-end
138 * (examples of the CSR servers which register some data for CSRSS).
142 CHAR FrontEndName
[80];
143 FRONTEND_LOAD FrontEndLoad
;
144 FRONTEND_UNLOAD FrontEndUnload
;
145 } FrontEndLoadingMethods
[] =
147 #ifdef TUITERM_COMPILE
148 {"TUI", TuiLoadFrontEnd
, TuiUnloadFrontEnd
},
150 {"GUI", GuiLoadFrontEnd
, GuiUnloadFrontEnd
},
152 // {"Not found", 0, NULL}
156 ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd
,
157 IN OUT PCONSOLE_INFO ConsoleInfo
,
158 IN OUT PVOID ExtraConsoleInfo
,
161 NTSTATUS Status
= STATUS_SUCCESS
;
165 * Choose an adequate terminal front-end to load, and load it
167 for (i
= 0; i
< sizeof(FrontEndLoadingMethods
) / sizeof(FrontEndLoadingMethods
[0]); ++i
)
169 DPRINT("CONSRV: Trying to load %s frontend...\n",
170 FrontEndLoadingMethods
[i
].FrontEndName
);
171 Status
= FrontEndLoadingMethods
[i
].FrontEndLoad(FrontEnd
,
175 if (NT_SUCCESS(Status
))
177 /* Save the unload callback */
178 FrontEnd
->UnloadFrontEnd
= FrontEndLoadingMethods
[i
].FrontEndUnload
;
180 DPRINT("CONSRV: %s frontend loaded successfully\n",
181 FrontEndLoadingMethods
[i
].FrontEndName
);
186 DPRINT1("CONSRV: Loading %s frontend failed, Status = 0x%08lx , continuing...\n",
187 FrontEndLoadingMethods
[i
].FrontEndName
, Status
);
195 ConSrvUnloadFrontEnd(IN PFRONTEND FrontEnd
)
197 if (FrontEnd
== NULL
) return STATUS_INVALID_PARAMETER
;
198 // return FrontEnd->Vtbl->UnloadFrontEnd(FrontEnd);
199 return FrontEnd
->UnloadFrontEnd(FrontEnd
);
203 static TERMINAL_VTBL ConSrvTermVtbl
;
206 ConSrvInitTerminal(IN OUT PTERMINAL Terminal
,
207 IN OUT PCONSOLE_INFO ConsoleInfo
,
208 IN OUT PVOID ExtraConsoleInfo
,
214 /* Load a suitable frontend for the ConSrv terminal */
215 FrontEnd
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, sizeof(*FrontEnd
));
216 if (!FrontEnd
) return STATUS_NO_MEMORY
;
218 Status
= ConSrvLoadFrontEnd(FrontEnd
,
222 if (!NT_SUCCESS(Status
))
224 DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status
);
225 ConsoleFreeHeap(FrontEnd
);
228 DPRINT("CONSRV: Frontend initialized\n");
230 /* Initialize the ConSrv terminal */
231 Terminal
->Vtbl
= &ConSrvTermVtbl
;
232 // Terminal->Console will be initialized by ConDrvRegisterTerminal
233 Terminal
->Data
= FrontEnd
; /* We store the frontend pointer in the terminal private data */
235 return STATUS_SUCCESS
;
239 ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal
)
241 NTSTATUS Status
= STATUS_SUCCESS
;
242 PFRONTEND FrontEnd
= Terminal
->Data
;
244 /* Reset the ConSrv terminal */
245 Terminal
->Data
= NULL
;
246 Terminal
->Vtbl
= NULL
;
248 /* Unload the frontend */
249 if (FrontEnd
!= NULL
)
251 Status
= ConSrvUnloadFrontEnd(FrontEnd
);
252 ConsoleFreeHeap(FrontEnd
);
259 /* CONSRV TERMINAL INTERFACE **************************************************/
261 static NTSTATUS NTAPI
262 ConSrvTermInitTerminal(IN OUT PTERMINAL This
,
266 PFRONTEND FrontEnd
= This
->Data
;
268 /* Initialize the console pointer for our frontend */
269 FrontEnd
->Console
= Console
;
271 /** HACK HACK!! Copy FrontEnd into the console!! **/
272 DPRINT1("Using FrontEndIFace HACK(1), should be removed after proper implementation!\n");
273 Console
->FrontEndIFace
= *FrontEnd
;
275 Status
= FrontEnd
->Vtbl
->InitFrontEnd(FrontEnd
, FrontEnd
->Console
);
276 if (!NT_SUCCESS(Status
))
277 DPRINT1("InitFrontEnd failed, Status = 0x%08lx\n", Status
);
279 /** HACK HACK!! Be sure FrontEndIFace is correctly updated in the console!! **/
280 DPRINT1("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n");
281 Console
->FrontEndIFace
= *FrontEnd
;
287 ConSrvTermDeinitTerminal(IN OUT PTERMINAL This
)
289 PFRONTEND FrontEnd
= This
->Data
;
290 FrontEnd
->Vtbl
->DeinitFrontEnd(FrontEnd
);
295 /************ Line discipline ***************/
297 static NTSTATUS NTAPI
298 ConSrvTermReadStream(IN OUT PTERMINAL This
,
299 /**/IN PUNICODE_STRING ExeName
/**/OPTIONAL
/**/,/**/
303 IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl
,
304 IN ULONG NumCharsToRead
,
305 OUT PULONG NumCharsRead OPTIONAL
)
307 PFRONTEND FrontEnd
= This
->Data
;
308 PCONSRV_CONSOLE Console
= FrontEnd
->Console
;
309 PCONSOLE_INPUT_BUFFER InputBuffer
= &Console
->InputBuffer
;
311 // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait.
312 NTSTATUS Status
= STATUS_PENDING
;
314 PLIST_ENTRY CurrentEntry
;
318 /* Validity checks */
319 // ASSERT(Console == InputBuffer->Header.Console);
320 ASSERT((Buffer
!= NULL
) || (Buffer
== NULL
&& NumCharsToRead
== 0));
322 /* We haven't read anything (yet) */
323 i
= ReadControl
->nInitialChars
;
325 if (InputBuffer
->Mode
& ENABLE_LINE_INPUT
)
327 /* COOKED mode, call the line discipline */
329 if (Console
->LineBuffer
== NULL
)
331 /* Starting a new line */
332 Console
->LineMaxSize
= max(256, NumCharsToRead
);
334 Console
->LineBuffer
= ConsoleAllocHeap(0, Console
->LineMaxSize
* sizeof(WCHAR
));
335 if (Console
->LineBuffer
== NULL
) return STATUS_NO_MEMORY
;
337 Console
->LinePos
= Console
->LineSize
= ReadControl
->nInitialChars
;
338 Console
->LineComplete
= Console
->LineUpPressed
= FALSE
;
339 Console
->LineInsertToggle
= Console
->InsertMode
;
340 Console
->LineWakeupMask
= ReadControl
->dwCtrlWakeupMask
;
343 * Pre-filling the buffer is only allowed in the Unicode API,
344 * so we don't need to worry about ANSI <-> Unicode conversion.
346 memcpy(Console
->LineBuffer
, Buffer
, Console
->LineSize
* sizeof(WCHAR
));
347 if (Console
->LineSize
== Console
->LineMaxSize
)
349 Console
->LineComplete
= TRUE
;
350 Console
->LinePos
= 0;
354 /* If we don't have a complete line yet, process the pending input */
355 while (!Console
->LineComplete
&& !IsListEmpty(&InputBuffer
->InputEvents
))
357 /* Remove input event from queue */
358 CurrentEntry
= RemoveHeadList(&InputBuffer
->InputEvents
);
359 if (IsListEmpty(&InputBuffer
->InputEvents
))
361 ResetEvent(InputBuffer
->ActiveEvent
);
363 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
365 /* Only pay attention to key down */
366 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
367 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
369 LineInputKeyDown(Console
, ExeName
,
370 &Input
->InputEvent
.Event
.KeyEvent
);
371 ReadControl
->dwControlKeyState
= Input
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
;
373 ConsoleFreeHeap(Input
);
376 /* Check if we have a complete line to read from */
377 if (Console
->LineComplete
)
379 while (i
< NumCharsToRead
&& Console
->LinePos
!= Console
->LineSize
)
381 WCHAR Char
= Console
->LineBuffer
[Console
->LinePos
++];
385 ((PWCHAR
)Buffer
)[i
] = Char
;
389 ConsoleInputUnicodeCharToAnsiChar(Console
, &((PCHAR
)Buffer
)[i
], &Char
);
394 if (Console
->LinePos
== Console
->LineSize
)
396 /* Entire line has been read */
397 ConsoleFreeHeap(Console
->LineBuffer
);
398 Console
->LineBuffer
= NULL
;
401 Status
= STATUS_SUCCESS
;
408 /* Character input */
409 while (i
< NumCharsToRead
&& !IsListEmpty(&InputBuffer
->InputEvents
))
411 /* Remove input event from queue */
412 CurrentEntry
= RemoveHeadList(&InputBuffer
->InputEvents
);
413 if (IsListEmpty(&InputBuffer
->InputEvents
))
415 ResetEvent(InputBuffer
->ActiveEvent
);
417 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
419 /* Only pay attention to valid characters, on key down */
420 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
421 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
422 Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
!= L
'\0')
424 WCHAR Char
= Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
;
428 ((PWCHAR
)Buffer
)[i
] = Char
;
432 ConsoleInputUnicodeCharToAnsiChar(Console
, &((PCHAR
)Buffer
)[i
], &Char
);
436 /* Did read something */
437 Status
= STATUS_SUCCESS
;
439 ConsoleFreeHeap(Input
);
443 // FIXME: Only set if Status == STATUS_SUCCESS ???
444 if (NumCharsRead
) *NumCharsRead
= i
;
452 /* GLOBALS ********************************************************************/
458 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff
);
461 ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff
, PSMALL_RECT UpdateRect
, PUINT ScrolledLines
)
463 /* If we hit bottom, slide the viewable screen */
464 if (++Buff
->CursorPosition
.Y
== Buff
->ScreenBufferSize
.Y
)
466 Buff
->CursorPosition
.Y
--;
467 if (++Buff
->VirtualY
== Buff
->ScreenBufferSize
.Y
)
472 ClearLineBuffer(Buff
);
473 if (UpdateRect
->Top
!= 0)
478 UpdateRect
->Left
= 0;
479 UpdateRect
->Right
= Buff
->ScreenBufferSize
.X
- 1;
480 UpdateRect
->Bottom
= Buff
->CursorPosition
.Y
;
484 ConioWriteConsole(PFRONTEND FrontEnd
,
485 PTEXTMODE_SCREEN_BUFFER Buff
,
490 PCONSRV_CONSOLE Console
= FrontEnd
->Console
;
494 SMALL_RECT UpdateRect
;
495 SHORT CursorStartX
, CursorStartY
;
498 CursorStartX
= Buff
->CursorPosition
.X
;
499 CursorStartY
= Buff
->CursorPosition
.Y
;
500 UpdateRect
.Left
= Buff
->ScreenBufferSize
.X
;
501 UpdateRect
.Top
= Buff
->CursorPosition
.Y
;
502 UpdateRect
.Right
= -1;
503 UpdateRect
.Bottom
= Buff
->CursorPosition
.Y
;
506 for (i
= 0; i
< Length
; i
++)
509 * If we are in processed mode, interpret special characters and
510 * display them correctly. Otherwise, just put them into the buffer.
512 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
515 if (Buffer
[i
] == L
'\r')
517 Buff
->CursorPosition
.X
= 0;
518 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
519 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
523 else if (Buffer
[i
] == L
'\n')
525 Buff
->CursorPosition
.X
= 0;
526 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
530 else if (Buffer
[i
] == L
'\b')
532 /* Only handle BS if we're not on the first pos of the first line */
533 if (0 != Buff
->CursorPosition
.X
|| 0 != Buff
->CursorPosition
.Y
)
535 if (0 == Buff
->CursorPosition
.X
)
537 /* slide virtual position up */
538 Buff
->CursorPosition
.X
= Buff
->ScreenBufferSize
.X
- 1;
539 Buff
->CursorPosition
.Y
--;
540 UpdateRect
.Top
= min(UpdateRect
.Top
, Buff
->CursorPosition
.Y
);
544 Buff
->CursorPosition
.X
--;
546 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
547 Ptr
->Char
.UnicodeChar
= L
' ';
548 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
549 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
550 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
555 else if (Buffer
[i
] == L
'\t')
559 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
560 EndX
= (Buff
->CursorPosition
.X
+ TAB_WIDTH
) & ~(TAB_WIDTH
- 1);
561 EndX
= min(EndX
, (UINT
)Buff
->ScreenBufferSize
.X
);
562 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
563 while (Buff
->CursorPosition
.X
< EndX
)
565 Ptr
->Char
.UnicodeChar
= L
' ';
566 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
568 Buff
->CursorPosition
.X
++;
570 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
- 1);
571 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
573 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
575 Buff
->CursorPosition
.X
= 0;
576 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
580 Buff
->CursorPosition
.X
--;
586 else if (Buffer
[i
] == L
'\a')
588 FrontEnd
->Vtbl
->RingBell(FrontEnd
);
592 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
593 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
595 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
596 Ptr
->Char
.UnicodeChar
= Buffer
[i
];
597 if (Attrib
) Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
599 Buff
->CursorPosition
.X
++;
600 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
602 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
604 Buff
->CursorPosition
.X
= 0;
605 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
609 Buff
->CursorPosition
.X
= CursorStartX
;
614 if (!ConioIsRectEmpty(&UpdateRect
) && (PCONSOLE_SCREEN_BUFFER
)Buff
== Console
->ActiveBuffer
)
616 // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
617 // ScrolledLines, Buffer, Length);
618 FrontEnd
->Vtbl
->WriteStream(FrontEnd
,
627 return STATUS_SUCCESS
;
632 static NTSTATUS NTAPI
633 ConSrvTermWriteStream(IN OUT PTERMINAL This
,
634 PTEXTMODE_SCREEN_BUFFER Buff
,
639 PFRONTEND FrontEnd
= This
->Data
;
640 return ConioWriteConsole(FrontEnd
,
647 /************ Line discipline ***************/
652 ConSrvTermDrawRegion(IN OUT PTERMINAL This
,
655 PFRONTEND FrontEnd
= This
->Data
;
656 FrontEnd
->Vtbl
->DrawRegion(FrontEnd
, Region
);
660 ConSrvTermSetCursorInfo(IN OUT PTERMINAL This
,
661 PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
663 PFRONTEND FrontEnd
= This
->Data
;
664 return FrontEnd
->Vtbl
->SetCursorInfo(FrontEnd
, ScreenBuffer
);
668 ConSrvTermSetScreenInfo(IN OUT PTERMINAL This
,
669 PCONSOLE_SCREEN_BUFFER ScreenBuffer
,
673 PFRONTEND FrontEnd
= This
->Data
;
674 return FrontEnd
->Vtbl
->SetScreenInfo(FrontEnd
,
681 ConSrvTermResizeTerminal(IN OUT PTERMINAL This
)
683 PFRONTEND FrontEnd
= This
->Data
;
684 FrontEnd
->Vtbl
->ResizeTerminal(FrontEnd
);
688 ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This
)
690 PFRONTEND FrontEnd
= This
->Data
;
691 FrontEnd
->Vtbl
->SetActiveScreenBuffer(FrontEnd
);
695 ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This
,
696 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer
)
698 PFRONTEND FrontEnd
= This
->Data
;
699 FrontEnd
->Vtbl
->ReleaseScreenBuffer(FrontEnd
, ScreenBuffer
);
703 ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This
,
706 PFRONTEND FrontEnd
= This
->Data
;
707 FrontEnd
->Vtbl
->GetLargestConsoleWindowSize(FrontEnd
, pSize
);
711 ConSrvTermSetPalette(IN OUT PTERMINAL This
,
712 HPALETTE PaletteHandle
,
715 PFRONTEND FrontEnd
= This
->Data
;
716 return FrontEnd
->Vtbl
->SetPalette(FrontEnd
, PaletteHandle
, PaletteUsage
);
720 ConSrvTermShowMouseCursor(IN OUT PTERMINAL This
,
723 PFRONTEND FrontEnd
= This
->Data
;
724 return FrontEnd
->Vtbl
->ShowMouseCursor(FrontEnd
, Show
);
727 static TERMINAL_VTBL ConSrvTermVtbl
=
729 ConSrvTermInitTerminal
,
730 ConSrvTermDeinitTerminal
,
732 ConSrvTermReadStream
,
733 ConSrvTermWriteStream
,
735 ConSrvTermDrawRegion
,
736 ConSrvTermSetCursorInfo
,
737 ConSrvTermSetScreenInfo
,
738 ConSrvTermResizeTerminal
,
739 ConSrvTermSetActiveScreenBuffer
,
740 ConSrvTermReleaseScreenBuffer
,
741 ConSrvTermGetLargestConsoleWindowSize
,
742 ConSrvTermSetPalette
,
743 ConSrvTermShowMouseCursor
,
748 ResetFrontEnd(IN PCONSOLE Console
)
750 if (!Console
) return;
752 /* Reinitialize the frontend interface */
753 RtlZeroMemory(&Console
->FrontEndIFace
, sizeof(Console
->FrontEndIFace
));
754 Console
->FrontEndIFace
.Vtbl
= &ConSrvTermVtbl
;