Sync with trunk r63887.
[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 /* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/
22
23 /***************/
24 #ifdef TUITERM_COMPILE
25 NTSTATUS NTAPI
26 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
27 IN OUT PCONSOLE_INFO ConsoleInfo,
28 IN OUT PVOID ExtraConsoleInfo,
29 IN ULONG ProcessId);
30 NTSTATUS NTAPI
31 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
32 #endif
33
34 NTSTATUS NTAPI
35 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
36 IN OUT PCONSOLE_INFO ConsoleInfo,
37 IN OUT PVOID ExtraConsoleInfo,
38 IN ULONG ProcessId);
39 NTSTATUS NTAPI
40 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
41 /***************/
42
43 typedef
44 NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
45 IN OUT PCONSOLE_INFO ConsoleInfo,
46 IN OUT PVOID ExtraConsoleInfo,
47 IN ULONG ProcessId);
48
49 typedef
50 NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
51
52 /*
53 * If we are not in GUI-mode, start the text-mode terminal emulator.
54 * If we fail, try to start the GUI-mode terminal emulator.
55 *
56 * Try to open the GUI-mode terminal emulator. Two cases are possible:
57 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
58 * failed and we start GUI-mode terminal emulator.
59 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
60 * succeeded BUT we failed at starting text-mode terminal emulator.
61 * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
62 * terminal emulator (Win32k will automatically switch to graphical mode,
63 * therefore no additional code is needed).
64 */
65
66 /*
67 * NOTE: Each entry of the table should be retrieved when loading a front-end
68 * (examples of the CSR servers which register some data for CSRSS).
69 */
70 struct
71 {
72 CHAR FrontEndName[80];
73 FRONTEND_LOAD FrontEndLoad;
74 FRONTEND_UNLOAD FrontEndUnload;
75 } FrontEndLoadingMethods[] =
76 {
77 #ifdef TUITERM_COMPILE
78 {"TUI", TuiLoadFrontEnd, TuiUnloadFrontEnd},
79 #endif
80 {"GUI", GuiLoadFrontEnd, GuiUnloadFrontEnd},
81
82 // {"Not found", 0, NULL}
83 };
84
85 static NTSTATUS
86 ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
87 IN OUT PCONSOLE_INFO ConsoleInfo,
88 IN OUT PVOID ExtraConsoleInfo,
89 IN ULONG ProcessId)
90 {
91 NTSTATUS Status = STATUS_SUCCESS;
92 ULONG i;
93
94 /*
95 * Choose an adequate terminal front-end to load, and load it
96 */
97 for (i = 0; i < sizeof(FrontEndLoadingMethods) / sizeof(FrontEndLoadingMethods[0]); ++i)
98 {
99 DPRINT("CONSRV: Trying to load %s frontend...\n",
100 FrontEndLoadingMethods[i].FrontEndName);
101 Status = FrontEndLoadingMethods[i].FrontEndLoad(FrontEnd,
102 ConsoleInfo,
103 ExtraConsoleInfo,
104 ProcessId);
105 if (NT_SUCCESS(Status))
106 {
107 /* Save the unload callback */
108 FrontEnd->UnloadFrontEnd = FrontEndLoadingMethods[i].FrontEndUnload;
109
110 DPRINT("CONSRV: %s frontend loaded successfully\n",
111 FrontEndLoadingMethods[i].FrontEndName);
112 break;
113 }
114 else
115 {
116 DPRINT1("CONSRV: Loading %s frontend failed, Status = 0x%08lx , continuing...\n",
117 FrontEndLoadingMethods[i].FrontEndName, Status);
118 }
119 }
120
121 return Status;
122 }
123
124 static NTSTATUS
125 ConSrvUnloadFrontEnd(IN PFRONTEND FrontEnd)
126 {
127 if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
128 // return FrontEnd->Vtbl->UnloadFrontEnd(FrontEnd);
129 return FrontEnd->UnloadFrontEnd(FrontEnd);
130 }
131
132 // See after...
133 static TERMINAL_VTBL ConSrvTermVtbl;
134
135 NTSTATUS NTAPI
136 ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
137 IN OUT PCONSOLE_INFO ConsoleInfo,
138 IN OUT PVOID ExtraConsoleInfo,
139 IN ULONG ProcessId)
140 {
141 NTSTATUS Status;
142 PFRONTEND FrontEnd;
143
144 /* Load a suitable frontend for the ConSrv terminal */
145 FrontEnd = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*FrontEnd));
146 if (!FrontEnd) return STATUS_NO_MEMORY;
147
148 Status = ConSrvLoadFrontEnd(FrontEnd,
149 ConsoleInfo,
150 ExtraConsoleInfo,
151 ProcessId);
152 if (!NT_SUCCESS(Status))
153 {
154 DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
155 ConsoleFreeHeap(FrontEnd);
156 return Status;
157 }
158 DPRINT("CONSRV: Frontend initialized\n");
159
160 /* Initialize the ConSrv terminal */
161 Terminal->Vtbl = &ConSrvTermVtbl;
162 // Terminal->Console will be initialized by ConDrvRegisterTerminal
163 Terminal->Data = FrontEnd; /* We store the frontend pointer in the terminal private data */
164
165 return STATUS_SUCCESS;
166 }
167
168 NTSTATUS NTAPI
169 ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal)
170 {
171 NTSTATUS Status = STATUS_SUCCESS;
172 PFRONTEND FrontEnd = Terminal->Data;
173
174 /* Reset the ConSrv terminal */
175 Terminal->Data = NULL;
176 Terminal->Vtbl = NULL;
177
178 /* Unload the frontend */
179 if (FrontEnd != NULL)
180 {
181 Status = ConSrvUnloadFrontEnd(FrontEnd);
182 ConsoleFreeHeap(FrontEnd);
183 }
184
185 return Status;
186 }
187
188
189 /* CONSRV TERMINAL INTERFACE **************************************************/
190
191 static NTSTATUS NTAPI
192 ConSrvTermInitTerminal(IN OUT PTERMINAL This,
193 IN PCONSOLE Console)
194 {
195 NTSTATUS Status;
196 PFRONTEND FrontEnd = This->Data;
197
198 /* Initialize the console pointer for our frontend */
199 FrontEnd->Console = Console;
200
201 /** HACK HACK!! Copy FrontEnd into the console!! **/
202 DPRINT1("Using FrontEndIFace HACK(1), should be removed after proper implementation!\n");
203 Console->FrontEndIFace = *FrontEnd;
204
205 Status = FrontEnd->Vtbl->InitFrontEnd(FrontEnd, FrontEnd->Console);
206
207 /** HACK HACK!! Be sure FrontEndIFace is correctly updated in the console!! **/
208 DPRINT1("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n");
209 Console->FrontEndIFace = *FrontEnd;
210
211 return Status;
212 }
213
214 static VOID NTAPI
215 ConSrvTermDeinitTerminal(IN OUT PTERMINAL This)
216 {
217 PFRONTEND FrontEnd = This->Data;
218 FrontEnd->Vtbl->DeinitFrontEnd(FrontEnd);
219 }
220
221 static VOID NTAPI
222 ConSrvTermDrawRegion(IN OUT PTERMINAL This,
223 SMALL_RECT* Region)
224 {
225 PFRONTEND FrontEnd = This->Data;
226 FrontEnd->Vtbl->DrawRegion(FrontEnd, Region);
227 }
228
229 static VOID NTAPI
230 ConSrvTermWriteStream(IN OUT PTERMINAL This,
231 SMALL_RECT* Region,
232 SHORT CursorStartX,
233 SHORT CursorStartY,
234 UINT ScrolledLines,
235 PWCHAR Buffer,
236 UINT Length)
237 {
238 PFRONTEND FrontEnd = This->Data;
239 FrontEnd->Vtbl->WriteStream(FrontEnd,
240 Region,
241 CursorStartX,
242 CursorStartY,
243 ScrolledLines,
244 Buffer,
245 Length);
246 }
247
248 static BOOL NTAPI
249 ConSrvTermSetCursorInfo(IN OUT PTERMINAL This,
250 PCONSOLE_SCREEN_BUFFER ScreenBuffer)
251 {
252 PFRONTEND FrontEnd = This->Data;
253 return FrontEnd->Vtbl->SetCursorInfo(FrontEnd, ScreenBuffer);
254 }
255
256 static BOOL NTAPI
257 ConSrvTermSetScreenInfo(IN OUT PTERMINAL This,
258 PCONSOLE_SCREEN_BUFFER ScreenBuffer,
259 SHORT OldCursorX,
260 SHORT OldCursorY)
261 {
262 PFRONTEND FrontEnd = This->Data;
263 return FrontEnd->Vtbl->SetScreenInfo(FrontEnd,
264 ScreenBuffer,
265 OldCursorX,
266 OldCursorY);
267 }
268
269 static VOID NTAPI
270 ConSrvTermResizeTerminal(IN OUT PTERMINAL This)
271 {
272 PFRONTEND FrontEnd = This->Data;
273 FrontEnd->Vtbl->ResizeTerminal(FrontEnd);
274 }
275
276 static VOID NTAPI
277 ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This)
278 {
279 PFRONTEND FrontEnd = This->Data;
280 FrontEnd->Vtbl->SetActiveScreenBuffer(FrontEnd);
281 }
282
283 static VOID NTAPI
284 ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This,
285 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
286 {
287 PFRONTEND FrontEnd = This->Data;
288 FrontEnd->Vtbl->ReleaseScreenBuffer(FrontEnd, ScreenBuffer);
289 }
290
291 static VOID NTAPI
292 ConSrvTermChangeTitle(IN OUT PTERMINAL This)
293 {
294 PFRONTEND FrontEnd = This->Data;
295 FrontEnd->Vtbl->ChangeTitle(FrontEnd);
296 }
297
298 static VOID NTAPI
299 ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This,
300 PCOORD pSize)
301 {
302 PFRONTEND FrontEnd = This->Data;
303 FrontEnd->Vtbl->GetLargestConsoleWindowSize(FrontEnd, pSize);
304 }
305
306 /*
307 static BOOL NTAPI
308 ConSrvTermGetSelectionInfo(IN OUT PTERMINAL This,
309 PCONSOLE_SELECTION_INFO pSelectionInfo)
310 {
311 PFRONTEND FrontEnd = This->Data;
312 return FrontEnd->Vtbl->GetSelectionInfo(FrontEnd, pSelectionInfo);
313 }
314 */
315
316 static BOOL NTAPI
317 ConSrvTermSetPalette(IN OUT PTERMINAL This,
318 HPALETTE PaletteHandle,
319 UINT PaletteUsage)
320 {
321 PFRONTEND FrontEnd = This->Data;
322 return FrontEnd->Vtbl->SetPalette(FrontEnd, PaletteHandle, PaletteUsage);
323 }
324
325 static INT NTAPI
326 ConSrvTermShowMouseCursor(IN OUT PTERMINAL This,
327 BOOL Show)
328 {
329 PFRONTEND FrontEnd = This->Data;
330 return FrontEnd->Vtbl->ShowMouseCursor(FrontEnd, Show);
331 }
332
333 static TERMINAL_VTBL ConSrvTermVtbl =
334 {
335 ConSrvTermInitTerminal,
336 ConSrvTermDeinitTerminal,
337 ConSrvTermDrawRegion,
338 ConSrvTermWriteStream,
339 ConSrvTermSetCursorInfo,
340 ConSrvTermSetScreenInfo,
341 ConSrvTermResizeTerminal,
342 ConSrvTermSetActiveScreenBuffer,
343 ConSrvTermReleaseScreenBuffer,
344 ConSrvTermChangeTitle,
345 ConSrvTermGetLargestConsoleWindowSize,
346 // ConSrvTermGetSelectionInfo,
347 ConSrvTermSetPalette,
348 ConSrvTermShowMouseCursor,
349 };
350
351 #if 0
352 VOID
353 ResetFrontEnd(IN PCONSOLE Console)
354 {
355 if (!Console) return;
356
357 /* Reinitialize the frontend interface */
358 RtlZeroMemory(&Console->FrontEndIFace, sizeof(Console->FrontEndIFace));
359 Console->FrontEndIFace.Vtbl = &ConSrvTermVtbl;
360 }
361 #endif
362
363 /* EOF */