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 CSR_API(SrvGetConsoleHardwareState)
56 {
57 #if 0
58     NTSTATUS Status;
59     PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
60     PCONSOLE_SCREEN_BUFFER Buff;
61     PCONSRV_CONSOLE Console;
62 
63     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
64                                    HardwareStateRequest->OutputHandle,
65                                    &Buff,
66                                    GENERIC_READ,
67                                    TRUE);
68     if (!NT_SUCCESS(Status))
69     {
70         DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
71         return Status;
72     }
73 
74     Console = Buff->Header.Console;
75     HardwareStateRequest->State = Console->HardwareState;
76 
77     ConSrvReleaseScreenBuffer(Buff, TRUE);
78     return Status;
79 #else
80     UNIMPLEMENTED;
81     return STATUS_NOT_IMPLEMENTED;
82 #endif
83 }
84 
85 CSR_API(SrvSetConsoleHardwareState)
86 {
87 #if 0
88     NTSTATUS Status;
89     PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
90     PCONSOLE_SCREEN_BUFFER Buff;
91     PCONSRV_CONSOLE Console;
92 
93     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
94                                    HardwareStateRequest->OutputHandle,
95                                    &Buff,
96                                    GENERIC_WRITE,
97                                    TRUE);
98     if (!NT_SUCCESS(Status))
99     {
100         DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
101         return Status;
102     }
103 
104     DPRINT("Setting console hardware state.\n");
105     Console = Buff->Header.Console;
106     Status = SetConsoleHardwareState(Console, HardwareStateRequest->State);
107 
108     ConSrvReleaseScreenBuffer(Buff, TRUE);
109     return Status;
110 #else
111     UNIMPLEMENTED;
112     return STATUS_NOT_IMPLEMENTED;
113 #endif
114 }
115 
116 CSR_API(SrvGetConsoleDisplayMode)
117 {
118     NTSTATUS Status;
119     PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
120     PCONSRV_CONSOLE Console;
121 
122     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
123                               &Console, TRUE);
124     if (!NT_SUCCESS(Status)) return Status;
125 
126     GetDisplayModeRequest->DisplayMode = TermGetDisplayMode(Console);
127 
128     ConSrvReleaseConsole(Console, TRUE);
129     return STATUS_SUCCESS;
130 }
131 
132 CSR_API(SrvSetConsoleDisplayMode)
133 {
134     NTSTATUS Status;
135     PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
136     PCONSRV_CONSOLE Console;
137     PCONSOLE_SCREEN_BUFFER Buff;
138 
139     Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
140                                    SetDisplayModeRequest->OutputHandle,
141                                    &Buff,
142                                    GENERIC_WRITE,
143                                    TRUE);
144     if (!NT_SUCCESS(Status)) return Status;
145 
146     Console = (PCONSRV_CONSOLE)Buff->Header.Console;
147 
148     if (TermSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode))
149     {
150         SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
151         Status = STATUS_SUCCESS;
152     }
153     else
154     {
155         Status = STATUS_INVALID_PARAMETER;
156     }
157 
158     ConSrvReleaseScreenBuffer(Buff, TRUE);
159     return Status;
160 }
161 
162 CSR_API(SrvGetLargestConsoleWindowSize)
163 {
164     NTSTATUS Status;
165     PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetLargestWindowSizeRequest;
166     PCONSOLE /*PCONSRV_CONSOLE*/ Console;
167     PCONSOLE_SCREEN_BUFFER Buff;
168 
169     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
170                                      GetLargestWindowSizeRequest->OutputHandle,
171                                      &Buff,
172                                      GENERIC_READ,
173                                      TRUE);
174     if (!NT_SUCCESS(Status)) return Status;
175 
176     Console = Buff->Header.Console;
177 
178     /*
179      * Retrieve the largest possible console window size, without
180      * taking into account the size of the console screen buffer
181      * (thus differs from ConDrvGetConsoleScreenBufferInfo).
182      */
183     TermGetLargestConsoleWindowSize(Console, &GetLargestWindowSizeRequest->Size);
184 
185     ConSrvReleaseScreenBuffer(Buff, TRUE);
186     return STATUS_SUCCESS;
187 }
188 
189 CSR_API(SrvShowConsoleCursor)
190 {
191     NTSTATUS Status;
192     PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest;
193     PCONSOLE /*PCONSRV_CONSOLE*/ Console;
194     PCONSOLE_SCREEN_BUFFER Buff;
195 
196     Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
197                                    ShowCursorRequest->OutputHandle,
198                                    &Buff,
199                                    GENERIC_WRITE,
200                                    TRUE);
201     if (!NT_SUCCESS(Status)) return Status;
202 
203     Console = Buff->Header.Console;
204 
205     ShowCursorRequest->RefCount = TermShowMouseCursor(Console, ShowCursorRequest->Show);
206 
207     ConSrvReleaseScreenBuffer(Buff, TRUE);
208     return STATUS_SUCCESS;
209 }
210 
211 CSR_API(SrvSetConsoleCursor)
212 {
213     NTSTATUS Status;
214     BOOL Success;
215     PCONSOLE_SETCURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
216     PCONSRV_CONSOLE Console;
217     PCONSOLE_SCREEN_BUFFER Buff;
218 
219     // NOTE: Tests show that this function is used only for graphics screen buffers
220     // and otherwise it returns FALSE and sets last error to ERROR_INVALID_HANDLE.
221     // I find that behaviour is ridiculous but ok, let's accept it at the moment...
222     Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
223                                      SetCursorRequest->OutputHandle,
224                                      &Buff,
225                                      GENERIC_WRITE,
226                                      TRUE);
227     if (!NT_SUCCESS(Status)) return Status;
228 
229     Console = (PCONSRV_CONSOLE)Buff->Header.Console;
230 
231     Success = TermSetMouseCursor(Console, SetCursorRequest->CursorHandle);
232 
233     ConSrvReleaseScreenBuffer(Buff, TRUE);
234     return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
235 }
236 
237 CSR_API(SrvConsoleMenuControl)
238 {
239     NTSTATUS Status;
240     PCONSOLE_MENUCONTROL MenuControlRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.MenuControlRequest;
241     PCONSRV_CONSOLE Console;
242     PCONSOLE_SCREEN_BUFFER Buff;
243 
244     Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
245                                    MenuControlRequest->OutputHandle,
246                                    &Buff,
247                                    GENERIC_WRITE,
248                                    TRUE);
249     if (!NT_SUCCESS(Status)) return Status;
250 
251     Console = (PCONSRV_CONSOLE)Buff->Header.Console;
252 
253     MenuControlRequest->MenuHandle = TermMenuControl(Console,
254                                                      MenuControlRequest->CmdIdLow,
255                                                      MenuControlRequest->CmdIdHigh);
256 
257     ConSrvReleaseScreenBuffer(Buff, TRUE);
258     return STATUS_SUCCESS;
259 }
260 
261 CSR_API(SrvSetConsoleMenuClose)
262 {
263     NTSTATUS Status;
264     BOOL Success;
265     PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetMenuCloseRequest;
266     PCONSRV_CONSOLE Console;
267 
268     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
269                               &Console, TRUE);
270     if (!NT_SUCCESS(Status)) return Status;
271 
272     Success = TermSetMenuClose(Console, SetMenuCloseRequest->Enable);
273 
274     ConSrvReleaseConsole(Console, TRUE);
275     return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
276 }
277 
278 /* Used by USERSRV!SrvGetThreadConsoleDesktop() */
279 NTSTATUS
280 NTAPI
281 GetThreadConsoleDesktop(
282     IN ULONG_PTR ThreadId,
283     OUT HDESK* ConsoleDesktop)
284 {
285     NTSTATUS Status;
286     PCSR_THREAD CsrThread;
287     PCONSRV_CONSOLE Console;
288 
289     /* No console desktop handle by default */
290     *ConsoleDesktop = NULL;
291 
292     /* Retrieve and lock the thread */
293     Status = CsrLockThreadByClientId(ULongToHandle(ThreadId), &CsrThread);
294     if (!NT_SUCCESS(Status))
295         return Status;
296 
297     ASSERT(CsrThread->Process);
298 
299     /* Retrieve the console to which the process is attached, and unlock the thread */
300     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrThread->Process),
301                               &Console, TRUE);
302     CsrUnlockThread(CsrThread);
303 
304     if (!NT_SUCCESS(Status))
305         return Status;
306 
307     /* Retrieve the console desktop handle, and release the console */
308     *ConsoleDesktop = TermGetThreadConsoleDesktop(Console);
309     ConSrvReleaseConsole(Console, TRUE);
310 
311     return STATUS_SUCCESS;
312 }
313 
314 CSR_API(SrvGetConsoleWindow)
315 {
316     NTSTATUS Status;
317     PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest;
318     PCONSRV_CONSOLE Console;
319 
320     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
321                               &Console, TRUE);
322     if (!NT_SUCCESS(Status)) return Status;
323 
324     GetWindowRequest->WindowHandle = TermGetConsoleWindowHandle(Console);
325 
326     ConSrvReleaseConsole(Console, TRUE);
327     return STATUS_SUCCESS;
328 }
329 
330 CSR_API(SrvSetConsoleIcon)
331 {
332     NTSTATUS Status;
333     PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest;
334     PCONSRV_CONSOLE Console;
335 
336     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
337                               &Console, TRUE);
338     if (!NT_SUCCESS(Status)) return Status;
339 
340     Status = (TermChangeIcon(Console, SetIconRequest->IconHandle)
341                 ? STATUS_SUCCESS
342                 : STATUS_UNSUCCESSFUL);
343 
344     ConSrvReleaseConsole(Console, TRUE);
345     return Status;
346 }
347 
348 CSR_API(SrvGetConsoleSelectionInfo)
349 {
350     NTSTATUS Status;
351     PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest;
352     PCONSRV_CONSOLE Console;
353 
354     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
355                               &Console, TRUE);
356     if (!NT_SUCCESS(Status)) return Status;
357 
358     Status = (TermGetSelectionInfo(Console, &GetSelectionInfoRequest->Info)
359                 ? STATUS_SUCCESS
360                 : STATUS_UNSUCCESSFUL);
361 
362     ConSrvReleaseConsole(Console, TRUE);
363     return Status;
364 }
365 
366 
367 
368 CSR_API(SrvGetConsoleNumberOfFonts)
369 {
370     NTSTATUS Status;
371     PCONSOLE_GETNUMFONTS GetNumFontsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumFontsRequest;
372     PCONSOLE /*PCONSRV_CONSOLE*/ Console;
373 
374     Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
375                               &Console, TRUE);
376     if (!NT_SUCCESS(Status)) return Status;
377 
378     // FIXME!
379     // TermGetNumberOfFonts(Console, ...);
380     DPRINT1("%s not yet implemented\n", __FUNCTION__);
381     GetNumFontsRequest->NumFonts = 0;
382 
383     ConSrvReleaseConsole(Console, TRUE);
384     return STATUS_SUCCESS;
385 }
386 
387 CSR_API(SrvGetConsoleFontInfo)
388 {
389     NTSTATUS Status;
390     PCONSOLE_GETFONTINFO GetFontInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetFontInfoRequest;
391     // PCONSOLE /*PCONSRV_CONSOLE*/ Console;
392     PCONSOLE_SCREEN_BUFFER Buff;
393 
394     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
395                                      GetFontInfoRequest->OutputHandle,
396                                      &Buff,
397                                      GENERIC_READ,
398                                      TRUE);
399     if (!NT_SUCCESS(Status)) return Status;
400 
401     // FIXME!
402     // Console = Buff->Header.Console;
403     // TermGetFontInfo(Console, ...);
404     DPRINT1("%s not yet implemented\n", __FUNCTION__);
405     GetFontInfoRequest->NumFonts = 0;
406 
407     ConSrvReleaseScreenBuffer(Buff, TRUE);
408     return STATUS_SUCCESS;
409 }
410 
411 CSR_API(SrvGetConsoleFontSize)
412 {
413     NTSTATUS Status;
414     PCONSOLE_GETFONTSIZE GetFontSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetFontSizeRequest;
415     // PCONSOLE /*PCONSRV_CONSOLE*/ Console;
416     PCONSOLE_SCREEN_BUFFER Buff;
417 
418     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
419                                      GetFontSizeRequest->OutputHandle,
420                                      &Buff,
421                                      GENERIC_READ,
422                                      TRUE);
423     if (!NT_SUCCESS(Status)) return Status;
424 
425     // FIXME!
426     // Console = Buff->Header.Console;
427     // TermGetFontSize(Console, ...);
428     DPRINT1("%s not yet implemented\n", __FUNCTION__);
429 
430     ConSrvReleaseScreenBuffer(Buff, TRUE);
431     return STATUS_SUCCESS;
432 }
433 
434 CSR_API(SrvGetConsoleCurrentFont)
435 {
436     NTSTATUS Status;
437     PCONSOLE_GETCURRENTFONT GetCurrentFontRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCurrentFontRequest;
438     // PCONSOLE /*PCONSRV_CONSOLE*/ Console;
439     PCONSOLE_SCREEN_BUFFER Buff;
440 
441     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
442                                      GetCurrentFontRequest->OutputHandle,
443                                      &Buff,
444                                      GENERIC_READ,
445                                      TRUE);
446     if (!NT_SUCCESS(Status)) return Status;
447 
448     // FIXME!
449     // Console = Buff->Header.Console;
450     // TermGetCurrentFont(Console, ...);
451     DPRINT1("%s not yet implemented\n", __FUNCTION__);
452     GetCurrentFontRequest->FontIndex = 0;
453 
454     ConSrvReleaseScreenBuffer(Buff, TRUE);
455     return STATUS_SUCCESS;
456 }
457 
458 CSR_API(SrvSetConsoleFont)
459 {
460     NTSTATUS Status;
461     PCONSOLE_SETFONT SetFontRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetFontRequest;
462     // PCONSOLE /*PCONSRV_CONSOLE*/ Console;
463     PCONSOLE_SCREEN_BUFFER Buff;
464 
465     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
466                                      SetFontRequest->OutputHandle,
467                                      &Buff,
468                                      GENERIC_WRITE,
469                                      TRUE);
470     if (!NT_SUCCESS(Status)) return Status;
471 
472     // FIXME!
473     // Console = Buff->Header.Console;
474     // TermSetFont(Console, ...);
475     DPRINT1("%s not yet implemented\n", __FUNCTION__);
476 
477     ConSrvReleaseScreenBuffer(Buff, TRUE);
478     return STATUS_SUCCESS;
479 }
480 
481 /* EOF */
482