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