e317334790a9b1d5b157fb7291b9daf591ae26d8
[reactos.git] / 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: win32ss/user/winsrv/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 SIZE_T 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
160 /* We display the output code page only */
161 pSharedInfo->CodePage = Console->OutputCodePage;
162
163 /* GUI Information */
164 StringCchCopyNW(pSharedInfo->FaceName, ARRAYSIZE(pSharedInfo->FaceName),
165 GuiData->GuiInfo.FaceName, ARRAYSIZE(GuiData->GuiInfo.FaceName));
166 pSharedInfo->FontFamily = GuiData->GuiInfo.FontFamily;
167 pSharedInfo->FontSize = GuiData->GuiInfo.FontSize;
168 pSharedInfo->FontWeight = GuiData->GuiInfo.FontWeight;
169 pSharedInfo->FullScreen = GuiData->GuiInfo.FullScreen;
170 pSharedInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
171 pSharedInfo->WindowPosition = GuiData->GuiInfo.WindowOrigin;
172
173 /* Palette */
174 RtlCopyMemory(pSharedInfo->ColorTable,
175 Console->Colors, sizeof(Console->Colors));
176
177 /* Copy the original title of the console and null-terminate it */
178 RtlCopyMemory(pSharedInfo->ConsoleTitle,
179 Console->OriginalTitle.Buffer,
180 Console->OriginalTitle.Length);
181
182 pSharedInfo->ConsoleTitle[Console->OriginalTitle.Length / sizeof(WCHAR)] = UNICODE_NULL;
183
184
185 /* Unmap the view */
186 NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo);
187
188 /* Duplicate the section handle for the client */
189 Status = NtDuplicateObject(NtCurrentProcess(),
190 hSection,
191 ProcessData->Process->ProcessHandle,
192 &hClientSection,
193 0, 0, DUPLICATE_SAME_ACCESS);
194 if (!NT_SUCCESS(Status))
195 {
196 DPRINT1("Error: Impossible to duplicate section handle for client, Status = 0x%08lx\n", Status);
197 goto Quit;
198 }
199
200 /* For the settings of a particular console, use the shared client section handle as the thread parameter */
201 ThreadParameter = (PVOID)hClientSection;
202 }
203 else
204 {
205 /* For the default settings, use the console window handle as the thread parameter */
206 ThreadParameter = (PVOID)GuiData->hWindow;
207 }
208
209 /* Start the console control panel applet */
210 _SEH2_TRY
211 {
212 HANDLE Thread = NULL;
213
214 _SEH2_TRY
215 {
216 Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
217 ProcessData->PropRoutine,
218 ThreadParameter, 0, NULL);
219 if (NULL == Thread)
220 {
221 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
222 }
223 else
224 {
225 DPRINT("ProcessData->PropRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n",
226 ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
227 }
228 }
229 _SEH2_FINALLY
230 {
231 CloseHandle(Thread);
232 }
233 _SEH2_END;
234 }
235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
236 {
237 Status = _SEH2_GetExceptionCode();
238 DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = 0x%08lx\n", Status);
239 }
240 _SEH2_END;
241
242 Quit:
243 /* We have finished, close the section handle if any */
244 if (hSection) NtClose(hSection);
245
246 LeaveCriticalSection(&Console->Lock);
247 return;
248 }
249
250 /*
251 * Function for dealing with the undocumented message and structure used by
252 * Windows' console.dll for setting console info.
253 * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c
254 * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf
255 * for more information.
256 */
257 VOID
258 GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
259 HANDLE hClientSection)
260 {
261 NTSTATUS Status = STATUS_SUCCESS;
262 PCONSRV_CONSOLE Console = GuiData->Console;
263 PCONSOLE_PROCESS_DATA ProcessData;
264 HANDLE hSection = NULL;
265 SIZE_T ViewSize = 0;
266 PCONSOLE_STATE_INFO pConInfo = NULL;
267
268 if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return;
269
270 /* Get the console leader process, our client */
271 ProcessData = ConSrvGetConsoleLeaderProcess(Console);
272
273 /* Duplicate the section handle for ourselves */
274 Status = NtDuplicateObject(ProcessData->Process->ProcessHandle,
275 hClientSection,
276 NtCurrentProcess(),
277 &hSection,
278 0, 0, DUPLICATE_SAME_ACCESS);
279 if (!NT_SUCCESS(Status))
280 {
281 DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status);
282 goto Quit;
283 }
284
285 /* Get a view of the shared section */
286 Status = NtMapViewOfSection(hSection,
287 NtCurrentProcess(),
288 (PVOID*)&pConInfo,
289 0,
290 0,
291 NULL,
292 &ViewSize,
293 ViewUnmap,
294 0,
295 PAGE_READWRITE);
296 if (!NT_SUCCESS(Status))
297 {
298 DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status);
299 goto Quit;
300 }
301
302 _SEH2_TRY
303 {
304 /* Check that the section is well-sized */
305 if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) ||
306 (pConInfo->cbSize < sizeof(CONSOLE_STATE_INFO)) )
307 {
308 DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n");
309 Status = STATUS_INVALID_VIEW_SIZE;
310 _SEH2_YIELD(goto Quit);
311 }
312
313 // TODO: Check that GuiData->hWindow == pConInfo->hWnd
314
315 /* Retrieve terminal informations */
316
317 /* Console information */
318 #if 0 // FIXME: Things not set
319 ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize;
320 ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers;
321 ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup;
322 ConInfo.CodePage = pConInfo->CodePage; // Done in ConSrvApplyUserSettings
323 #endif
324
325 /*
326 * Apply the settings
327 */
328
329 /* Set the console informations */
330 ConSrvApplyUserSettings(Console, pConInfo);
331
332 /* Set the terminal informations */
333
334 /* Change the font */
335 InitFonts(GuiData,
336 pConInfo->FaceName,
337 pConInfo->FontFamily,
338 pConInfo->FontSize,
339 pConInfo->FontWeight);
340 // HACK, needed because changing font may change the size of the window
341 /**/TermResizeTerminal(Console);/**/
342
343 /* Move the window to the user's values */
344 GuiData->GuiInfo.AutoPosition = !!pConInfo->AutoPosition;
345 GuiData->GuiInfo.WindowOrigin = pConInfo->WindowPosition;
346 GuiConsoleMoveWindow(GuiData);
347
348 InvalidateRect(GuiData->hWindow, NULL, TRUE);
349
350 /*
351 * Apply full-screen mode.
352 */
353 if (!!pConInfo->FullScreen != GuiData->GuiInfo.FullScreen)
354 {
355 SwitchFullScreen(GuiData, !!pConInfo->FullScreen);
356 }
357
358 /*
359 * The settings are saved in the registry by console.dll itself, if needed.
360 */
361 // if (SaveSettings)
362 // {
363 // GuiConsoleWriteUserSettings(GuiInfo);
364 // }
365
366 Status = STATUS_SUCCESS;
367 }
368 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
369 {
370 Status = _SEH2_GetExceptionCode();
371 DPRINT1("GuiApplyUserSettings - Caught an exception, Status = 0x%08lx\n", Status);
372 }
373 _SEH2_END;
374
375 Quit:
376 /* Finally, close the section and return */
377 if (hSection)
378 {
379 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo);
380 NtClose(hSection);
381 }
382
383 LeaveCriticalSection(&Console->Lock);
384 return;
385 }
386
387 /* EOF */