1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Console Server DLL
4  * FILE:            win32ss/user/winsrv/consrv/frontendctl.c
5  * PURPOSE:         Terminal Front-Ends Control
6  * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "consrv.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* PUBLIC SERVER APIS *********************************************************/
17 
18 /**********************************************************************
19  *  HardwareStateProperty
20  *
21  *  DESCRIPTION
22  *      Set/Get the value of the HardwareState and switch
23  *      between direct video buffer ouput and GDI windowed
24  *      output.
25  *  ARGUMENTS
26  *      Client hands us a CONSOLE_GETSETHWSTATE object.
27  *      We use the same object to Request.
28  *  NOTE
29  *      ConsoleHwState has the correct size to be compatible
30  *      with NT's, but values are not.
31  */
32 #if 0
33 static NTSTATUS
34 SetConsoleHardwareState(PCONSRV_CONSOLE Console, ULONG ConsoleHwState)
35 {
36     DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
37 
38     if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
39             ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
40     {
41         if (Console->HardwareState != ConsoleHwState)
42         {
43             /* TODO: implement switching from full screen to windowed mode */
44             /* TODO: or back; now simply store the hardware state */
45             Console->HardwareState = ConsoleHwState;
46         }
47 
48         return STATUS_SUCCESS;
49     }
50 
51     return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
52 }
53 #endif
54 
55 /* API_NUMBER: ConsolepGetHardwareState */
56 CSR_API(SrvGetConsoleHardwareState)
57 {
58 #if 0
59     NTSTATUS Status;
60     PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
61     PCONSOLE_SCREEN_BUFFER Buff;
62     PCONSRV_CONSOLE Console;
63 
64     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
65                                    HardwareStateRequest->OutputHandle,
66                                    &Buff,
67                                    GENERIC_READ,
68                                    TRUE);
69     if (!NT_SUCCESS(Status))
70     {
71         DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
72         return Status;
73     }
74 
75     Console = Buff->Header.Console;
76     HardwareStateRequest->State = Console->HardwareState;
77 
78     ConSrvReleaseScreenBuffer(Buff, TRUE);
79     return Status;
80 #else
81     UNIMPLEMENTED;
82     return STATUS_NOT_IMPLEMENTED;
83 #endif
84 }
85 
86 /* API_NUMBER: ConsolepSetHardwareState */
87 CSR_API(SrvSetConsoleHardwareState)
88 {
89 #if 0
90     NTSTATUS Status;
91     PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
92     PCONSOLE_SCREEN_BUFFER Buff;
93     PCONSRV_CONSOLE Console;
94 
95     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
96                                    HardwareStateRequest->OutputHandle,
97                                    &Buff,
98                                    GENERIC_WRITE,
99                                    TRUE);
100     if (!NT_SUCCESS(Status))
101     {
102         DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
103         return Status;
104     }
105 
106     DPRINT("Setting console hardware state.\n");
107     Console = Buff->Header.Console;
108     Status = SetConsoleHardwareState(Console, HardwareStateRequest->State);
109 
110     ConSrvReleaseScreenBuffer(Buff, TRUE);
111     return Status;
112 #else
113     UNIMPLEMENTED;
114     return STATUS_NOT_IMPLEMENTED;
115 #endif
116 }
117 
118 /* API_NUMBER: ConsolepGetDisplayMode */
119 CSR_API(SrvGetConsoleDisplayMode)
120 {
121     NTSTATUS Status;
122     PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
123     PCONSRV_CONSOLE Console;
124 
125     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
126                               &Console, TRUE);
127     if (!NT_SUCCESS(Status)) return Status;
128 
129     GetDisplayModeRequest->DisplayMode = TermGetDisplayMode(Console);
130 
131     ConSrvReleaseConsole(Console, TRUE);
132     return STATUS_SUCCESS;
133 }
134 
135 /* API_NUMBER: ConsolepSetDisplayMode */
136 CSR_API(SrvSetConsoleDisplayMode)
137 {
138     NTSTATUS Status;
139     PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
140     PCONSRV_CONSOLE Console;
141     PCONSOLE_SCREEN_BUFFER Buff;
142 
143     Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
144                                    SetDisplayModeRequest->OutputHandle,
145                                    &Buff,
146                                    GENERIC_WRITE,
147                                    TRUE);
148     if (!NT_SUCCESS(Status)) return Status;
149 
150     Console = (PCONSRV_CONSOLE)Buff->Header.Console;
151 
152     if (TermSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode))
153     {
154         SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
155         Status = STATUS_SUCCESS;
156     }
157     else
158     {
159         Status = STATUS_INVALID_PARAMETER;
160     }
161 
162     ConSrvReleaseScreenBuffer(Buff, TRUE);
163     return Status;
164 }
165 
166 /* API_NUMBER: ConsolepGetLargestWindowSize */
167 CSR_API(SrvGetLargestConsoleWindowSize)
168 {
169     NTSTATUS Status;
170     PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetLargestWindowSizeRequest;
171     PCONSOLE /*PCONSRV_CONSOLE*/ Console;
172     PCONSOLE_SCREEN_BUFFER Buff;
173 
174     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
175                                      GetLargestWindowSizeRequest->OutputHandle,
176                                      &Buff,
177                                      GENERIC_READ,
178                                      TRUE);
179     if (!NT_SUCCESS(Status)) return Status;
180 
181     Console = Buff->Header.Console;
182 
183     /*
184      * Retrieve the largest possible console window size, without
185      * taking into account the size of the console screen buffer
186      * (thus differs from ConDrvGetConsoleScreenBufferInfo).
187      */
188     TermGetLargestConsoleWindowSize(Console, &GetLargestWindowSizeRequest->Size);
189 
190     ConSrvReleaseScreenBuffer(Buff, TRUE);
191     return STATUS_SUCCESS;
192 }
193 
194 /* API_NUMBER: ConsolepShowCursor */
195 CSR_API(SrvShowConsoleCursor)
196 {
197     NTSTATUS Status;
198     PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest;
199     PCONSOLE /*PCONSRV_CONSOLE*/ Console;
200     PCONSOLE_SCREEN_BUFFER Buff;
201 
202     Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
203                                    ShowCursorRequest->OutputHandle,
204                                    &Buff,
205                                    GENERIC_WRITE,
206                                    TRUE);
207     if (!NT_SUCCESS(Status)) return Status;
208 
209     Console = Buff->Header.Console;
210 
211     ShowCursorRequest->RefCount = TermShowMouseCursor(Console, ShowCursorRequest->Show);
212 
213     ConSrvReleaseScreenBuffer(Buff, TRUE);
214     return STATUS_SUCCESS;
215 }
216 
217 /* API_NUMBER: ConsolepSetCursor */
218 CSR_API(SrvSetConsoleCursor)
219 {
220     NTSTATUS Status;
221     BOOL Success;
222     PCONSOLE_SETCURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
223     PCONSRV_CONSOLE Console;
224     PCONSOLE_SCREEN_BUFFER Buff;
225 
226     // NOTE: Tests show that this function is used only for graphics screen buffers
227     // and otherwise it returns FALSE and sets last error to ERROR_INVALID_HANDLE.
228     // I find that behaviour is ridiculous but ok, let's accept it at the moment...
229     Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
230                                      SetCursorRequest->OutputHandle,
231                                      &Buff,
232                                      GENERIC_WRITE,
233                                      TRUE);
234     if (!NT_SUCCESS(Status)) return Status;
235 
236     Console = (PCONSRV_CONSOLE)Buff->Header.Console;
237 
238     Success = TermSetMouseCursor(Console, SetCursorRequest->CursorHandle);
239 
240     ConSrvReleaseScreenBuffer(Buff, TRUE);
241     return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
242 }
243 
244 /* API_NUMBER: ConsolepMenuControl */
245 CSR_API(SrvConsoleMenuControl)
246 {
247     NTSTATUS Status;
248     PCONSOLE_MENUCONTROL MenuControlRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.MenuControlRequest;
249     PCONSRV_CONSOLE Console;
250     PCONSOLE_SCREEN_BUFFER Buff;
251 
252     Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
253                                    MenuControlRequest->OutputHandle,
254                                    &Buff,
255                                    GENERIC_WRITE,
256                                    TRUE);
257     if (!NT_SUCCESS(Status)) return Status;
258 
259     Console = (PCONSRV_CONSOLE)Buff->Header.Console;
260 
261     MenuControlRequest->MenuHandle = TermMenuControl(Console,
262                                                      MenuControlRequest->CmdIdLow,
263                                                      MenuControlRequest->CmdIdHigh);
264 
265     ConSrvReleaseScreenBuffer(Buff, TRUE);
266     return STATUS_SUCCESS;
267 }
268 
269 /* API_NUMBER: ConsolepSetMenuClose */
270 CSR_API(SrvSetConsoleMenuClose)
271 {
272     NTSTATUS Status;
273     BOOL Success;
274     PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetMenuCloseRequest;
275     PCONSRV_CONSOLE Console;
276 
277     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
278                               &Console, TRUE);
279     if (!NT_SUCCESS(Status)) return Status;
280 
281     Success = TermSetMenuClose(Console, SetMenuCloseRequest->Enable);
282 
283     ConSrvReleaseConsole(Console, TRUE);
284     return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
285 }
286 
287 /* Used by USERSRV!SrvGetThreadConsoleDesktop() */
288 NTSTATUS
289 NTAPI
290 GetThreadConsoleDesktop(
291     IN ULONG_PTR ThreadId,
292     OUT HDESK* ConsoleDesktop)
293 {
294     NTSTATUS Status;
295     PCSR_THREAD CsrThread;
296     PCONSRV_CONSOLE Console;
297 
298     /* No console desktop handle by default */
299     *ConsoleDesktop = NULL;
300 
301     /* Retrieve and lock the thread */
302     Status = CsrLockThreadByClientId(ULongToHandle(ThreadId), &CsrThread);
303     if (!NT_SUCCESS(Status))
304         return Status;
305 
306     ASSERT(CsrThread->Process);
307 
308     /* Retrieve the console to which the process is attached, and unlock the thread */
309     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrThread->Process),
310                               &Console, TRUE);
311     CsrUnlockThread(CsrThread);
312 
313     if (!NT_SUCCESS(Status))
314         return Status;
315 
316     /* Retrieve the console desktop handle, and release the console */
317     *ConsoleDesktop = TermGetThreadConsoleDesktop(Console);
318     ConSrvReleaseConsole(Console, TRUE);
319 
320     return STATUS_SUCCESS;
321 }
322 
323 /* API_NUMBER: ConsolepGetConsoleWindow */
324 CSR_API(SrvGetConsoleWindow)
325 {
326     NTSTATUS Status;
327     PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest;
328     PCONSRV_CONSOLE Console;
329 
330     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
331                               &Console, TRUE);
332     if (!NT_SUCCESS(Status)) return Status;
333 
334     GetWindowRequest->WindowHandle = TermGetConsoleWindowHandle(Console);
335 
336     ConSrvReleaseConsole(Console, TRUE);
337     return STATUS_SUCCESS;
338 }
339 
340 /* API_NUMBER: ConsolepSetIcon */
341 CSR_API(SrvSetConsoleIcon)
342 {
343     NTSTATUS Status;
344     PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest;
345     PCONSRV_CONSOLE Console;
346 
347     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
348                               &Console, TRUE);
349     if (!NT_SUCCESS(Status)) return Status;
350 
351     Status = (TermChangeIcon(Console, SetIconRequest->IconHandle)
352                 ? STATUS_SUCCESS
353                 : STATUS_UNSUCCESSFUL);
354 
355     ConSrvReleaseConsole(Console, TRUE);
356     return Status;
357 }
358 
359 /* API_NUMBER: ConsolepGetSelectionInfo */
360 CSR_API(SrvGetConsoleSelectionInfo)
361 {
362     NTSTATUS Status;
363     PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest;
364     PCONSRV_CONSOLE Console;
365 
366     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
367                               &Console, TRUE);
368     if (!NT_SUCCESS(Status)) return Status;
369 
370     Status = (TermGetSelectionInfo(Console, &GetSelectionInfoRequest->Info)
371                 ? STATUS_SUCCESS
372                 : STATUS_UNSUCCESSFUL);
373 
374     ConSrvReleaseConsole(Console, TRUE);
375     return Status;
376 }
377 
378 /* API_NUMBER: ConsolepGetNumberOfFonts */
379 CSR_API(SrvGetConsoleNumberOfFonts)
380 {
381     NTSTATUS Status;
382     PCONSOLE_GETNUMFONTS GetNumFontsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumFontsRequest;
383     PCONSOLE /*PCONSRV_CONSOLE*/ Console;
384 
385     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
386                               &Console, TRUE);
387     if (!NT_SUCCESS(Status)) return Status;
388 
389     // FIXME!
390     // TermGetNumberOfFonts(Console, ...);
391     DPRINT1("%s not yet implemented\n", __FUNCTION__);
392     GetNumFontsRequest->NumFonts = 0;
393 
394     ConSrvReleaseConsole(Console, TRUE);
395     return STATUS_SUCCESS;
396 }
397 
398 /* API_NUMBER: ConsolepGetFontInfo */
399 CSR_API(SrvGetConsoleFontInfo)
400 {
401     NTSTATUS Status;
402     PCONSOLE_GETFONTINFO GetFontInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetFontInfoRequest;
403     // PCONSOLE /*PCONSRV_CONSOLE*/ Console;
404     PCONSOLE_SCREEN_BUFFER Buff;
405 
406     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
407                                      GetFontInfoRequest->OutputHandle,
408                                      &Buff,
409                                      GENERIC_READ,
410                                      TRUE);
411     if (!NT_SUCCESS(Status)) return Status;
412 
413     // FIXME!
414     // Console = Buff->Header.Console;
415     // TermGetFontInfo(Console, ...);
416     DPRINT1("%s not yet implemented\n", __FUNCTION__);
417     GetFontInfoRequest->NumFonts = 0;
418 
419     ConSrvReleaseScreenBuffer(Buff, TRUE);
420     return STATUS_SUCCESS;
421 }
422 
423 /* API_NUMBER: ConsolepGetFontSize */
424 CSR_API(SrvGetConsoleFontSize)
425 {
426     NTSTATUS Status;
427     PCONSOLE_GETFONTSIZE GetFontSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetFontSizeRequest;
428     // PCONSOLE /*PCONSRV_CONSOLE*/ Console;
429     PCONSOLE_SCREEN_BUFFER Buff;
430 
431     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
432                                      GetFontSizeRequest->OutputHandle,
433                                      &Buff,
434                                      GENERIC_READ,
435                                      TRUE);
436     if (!NT_SUCCESS(Status)) return Status;
437 
438     // FIXME!
439     // Console = Buff->Header.Console;
440     // TermGetFontSize(Console, ...);
441     DPRINT1("%s not yet implemented\n", __FUNCTION__);
442 
443     ConSrvReleaseScreenBuffer(Buff, TRUE);
444     return STATUS_SUCCESS;
445 }
446 
447 /* API_NUMBER: ConsolepGetCurrentFont */
448 CSR_API(SrvGetConsoleCurrentFont)
449 {
450     NTSTATUS Status;
451     PCONSOLE_GETCURRENTFONT GetCurrentFontRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCurrentFontRequest;
452     // PCONSOLE /*PCONSRV_CONSOLE*/ Console;
453     PCONSOLE_SCREEN_BUFFER Buff;
454 
455     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
456                                      GetCurrentFontRequest->OutputHandle,
457                                      &Buff,
458                                      GENERIC_READ,
459                                      TRUE);
460     if (!NT_SUCCESS(Status)) return Status;
461 
462     // FIXME!
463     // Console = Buff->Header.Console;
464     // TermGetCurrentFont(Console, ...);
465     DPRINT1("%s not yet implemented\n", __FUNCTION__);
466     GetCurrentFontRequest->FontIndex = 0;
467 
468     ConSrvReleaseScreenBuffer(Buff, TRUE);
469     return STATUS_SUCCESS;
470 }
471 
472 /* API_NUMBER: ConsolepSetFont */
473 CSR_API(SrvSetConsoleFont)
474 {
475     NTSTATUS Status;
476     PCONSOLE_SETFONT SetFontRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetFontRequest;
477     // PCONSOLE /*PCONSRV_CONSOLE*/ Console;
478     PCONSOLE_SCREEN_BUFFER Buff;
479 
480     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
481                                      SetFontRequest->OutputHandle,
482                                      &Buff,
483                                      GENERIC_WRITE,
484                                      TRUE);
485     if (!NT_SUCCESS(Status)) return Status;
486 
487     // FIXME!
488     // Console = Buff->Header.Console;
489     // TermSetFont(Console, ...);
490     DPRINT1("%s not yet implemented\n", __FUNCTION__);
491 
492     ConSrvReleaseScreenBuffer(Buff, TRUE);
493     return STATUS_SUCCESS;
494 }
495 
496 /* EOF */
497