[CONSRV]
[reactos.git] / reactos / win32ss / user / winsrv / consrv / frontends / gui / guisettings.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: consrv/frontends/gui/guisettings.c
5 * PURPOSE: GUI Terminal Front-End Settings Management
6 * PROGRAMMERS: Johannes Anderwald
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <consrv.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 #include "guiterm.h"
18 #include "guisettings.h"
19
20 /* FUNCTIONS ******************************************************************/
21
22 BOOL
23 GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo)
24 {
25 /* Do nothing */
26 return TRUE;
27 }
28
29 BOOL
30 GuiConsoleWriteUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo)
31 {
32 /* Do nothing */
33 return TRUE;
34 }
35
36 VOID
37 GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo)
38 {
39 /* Do nothing */
40 }
41
42 VOID
43 GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
44 BOOL Defaults)
45 {
46 NTSTATUS Status;
47 PCONSRV_CONSOLE Console = GuiData->Console;
48 PCONSOLE_PROCESS_DATA ProcessData;
49 HANDLE hSection = NULL, hClientSection = NULL;
50 PVOID ThreadParameter = NULL; // Is either hClientSection or the console window handle,
51 // depending on whether we display the default settings or
52 // the settings of a particular console.
53
54 DPRINT("GuiConsoleShowConsoleProperties entered\n");
55
56 if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return;
57
58 /* Get the console leader process, our client */
59 ProcessData = ConSrvGetConsoleLeaderProcess(Console);
60
61 /*
62 * Be sure we effectively have a properties dialog routine (that launches
63 * the console control panel applet). It resides in kernel32.dll (client).
64 */
65 if (ProcessData->PropRoutine == NULL) goto Quit;
66
67 /*
68 * Create a memory section to be shared with the console control panel applet
69 * in the case we are displaying the settings of a particular console.
70 * In that case the ThreadParameter is the hClientSection handle.
71 * In the case we display the default console parameters, we don't need to
72 * create a memory section. We just need to open the applet, and in this case
73 * the ThreadParameter is the parent window handle of the applet's window,
74 * that is, the console window.
75 */
76 if (!Defaults)
77 {
78 PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
79 LARGE_INTEGER SectionSize;
80 ULONG ViewSize = 0;
81 PCONSOLE_STATE_INFO pSharedInfo = NULL;
82
83 /*
84 * Create a memory section to share with the applet, and map it.
85 */
86 SectionSize.QuadPart = sizeof(CONSOLE_STATE_INFO); // Standard size
87 SectionSize.QuadPart += Console->OriginalTitle.Length; // Add the length in bytes of the console title string
88
89 Status = NtCreateSection(&hSection,
90 SECTION_ALL_ACCESS,
91 NULL,
92 &SectionSize,
93 PAGE_READWRITE,
94 SEC_COMMIT,
95 NULL);
96 if (!NT_SUCCESS(Status))
97 {
98 DPRINT1("Error: Impossible to create a shared section, Status = 0x%08lx\n", Status);
99 goto Quit;
100 }
101
102 Status = NtMapViewOfSection(hSection,
103 NtCurrentProcess(),
104 (PVOID*)&pSharedInfo,
105 0,
106 0,
107 NULL,
108 &ViewSize,
109 ViewUnmap,
110 0,
111 PAGE_READWRITE);
112 if (!NT_SUCCESS(Status))
113 {
114 DPRINT1("Error: Impossible to map the shared section, Status = 0x%08lx\n", Status);
115 goto Quit;
116 }
117
118
119 /*
120 * Setup the shared console properties structure.
121 */
122
123 /* Store the real size of the structure */
124 pSharedInfo->cbSize = SectionSize.QuadPart;
125
126 /*
127 * When we setup the settings of a particular console, the parent window
128 * of the applet's window is the console window, and it is given via the
129 * hWnd member of the shared console info structure.
130 */
131 pSharedInfo->hWnd = GuiData->hWindow;
132
133 /* Console information */
134 pSharedInfo->HistoryBufferSize = Console->HistoryBufferSize;
135 pSharedInfo->NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
136 pSharedInfo->HistoryNoDup = Console->HistoryNoDup;
137 pSharedInfo->QuickEdit = Console->QuickEdit;
138 pSharedInfo->InsertMode = Console->InsertMode;
139 /// pSharedInfo->InputBufferSize = 0;
140 pSharedInfo->ScreenBufferSize = ActiveBuffer->ScreenBufferSize;
141 pSharedInfo->WindowSize = ActiveBuffer->ViewSize;
142 pSharedInfo->CursorSize = ActiveBuffer->CursorInfo.dwSize;
143 if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
144 {
145 PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
146
147 pSharedInfo->ScreenAttributes = Buffer->ScreenDefaultAttrib;
148 pSharedInfo->PopupAttributes = Buffer->PopupDefaultAttrib;
149 }
150 else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
151 {
152 // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer;
153 DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n");
154
155 // FIXME: Gather defaults from the registry ?
156 pSharedInfo->ScreenAttributes = DEFAULT_SCREEN_ATTRIB;
157 pSharedInfo->PopupAttributes = DEFAULT_POPUP_ATTRIB ;
158 }
159 /// pSharedInfo->CodePage;
160
161 /* GUI Information */
162 wcsncpy(pSharedInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE);
163 pSharedInfo->FaceName[LF_FACESIZE - 1] = UNICODE_NULL;
164 pSharedInfo->FontFamily = GuiData->GuiInfo.FontFamily;
165 pSharedInfo->FontSize = GuiData->GuiInfo.FontSize;
166 pSharedInfo->FontWeight = GuiData->GuiInfo.FontWeight;
167 pSharedInfo->FullScreen = GuiData->GuiInfo.FullScreen;
168 pSharedInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
169 pSharedInfo->WindowPosition = GuiData->GuiInfo.WindowOrigin;
170
171 /* Palette */
172 RtlCopyMemory(pSharedInfo->ColorTable,
173 Console->Colors, sizeof(Console->Colors));
174
175 /* Copy the original title of the console and null-terminate it */
176 RtlCopyMemory(pSharedInfo->ConsoleTitle,
177 Console->OriginalTitle.Buffer,
178 Console->OriginalTitle.Length);
179
180 pSharedInfo->ConsoleTitle[Console->OriginalTitle.Length / sizeof(WCHAR)] = UNICODE_NULL;
181
182
183 /* Unmap the view */
184 NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo);
185
186 /* Duplicate the section handle for the client */
187 Status = NtDuplicateObject(NtCurrentProcess(),
188 hSection,
189 ProcessData->Process->ProcessHandle,
190 &hClientSection,
191 0, 0, DUPLICATE_SAME_ACCESS);
192 if (!NT_SUCCESS(Status))
193 {
194 DPRINT1("Error: Impossible to duplicate section handle for client, Status = 0x%08lx\n", Status);
195 goto Quit;
196 }
197
198 /* For the settings of a particular console, use the shared client section handle as the thread parameter */
199 ThreadParameter = (PVOID)hClientSection;
200 }
201 else
202 {
203 /* For the default settings, use the console window handle as the thread parameter */
204 ThreadParameter = (PVOID)GuiData->hWindow;
205 }
206
207 /* Start the console control panel applet */
208 _SEH2_TRY
209 {
210 HANDLE Thread = NULL;
211
212 _SEH2_TRY
213 {
214 Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
215 ProcessData->PropRoutine,
216 ThreadParameter, 0, NULL);
217 if (NULL == Thread)
218 {
219 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
220 }
221 else
222 {
223 DPRINT("ProcessData->PropRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n",
224 ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
225 }
226 }
227 _SEH2_FINALLY
228 {
229 CloseHandle(Thread);
230 }
231 _SEH2_END;
232 }
233 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
234 {
235 Status = _SEH2_GetExceptionCode();
236 DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = 0x%08lx\n", Status);
237 }
238 _SEH2_END;
239
240 Quit:
241 /* We have finished, close the section handle if any */
242 if (hSection) NtClose(hSection);
243
244 LeaveCriticalSection(&Console->Lock);
245 return;
246 }
247
248 /*
249 * Function for dealing with the undocumented message and structure used by
250 * Windows' console.dll for setting console info.
251 * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c
252 * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf
253 * for more information.
254 */
255 VOID
256 GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
257 HANDLE hClientSection)
258 {
259 NTSTATUS Status = STATUS_SUCCESS;
260 PCONSRV_CONSOLE Console = GuiData->Console;
261 PCONSOLE_PROCESS_DATA ProcessData;
262 HANDLE hSection = NULL;
263 ULONG ViewSize = 0;
264 PCONSOLE_STATE_INFO pConInfo = NULL;
265
266 if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return;
267
268 /* Get the console leader process, our client */
269 ProcessData = ConSrvGetConsoleLeaderProcess(Console);
270
271 /* Duplicate the section handle for ourselves */
272 Status = NtDuplicateObject(ProcessData->Process->ProcessHandle,
273 hClientSection,
274 NtCurrentProcess(),
275 &hSection,
276 0, 0, DUPLICATE_SAME_ACCESS);
277 if (!NT_SUCCESS(Status))
278 {
279 DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status);
280 goto Quit;
281 }
282
283 /* Get a view of the shared section */
284 Status = NtMapViewOfSection(hSection,
285 NtCurrentProcess(),
286 (PVOID*)&pConInfo,
287 0,
288 0,
289 NULL,
290 &ViewSize,
291 ViewUnmap,
292 0,
293 PAGE_READWRITE);
294 if (!NT_SUCCESS(Status))
295 {
296 DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status);
297 goto Quit;
298 }
299
300 _SEH2_TRY
301 {
302 /* Check that the section is well-sized */
303 if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) ||
304 (pConInfo->cbSize < sizeof(CONSOLE_STATE_INFO)) )
305 {
306 DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n");
307 Status = STATUS_INVALID_VIEW_SIZE;
308 _SEH2_YIELD(goto Quit);
309 }
310
311 // TODO: Check that GuiData->hWindow == pConInfo->hWnd
312
313 /* Retrieve terminal informations */
314
315 /* Console information */
316 #if 0 // FIXME: Things not set
317 ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize;
318 ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers;
319 ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup;
320 ConInfo.CodePage = pConInfo->CodePage;
321 #endif
322
323 /*
324 * Apply the settings
325 */
326
327 /* Set the console informations */
328 ConSrvApplyUserSettings(Console, pConInfo);
329
330 /* Set the terminal informations */
331
332 /* Change the font */
333 InitFonts(GuiData,
334 pConInfo->FaceName,
335 pConInfo->FontFamily,
336 pConInfo->FontSize,
337 pConInfo->FontWeight);
338 // HACK, needed because changing font may change the size of the window
339 /**/TermResizeTerminal(Console);/**/
340
341 /* Move the window to the user's values */
342 GuiData->GuiInfo.AutoPosition = !!pConInfo->AutoPosition;
343 GuiData->GuiInfo.WindowOrigin = pConInfo->WindowPosition;
344 GuiConsoleMoveWindow(GuiData);
345
346 InvalidateRect(GuiData->hWindow, NULL, TRUE);
347
348 /*
349 * Apply full-screen mode.
350 */
351 if (!!pConInfo->FullScreen != GuiData->GuiInfo.FullScreen)
352 {
353 SwitchFullScreen(GuiData, !!pConInfo->FullScreen);
354 }
355
356 /*
357 * The settings are saved in the registry by console.dll itself, if needed.
358 */
359 // if (SaveSettings)
360 // {
361 // GuiConsoleWriteUserSettings(GuiInfo);
362 // }
363
364 Status = STATUS_SUCCESS;
365 }
366 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
367 {
368 Status = _SEH2_GetExceptionCode();
369 DPRINT1("GuiApplyUserSettings - Caught an exception, Status = 0x%08lx\n", Status);
370 }
371 _SEH2_END;
372
373 Quit:
374 /* Finally, close the section and return */
375 if (hSection)
376 {
377 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo);
378 NtClose(hSection);
379 }
380
381 LeaveCriticalSection(&Console->Lock);
382 return;
383 }
384
385 /* EOF */