Fix merge r65567.
[reactos.git] / win32ss / user / winsrv / consrv / frontends / terminal.c
1 /*
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)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <consrv.h>
12
13 // #include "frontends/gui/guiterm.h"
14 #ifdef TUITERM_COMPILE
15 #include "frontends/tui/tuiterm.h"
16 #endif
17
18 #define NDEBUG
19 #include <debug.h>
20
21
22
23
24
25 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
26
27 /* GLOBALS ********************************************************************/
28
29 /*
30 * From MSDN:
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."
34 */
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)
38
39 #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
40 ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \
41 MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1)
42
43 typedef struct ConsoleInput_t
44 {
45 LIST_ENTRY ListEntry;
46 INPUT_RECORD InputEvent;
47 } ConsoleInput;
48
49
50 /* PRIVATE FUNCTIONS **********************************************************/
51
52 #if 0
53
54 static VOID
55 ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
56 {
57 if (InputEvent->EventType == KEY_EVENT)
58 {
59 WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
60 InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
61 ConsoleInputUnicodeCharToAnsiChar(Console,
62 &InputEvent->Event.KeyEvent.uChar.AsciiChar,
63 &UnicodeChar);
64 }
65 }
66
67 static VOID
68 ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent)
69 {
70 if (InputEvent->EventType == KEY_EVENT)
71 {
72 CHAR AsciiChar = InputEvent->Event.KeyEvent.uChar.AsciiChar;
73 InputEvent->Event.KeyEvent.uChar.AsciiChar = 0;
74 ConsoleInputAnsiCharToUnicodeChar(Console,
75 &InputEvent->Event.KeyEvent.uChar.UnicodeChar,
76 &AsciiChar);
77 }
78 }
79
80 #endif
81
82 /********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/
83
84
85
86
87
88
89
90
91 /* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/
92
93 /***************/
94 #ifdef TUITERM_COMPILE
95 NTSTATUS NTAPI
96 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
97 IN OUT PCONSOLE_INFO ConsoleInfo,
98 IN OUT PVOID ExtraConsoleInfo,
99 IN ULONG ProcessId);
100 NTSTATUS NTAPI
101 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
102 #endif
103
104 NTSTATUS NTAPI
105 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
106 IN OUT PCONSOLE_INFO ConsoleInfo,
107 IN OUT PVOID ExtraConsoleInfo,
108 IN ULONG ProcessId);
109 NTSTATUS NTAPI
110 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
111 /***************/
112
113 typedef
114 NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
115 IN OUT PCONSOLE_INFO ConsoleInfo,
116 IN OUT PVOID ExtraConsoleInfo,
117 IN ULONG ProcessId);
118
119 typedef
120 NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
121
122 /*
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.
125 *
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).
134 */
135
136 /*
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).
139 */
140 static struct
141 {
142 CHAR FrontEndName[80];
143 FRONTEND_LOAD FrontEndLoad;
144 FRONTEND_UNLOAD FrontEndUnload;
145 } FrontEndLoadingMethods[] =
146 {
147 #ifdef TUITERM_COMPILE
148 {"TUI", TuiLoadFrontEnd, TuiUnloadFrontEnd},
149 #endif
150 {"GUI", GuiLoadFrontEnd, GuiUnloadFrontEnd},
151
152 // {"Not found", 0, NULL}
153 };
154
155 static NTSTATUS
156 ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
157 IN OUT PCONSOLE_INFO ConsoleInfo,
158 IN OUT PVOID ExtraConsoleInfo,
159 IN ULONG ProcessId)
160 {
161 NTSTATUS Status = STATUS_SUCCESS;
162 ULONG i;
163
164 /*
165 * Choose an adequate terminal front-end to load, and load it
166 */
167 for (i = 0; i < sizeof(FrontEndLoadingMethods) / sizeof(FrontEndLoadingMethods[0]); ++i)
168 {
169 DPRINT("CONSRV: Trying to load %s frontend...\n",
170 FrontEndLoadingMethods[i].FrontEndName);
171 Status = FrontEndLoadingMethods[i].FrontEndLoad(FrontEnd,
172 ConsoleInfo,
173 ExtraConsoleInfo,
174 ProcessId);
175 if (NT_SUCCESS(Status))
176 {
177 /* Save the unload callback */
178 FrontEnd->UnloadFrontEnd = FrontEndLoadingMethods[i].FrontEndUnload;
179
180 DPRINT("CONSRV: %s frontend loaded successfully\n",
181 FrontEndLoadingMethods[i].FrontEndName);
182 break;
183 }
184 else
185 {
186 DPRINT1("CONSRV: Loading %s frontend failed, Status = 0x%08lx , continuing...\n",
187 FrontEndLoadingMethods[i].FrontEndName, Status);
188 }
189 }
190
191 return Status;
192 }
193
194 static NTSTATUS
195 ConSrvUnloadFrontEnd(IN PFRONTEND FrontEnd)
196 {
197 if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
198 // return FrontEnd->Vtbl->UnloadFrontEnd(FrontEnd);
199 return FrontEnd->UnloadFrontEnd(FrontEnd);
200 }
201
202 // See after...
203 static TERMINAL_VTBL ConSrvTermVtbl;
204
205 NTSTATUS NTAPI
206 ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
207 IN OUT PCONSOLE_INFO ConsoleInfo,
208 IN OUT PVOID ExtraConsoleInfo,
209 IN ULONG ProcessId)
210 {
211 NTSTATUS Status;
212 PFRONTEND FrontEnd;
213
214 /* Load a suitable frontend for the ConSrv terminal */
215 FrontEnd = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*FrontEnd));
216 if (!FrontEnd) return STATUS_NO_MEMORY;
217
218 Status = ConSrvLoadFrontEnd(FrontEnd,
219 ConsoleInfo,
220 ExtraConsoleInfo,
221 ProcessId);
222 if (!NT_SUCCESS(Status))
223 {
224 DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
225 ConsoleFreeHeap(FrontEnd);
226 return Status;
227 }
228 DPRINT("CONSRV: Frontend initialized\n");
229
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 */
234
235 return STATUS_SUCCESS;
236 }
237
238 NTSTATUS NTAPI
239 ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal)
240 {
241 NTSTATUS Status = STATUS_SUCCESS;
242 PFRONTEND FrontEnd = Terminal->Data;
243
244 /* Reset the ConSrv terminal */
245 Terminal->Data = NULL;
246 Terminal->Vtbl = NULL;
247
248 /* Unload the frontend */
249 if (FrontEnd != NULL)
250 {
251 Status = ConSrvUnloadFrontEnd(FrontEnd);
252 ConsoleFreeHeap(FrontEnd);
253 }
254
255 return Status;
256 }
257
258
259 /* CONSRV TERMINAL INTERFACE **************************************************/
260
261 static NTSTATUS NTAPI
262 ConSrvTermInitTerminal(IN OUT PTERMINAL This,
263 IN PCONSOLE Console)
264 {
265 NTSTATUS Status;
266 PFRONTEND FrontEnd = This->Data;
267
268 /* Initialize the console pointer for our frontend */
269 FrontEnd->Console = Console;
270
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;
274
275 Status = FrontEnd->Vtbl->InitFrontEnd(FrontEnd, FrontEnd->Console);
276 if (!NT_SUCCESS(Status))
277 DPRINT1("InitFrontEnd failed, Status = 0x%08lx\n", Status);
278
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;
282
283 return Status;
284 }
285
286 static VOID NTAPI
287 ConSrvTermDeinitTerminal(IN OUT PTERMINAL This)
288 {
289 PFRONTEND FrontEnd = This->Data;
290 FrontEnd->Vtbl->DeinitFrontEnd(FrontEnd);
291 }
292
293
294
295 /************ Line discipline ***************/
296
297 static NTSTATUS NTAPI
298 ConSrvTermReadStream(IN OUT PTERMINAL This,
299 /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/
300 IN BOOLEAN Unicode,
301 /**PWCHAR Buffer,**/
302 OUT PVOID Buffer,
303 IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
304 IN ULONG NumCharsToRead,
305 OUT PULONG NumCharsRead OPTIONAL)
306 {
307 PFRONTEND FrontEnd = This->Data;
308 PCONSRV_CONSOLE Console = FrontEnd->Console;
309 PCONSOLE_INPUT_BUFFER InputBuffer = &Console->InputBuffer;
310
311 // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait.
312 NTSTATUS Status = STATUS_PENDING;
313
314 PLIST_ENTRY CurrentEntry;
315 ConsoleInput *Input;
316 ULONG i;
317
318 /* Validity checks */
319 // ASSERT(Console == InputBuffer->Header.Console);
320 ASSERT((Buffer != NULL) || (Buffer == NULL && NumCharsToRead == 0));
321
322 /* We haven't read anything (yet) */
323 i = ReadControl->nInitialChars;
324
325 if (InputBuffer->Mode & ENABLE_LINE_INPUT)
326 {
327 /* COOKED mode, call the line discipline */
328
329 if (Console->LineBuffer == NULL)
330 {
331 /* Starting a new line */
332 Console->LineMaxSize = max(256, NumCharsToRead);
333
334 Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR));
335 if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY;
336
337 Console->LinePos = Console->LineSize = ReadControl->nInitialChars;
338 Console->LineComplete = Console->LineUpPressed = FALSE;
339 Console->LineInsertToggle = Console->InsertMode;
340 Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask;
341
342 /*
343 * Pre-filling the buffer is only allowed in the Unicode API,
344 * so we don't need to worry about ANSI <-> Unicode conversion.
345 */
346 memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR));
347 if (Console->LineSize == Console->LineMaxSize)
348 {
349 Console->LineComplete = TRUE;
350 Console->LinePos = 0;
351 }
352 }
353
354 /* If we don't have a complete line yet, process the pending input */
355 while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents))
356 {
357 /* Remove input event from queue */
358 CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
359 if (IsListEmpty(&InputBuffer->InputEvents))
360 {
361 ResetEvent(InputBuffer->ActiveEvent);
362 }
363 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
364
365 /* Only pay attention to key down */
366 if (Input->InputEvent.EventType == KEY_EVENT &&
367 Input->InputEvent.Event.KeyEvent.bKeyDown)
368 {
369 LineInputKeyDown(Console, ExeName,
370 &Input->InputEvent.Event.KeyEvent);
371 ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
372 }
373 ConsoleFreeHeap(Input);
374 }
375
376 /* Check if we have a complete line to read from */
377 if (Console->LineComplete)
378 {
379 while (i < NumCharsToRead && Console->LinePos != Console->LineSize)
380 {
381 WCHAR Char = Console->LineBuffer[Console->LinePos++];
382
383 if (Unicode)
384 {
385 ((PWCHAR)Buffer)[i] = Char;
386 }
387 else
388 {
389 ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char);
390 }
391 ++i;
392 }
393
394 if (Console->LinePos == Console->LineSize)
395 {
396 /* Entire line has been read */
397 ConsoleFreeHeap(Console->LineBuffer);
398 Console->LineBuffer = NULL;
399 }
400
401 Status = STATUS_SUCCESS;
402 }
403 }
404 else
405 {
406 /* RAW mode */
407
408 /* Character input */
409 while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents))
410 {
411 /* Remove input event from queue */
412 CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
413 if (IsListEmpty(&InputBuffer->InputEvents))
414 {
415 ResetEvent(InputBuffer->ActiveEvent);
416 }
417 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
418
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')
423 {
424 WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar;
425
426 if (Unicode)
427 {
428 ((PWCHAR)Buffer)[i] = Char;
429 }
430 else
431 {
432 ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char);
433 }
434 ++i;
435
436 /* Did read something */
437 Status = STATUS_SUCCESS;
438 }
439 ConsoleFreeHeap(Input);
440 }
441 }
442
443 // FIXME: Only set if Status == STATUS_SUCCESS ???
444 if (NumCharsRead) *NumCharsRead = i;
445
446 return Status;
447 }
448
449
450
451
452 /* GLOBALS ********************************************************************/
453
454 #define TAB_WIDTH 8
455
456 // See condrv/text.c
457 /*static*/ VOID
458 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff);
459
460 static VOID
461 ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT ScrolledLines)
462 {
463 /* If we hit bottom, slide the viewable screen */
464 if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y)
465 {
466 Buff->CursorPosition.Y--;
467 if (++Buff->VirtualY == Buff->ScreenBufferSize.Y)
468 {
469 Buff->VirtualY = 0;
470 }
471 (*ScrolledLines)++;
472 ClearLineBuffer(Buff);
473 if (UpdateRect->Top != 0)
474 {
475 UpdateRect->Top--;
476 }
477 }
478 UpdateRect->Left = 0;
479 UpdateRect->Right = Buff->ScreenBufferSize.X - 1;
480 UpdateRect->Bottom = Buff->CursorPosition.Y;
481 }
482
483 static NTSTATUS
484 ConioWriteConsole(PFRONTEND FrontEnd,
485 PTEXTMODE_SCREEN_BUFFER Buff,
486 PWCHAR Buffer,
487 DWORD Length,
488 BOOL Attrib)
489 {
490 PCONSRV_CONSOLE Console = FrontEnd->Console;
491
492 UINT i;
493 PCHAR_INFO Ptr;
494 SMALL_RECT UpdateRect;
495 SHORT CursorStartX, CursorStartY;
496 UINT ScrolledLines;
497
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;
504 ScrolledLines = 0;
505
506 for (i = 0; i < Length; i++)
507 {
508 /*
509 * If we are in processed mode, interpret special characters and
510 * display them correctly. Otherwise, just put them into the buffer.
511 */
512 if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
513 {
514 /* --- CR --- */
515 if (Buffer[i] == L'\r')
516 {
517 Buff->CursorPosition.X = 0;
518 UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
519 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
520 continue;
521 }
522 /* --- LF --- */
523 else if (Buffer[i] == L'\n')
524 {
525 Buff->CursorPosition.X = 0;
526 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
527 continue;
528 }
529 /* --- BS --- */
530 else if (Buffer[i] == L'\b')
531 {
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)
534 {
535 if (0 == Buff->CursorPosition.X)
536 {
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);
541 }
542 else
543 {
544 Buff->CursorPosition.X--;
545 }
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);
551 }
552 continue;
553 }
554 /* --- TAB --- */
555 else if (Buffer[i] == L'\t')
556 {
557 UINT EndX;
558
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)
564 {
565 Ptr->Char.UnicodeChar = L' ';
566 Ptr->Attributes = Buff->ScreenDefaultAttrib;
567 ++Ptr;
568 Buff->CursorPosition.X++;
569 }
570 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1);
571 if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
572 {
573 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
574 {
575 Buff->CursorPosition.X = 0;
576 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
577 }
578 else
579 {
580 Buff->CursorPosition.X--;
581 }
582 }
583 continue;
584 }
585 /* --- BEL ---*/
586 else if (Buffer[i] == L'\a')
587 {
588 FrontEnd->Vtbl->RingBell(FrontEnd);
589 continue;
590 }
591 }
592 UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X);
593 UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X);
594
595 Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y);
596 Ptr->Char.UnicodeChar = Buffer[i];
597 if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib;
598
599 Buff->CursorPosition.X++;
600 if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X)
601 {
602 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
603 {
604 Buff->CursorPosition.X = 0;
605 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
606 }
607 else
608 {
609 Buff->CursorPosition.X = CursorStartX;
610 }
611 }
612 }
613
614 if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer)
615 {
616 // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY,
617 // ScrolledLines, Buffer, Length);
618 FrontEnd->Vtbl->WriteStream(FrontEnd,
619 &UpdateRect,
620 CursorStartX,
621 CursorStartY,
622 ScrolledLines,
623 Buffer,
624 Length);
625 }
626
627 return STATUS_SUCCESS;
628 }
629
630
631
632 static NTSTATUS NTAPI
633 ConSrvTermWriteStream(IN OUT PTERMINAL This,
634 PTEXTMODE_SCREEN_BUFFER Buff,
635 PWCHAR Buffer,
636 DWORD Length,
637 BOOL Attrib)
638 {
639 PFRONTEND FrontEnd = This->Data;
640 return ConioWriteConsole(FrontEnd,
641 Buff,
642 Buffer,
643 Length,
644 Attrib);
645 }
646
647 /************ Line discipline ***************/
648
649
650
651 static VOID NTAPI
652 ConSrvTermDrawRegion(IN OUT PTERMINAL This,
653 SMALL_RECT* Region)
654 {
655 PFRONTEND FrontEnd = This->Data;
656 FrontEnd->Vtbl->DrawRegion(FrontEnd, Region);
657 }
658
659 static BOOL NTAPI
660 ConSrvTermSetCursorInfo(IN OUT PTERMINAL This,
661 PCONSOLE_SCREEN_BUFFER ScreenBuffer)
662 {
663 PFRONTEND FrontEnd = This->Data;
664 return FrontEnd->Vtbl->SetCursorInfo(FrontEnd, ScreenBuffer);
665 }
666
667 static BOOL NTAPI
668 ConSrvTermSetScreenInfo(IN OUT PTERMINAL This,
669 PCONSOLE_SCREEN_BUFFER ScreenBuffer,
670 SHORT OldCursorX,
671 SHORT OldCursorY)
672 {
673 PFRONTEND FrontEnd = This->Data;
674 return FrontEnd->Vtbl->SetScreenInfo(FrontEnd,
675 ScreenBuffer,
676 OldCursorX,
677 OldCursorY);
678 }
679
680 static VOID NTAPI
681 ConSrvTermResizeTerminal(IN OUT PTERMINAL This)
682 {
683 PFRONTEND FrontEnd = This->Data;
684 FrontEnd->Vtbl->ResizeTerminal(FrontEnd);
685 }
686
687 static VOID NTAPI
688 ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This)
689 {
690 PFRONTEND FrontEnd = This->Data;
691 FrontEnd->Vtbl->SetActiveScreenBuffer(FrontEnd);
692 }
693
694 static VOID NTAPI
695 ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This,
696 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
697 {
698 PFRONTEND FrontEnd = This->Data;
699 FrontEnd->Vtbl->ReleaseScreenBuffer(FrontEnd, ScreenBuffer);
700 }
701
702 static VOID NTAPI
703 ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This,
704 PCOORD pSize)
705 {
706 PFRONTEND FrontEnd = This->Data;
707 FrontEnd->Vtbl->GetLargestConsoleWindowSize(FrontEnd, pSize);
708 }
709
710 static BOOL NTAPI
711 ConSrvTermSetPalette(IN OUT PTERMINAL This,
712 HPALETTE PaletteHandle,
713 UINT PaletteUsage)
714 {
715 PFRONTEND FrontEnd = This->Data;
716 return FrontEnd->Vtbl->SetPalette(FrontEnd, PaletteHandle, PaletteUsage);
717 }
718
719 static INT NTAPI
720 ConSrvTermShowMouseCursor(IN OUT PTERMINAL This,
721 BOOL Show)
722 {
723 PFRONTEND FrontEnd = This->Data;
724 return FrontEnd->Vtbl->ShowMouseCursor(FrontEnd, Show);
725 }
726
727 static TERMINAL_VTBL ConSrvTermVtbl =
728 {
729 ConSrvTermInitTerminal,
730 ConSrvTermDeinitTerminal,
731
732 ConSrvTermReadStream,
733 ConSrvTermWriteStream,
734
735 ConSrvTermDrawRegion,
736 ConSrvTermSetCursorInfo,
737 ConSrvTermSetScreenInfo,
738 ConSrvTermResizeTerminal,
739 ConSrvTermSetActiveScreenBuffer,
740 ConSrvTermReleaseScreenBuffer,
741 ConSrvTermGetLargestConsoleWindowSize,
742 ConSrvTermSetPalette,
743 ConSrvTermShowMouseCursor,
744 };
745
746 #if 0
747 VOID
748 ResetFrontEnd(IN PCONSOLE Console)
749 {
750 if (!Console) return;
751
752 /* Reinitialize the frontend interface */
753 RtlZeroMemory(&Console->FrontEndIFace, sizeof(Console->FrontEndIFace));
754 Console->FrontEndIFace.Vtbl = &ConSrvTermVtbl;
755 }
756 #endif
757
758 /* EOF */