[CONSOLE.CPL][CONSRV]
[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 VOID GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData);
21 VOID SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen);
22
23 /* FUNCTIONS ******************************************************************/
24
25 BOOL
26 GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
27 IN LPCWSTR ConsoleTitle,
28 IN DWORD ProcessId)
29 {
30 /*****************************************************
31 * Adapted from ConSrvReadUserSettings in settings.c *
32 *****************************************************/
33
34 BOOL RetVal = FALSE;
35 HKEY hKey;
36 DWORD dwNumSubKeys = 0;
37 DWORD dwIndex;
38 DWORD dwType;
39 WCHAR szValueName[MAX_PATH];
40 DWORD dwValueName;
41 WCHAR szValue[LF_FACESIZE] = L"\0";
42 DWORD Value;
43 DWORD dwValue;
44
45 if (!ConSrvOpenUserSettings(ProcessId,
46 ConsoleTitle,
47 &hKey, KEY_READ,
48 FALSE))
49 {
50 DPRINT("ConSrvOpenUserSettings failed\n");
51 return FALSE;
52 }
53
54 if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
55 &dwNumSubKeys, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
56 {
57 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
58 RegCloseKey(hKey);
59 return FALSE;
60 }
61
62 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys);
63
64 for (dwIndex = 0; dwIndex < dwNumSubKeys; dwIndex++)
65 {
66 dwValue = sizeof(Value);
67 dwValueName = MAX_PATH; // sizeof(szValueName)/sizeof(szValueName[0])
68
69 if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, &dwType, (BYTE*)&Value, &dwValue) != ERROR_SUCCESS)
70 {
71 if (dwType == REG_SZ)
72 {
73 /*
74 * Retry in case of string value
75 */
76 dwValue = sizeof(szValue);
77 dwValueName = MAX_PATH; // sizeof(szValueName)/sizeof(szValueName[0])
78 if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (BYTE*)szValue, &dwValue) != ERROR_SUCCESS)
79 break;
80 }
81 else
82 {
83 break;
84 }
85 }
86
87 if (!wcscmp(szValueName, L"FaceName"))
88 {
89 SIZE_T Length = min(wcslen(szValue) + 1, LF_FACESIZE); // wcsnlen
90 wcsncpy(TermInfo->FaceName, szValue, LF_FACESIZE);
91 TermInfo->FaceName[Length] = L'\0';
92 RetVal = TRUE;
93 }
94 else if (!wcscmp(szValueName, L"FontFamily"))
95 {
96 TermInfo->FontFamily = Value;
97 RetVal = TRUE;
98 }
99 else if (!wcscmp(szValueName, L"FontSize"))
100 {
101 TermInfo->FontSize.X = LOWORD(Value); // Width
102 TermInfo->FontSize.Y = HIWORD(Value); // Height
103 RetVal = TRUE;
104 }
105 else if (!wcscmp(szValueName, L"FontWeight"))
106 {
107 TermInfo->FontWeight = Value;
108 RetVal = TRUE;
109 }
110 else if (!wcscmp(szValueName, L"FullScreen"))
111 {
112 TermInfo->FullScreen = Value;
113 RetVal = TRUE;
114 }
115 else if (!wcscmp(szValueName, L"WindowPosition"))
116 {
117 TermInfo->AutoPosition = FALSE;
118 TermInfo->WindowOrigin.x = LOWORD(Value);
119 TermInfo->WindowOrigin.y = HIWORD(Value);
120 RetVal = TRUE;
121 }
122 }
123
124 RegCloseKey(hKey);
125 return RetVal;
126 }
127
128 BOOL
129 GuiConsoleWriteUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
130 IN LPCWSTR ConsoleTitle,
131 IN DWORD ProcessId)
132 {
133 /******************************************************
134 * Adapted from ConSrvWriteUserSettings in settings.c *
135 ******************************************************/
136
137 BOOL GlobalSettings = (ConsoleTitle[0] == L'\0');
138 HKEY hKey;
139 DWORD Storage = 0;
140
141 #define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
142 do { \
143 if (GlobalSettings || (!GlobalSettings && (*(Setting) != (DefaultValue)))) \
144 { \
145 RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
146 } \
147 else \
148 { \
149 RegDeleteValue(hKey, (SettingName)); \
150 } \
151 } while (0)
152
153 if (!ConSrvOpenUserSettings(ProcessId,
154 ConsoleTitle,
155 &hKey, KEY_WRITE,
156 TRUE))
157 {
158 return FALSE;
159 }
160
161 SetConsoleSetting(L"FaceName", REG_SZ, (wcslen(TermInfo->FaceName) + 1) * sizeof(WCHAR), TermInfo->FaceName, L'\0'); // wcsnlen
162 SetConsoleSetting(L"FontFamily", REG_DWORD, sizeof(DWORD), &TermInfo->FontFamily, FF_DONTCARE);
163
164 Storage = MAKELONG(TermInfo->FontSize.X, TermInfo->FontSize.Y); // Width, Height
165 SetConsoleSetting(L"FontSize", REG_DWORD, sizeof(DWORD), &Storage, 0);
166
167 SetConsoleSetting(L"FontWeight", REG_DWORD, sizeof(DWORD), &TermInfo->FontWeight, FW_DONTCARE);
168
169 Storage = TermInfo->FullScreen;
170 SetConsoleSetting(L"FullScreen", REG_DWORD, sizeof(DWORD), &Storage, FALSE);
171
172 if (TermInfo->AutoPosition == FALSE)
173 {
174 Storage = MAKELONG(TermInfo->WindowOrigin.x, TermInfo->WindowOrigin.y);
175 RegSetValueExW(hKey, L"WindowPosition", 0, REG_DWORD, (PBYTE)&Storage, sizeof(DWORD));
176 }
177 else
178 {
179 RegDeleteValue(hKey, L"WindowPosition");
180 }
181
182 RegCloseKey(hKey);
183 return TRUE;
184 }
185
186 VOID
187 GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
188 IN DWORD ProcessId)
189 {
190 /*******************************************************
191 * Adapted from ConSrvGetDefaultSettings in settings.c *
192 *******************************************************/
193
194 if (TermInfo == NULL) return;
195
196 /*
197 * 1. Load the default values
198 */
199 // wcsncpy(TermInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
200 // TermInfo->FontSize = MAKELONG(8, 12); // 0x000C0008; // font is 8x12
201 // TermInfo->FontSize = MAKELONG(16, 16); // font is 16x16
202 // TermInfo->FontWeight = FW_NORMAL;
203
204 wcsncpy(TermInfo->FaceName, L"VGA", LF_FACESIZE); // HACK: !!
205 // TermInfo->FaceName[0] = L'\0';
206 TermInfo->FontFamily = FF_DONTCARE;
207 TermInfo->FontSize.X = 0;
208 TermInfo->FontSize.Y = 0;
209 TermInfo->FontWeight = FW_DONTCARE;
210
211 TermInfo->FullScreen = FALSE;
212 TermInfo->ShowWindow = SW_SHOWNORMAL;
213 TermInfo->AutoPosition = TRUE;
214 TermInfo->WindowOrigin.x = 0;
215 TermInfo->WindowOrigin.y = 0;
216
217 /*
218 * 2. Overwrite them with the ones stored in HKCU\Console.
219 * If the HKCU\Console key doesn't exist, create it
220 * and store the default values inside.
221 */
222 if (!GuiConsoleReadUserSettings(TermInfo, L"", ProcessId))
223 {
224 GuiConsoleWriteUserSettings(TermInfo, L"", ProcessId);
225 }
226 }
227
228 VOID
229 GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
230 BOOL Defaults)
231 {
232 NTSTATUS Status;
233 PCONSOLE Console = GuiData->Console;
234 PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
235 PCONSOLE_PROCESS_DATA ProcessData;
236 HANDLE hSection = NULL, hClientSection = NULL;
237 LARGE_INTEGER SectionSize;
238 ULONG ViewSize = 0;
239 SIZE_T Length = 0;
240 PCONSOLE_PROPS pSharedInfo = NULL;
241 PGUI_CONSOLE_INFO GuiInfo = NULL;
242
243 DPRINT("GuiConsoleShowConsoleProperties entered\n");
244
245 if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
246
247 /*
248 * Create a memory section to share with the applet, and map it.
249 */
250 /* Holds data for console.dll + console info + terminal-specific info */
251 SectionSize.QuadPart = sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO);
252 Status = NtCreateSection(&hSection,
253 SECTION_ALL_ACCESS,
254 NULL,
255 &SectionSize,
256 PAGE_READWRITE,
257 SEC_COMMIT,
258 NULL);
259 if (!NT_SUCCESS(Status))
260 {
261 DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status);
262 goto Quit;
263 }
264
265 Status = NtMapViewOfSection(hSection,
266 NtCurrentProcess(),
267 (PVOID*)&pSharedInfo,
268 0,
269 0,
270 NULL,
271 &ViewSize,
272 ViewUnmap,
273 0,
274 PAGE_READWRITE);
275 if (!NT_SUCCESS(Status))
276 {
277 DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
278 goto Quit;
279 }
280
281
282 /*
283 * Setup the shared console properties structure.
284 */
285
286 /* Header */
287 pSharedInfo->hConsoleWindow = GuiData->hWindow;
288 pSharedInfo->ShowDefaultParams = Defaults;
289
290 /*
291 * We fill-in the fields only if we display
292 * our properties, not the default ones.
293 */
294 if (!Defaults)
295 {
296 /* Console information */
297 pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize;
298 pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
299 pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup;
300 pSharedInfo->ci.QuickEdit = Console->QuickEdit;
301 pSharedInfo->ci.InsertMode = Console->InsertMode;
302 pSharedInfo->ci.InputBufferSize = 0;
303 pSharedInfo->ci.ScreenBufferSize = ActiveBuffer->ScreenBufferSize;
304 pSharedInfo->ci.ConsoleSize = ActiveBuffer->ViewSize;
305 pSharedInfo->ci.CursorBlinkOn;
306 pSharedInfo->ci.ForceCursorOff;
307 pSharedInfo->ci.CursorSize = ActiveBuffer->CursorInfo.dwSize;
308 if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
309 {
310 PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
311
312 pSharedInfo->ci.ScreenAttrib = Buffer->ScreenDefaultAttrib;
313 pSharedInfo->ci.PopupAttrib = Buffer->PopupDefaultAttrib;
314 }
315 else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
316 {
317 // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer;
318 DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n");
319
320 // FIXME: Gather defaults from the registry ?
321 pSharedInfo->ci.ScreenAttrib = DEFAULT_SCREEN_ATTRIB;
322 pSharedInfo->ci.PopupAttrib = DEFAULT_POPUP_ATTRIB ;
323 }
324 pSharedInfo->ci.CodePage;
325
326 /* GUI Information */
327 pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
328 GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1);
329 Length = min(wcslen(GuiData->GuiInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
330 wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE);
331 GuiInfo->FaceName[Length] = L'\0';
332 GuiInfo->FontFamily = GuiData->GuiInfo.FontFamily;
333 GuiInfo->FontSize = GuiData->GuiInfo.FontSize;
334 GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight;
335 GuiInfo->FullScreen = GuiData->GuiInfo.FullScreen;
336 GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
337 GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin;
338 /* Offsetize */
339 pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo);
340
341 /* Palette */
342 memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors));
343
344 /* Title of the console, original one corresponding to the one set by the console leader */
345 Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1,
346 Console->OriginalTitle.Length / sizeof(WCHAR));
347 wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length);
348 }
349 else
350 {
351 Length = 0;
352 // FIXME: Load the default parameters from the registry.
353 }
354
355 /* Null-terminate the title */
356 pSharedInfo->ci.ConsoleTitle[Length] = L'\0';
357
358
359 /* Unmap the view */
360 NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo);
361
362 /* Get the console leader process, our client */
363 ProcessData = ConSrvGetConsoleLeaderProcess(Console);
364
365 /* Duplicate the section handle for the client */
366 Status = NtDuplicateObject(NtCurrentProcess(),
367 hSection,
368 ProcessData->Process->ProcessHandle,
369 &hClientSection,
370 0, 0, DUPLICATE_SAME_ACCESS);
371 if (!NT_SUCCESS(Status))
372 {
373 DPRINT1("Error: Impossible to duplicate section handle for client ; Status = %lu\n", Status);
374 goto Quit;
375 }
376
377 /* Start the properties dialog */
378 if (ProcessData->PropDispatcher)
379 {
380 _SEH2_TRY
381 {
382 HANDLE Thread = NULL;
383
384 _SEH2_TRY
385 {
386 Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
387 ProcessData->PropDispatcher,
388 (PVOID)hClientSection, 0, NULL);
389 if (NULL == Thread)
390 {
391 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
392 }
393 else
394 {
395 DPRINT("ProcessData->PropDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
396 /// WaitForSingleObject(Thread, INFINITE);
397 }
398 }
399 _SEH2_FINALLY
400 {
401 CloseHandle(Thread);
402 }
403 _SEH2_END;
404 }
405 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
406 {
407 Status = _SEH2_GetExceptionCode();
408 DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = %08X\n", Status);
409 }
410 _SEH2_END;
411 }
412
413 Quit:
414 /* We have finished, close the section handle */
415 if (hSection) NtClose(hSection);
416
417 LeaveCriticalSection(&Console->Lock);
418 return;
419 }
420
421
422
423
424 BOOL
425 ChangeFont(PGUI_CONSOLE_DATA GuiData,
426 LPWSTR FaceName, // Points to a WCHAR array of LF_FACESIZE elements.
427 ULONG FontFamily,
428 COORD FontSize,
429 ULONG FontWeight)
430 {
431 HDC hDC;
432 HFONT OldFont, NewFont;
433 TEXTMETRICW Metrics;
434 SIZE CharSize;
435 SIZE_T Length;
436
437 NewFont = CreateFontW(FontSize.Y,
438 0, // FontSize.X,
439 0,
440 TA_BASELINE,
441 FontWeight,
442 FALSE,
443 FALSE,
444 FALSE,
445 OEM_CHARSET,
446 OUT_DEFAULT_PRECIS,
447 CLIP_DEFAULT_PRECIS,
448 NONANTIALIASED_QUALITY,
449 FIXED_PITCH | FontFamily /* FF_DONTCARE */,
450 FaceName);
451 if (NewFont == NULL)
452 {
453 DPRINT1("ChangeFont: CreateFont failed\n");
454 return FALSE;
455 }
456
457 hDC = GetDC(GuiData->hWindow);
458 if (hDC == NULL)
459 {
460 DPRINT1("ChangeFont: GetDC failed\n");
461 DeleteObject(NewFont);
462 return FALSE;
463 }
464
465 OldFont = SelectObject(hDC, NewFont);
466 if (OldFont == NULL)
467 {
468 DPRINT1("ChangeFont: SelectObject failed\n");
469 ReleaseDC(GuiData->hWindow, hDC);
470 DeleteObject(NewFont);
471 return FALSE;
472 }
473
474 if (!GetTextMetricsW(hDC, &Metrics))
475 {
476 DPRINT1("ChangeFont: GetTextMetrics failed\n");
477 SelectObject(hDC, OldFont);
478 ReleaseDC(GuiData->hWindow, hDC);
479 DeleteObject(NewFont);
480 return FALSE;
481 }
482 GuiData->CharWidth = Metrics.tmMaxCharWidth;
483 GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
484
485 /* Measure real char width more precisely if possible. */
486 if (GetTextExtentPoint32W(hDC, L"R", 1, &CharSize))
487 GuiData->CharWidth = CharSize.cx;
488
489 SelectObject(hDC, OldFont);
490 ReleaseDC(GuiData->hWindow, hDC);
491
492 if (GuiData->Font != NULL) DeleteObject(GuiData->Font);
493 GuiData->Font = NewFont;
494
495 Length = min(wcslen(FaceName) + 1, LF_FACESIZE); // wcsnlen
496 wcsncpy(GuiData->GuiInfo.FaceName, FaceName, LF_FACESIZE);
497 GuiData->GuiInfo.FaceName[Length] = L'\0'; // NULL-terminate
498 GuiData->GuiInfo.FontFamily = FontFamily;
499 GuiData->GuiInfo.FontSize = FontSize;
500 GuiData->GuiInfo.FontWeight = FontWeight;
501
502 return TRUE;
503 }
504
505
506
507 VOID
508 GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
509 HANDLE hClientSection,
510 BOOL SaveSettings)
511 {
512 NTSTATUS Status = STATUS_SUCCESS;
513 PCONSOLE Console = GuiData->Console;
514 PCONSOLE_PROCESS_DATA ProcessData;
515 HANDLE hSection = NULL;
516 ULONG ViewSize = 0;
517 PCONSOLE_PROPS pConInfo = NULL;
518 PCONSOLE_INFO ConInfo = NULL;
519 PTERMINAL_INFO TermInfo = NULL;
520 PGUI_CONSOLE_INFO GuiInfo = NULL;
521
522 if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
523
524 /* Get the console leader process, our client */
525 ProcessData = ConSrvGetConsoleLeaderProcess(Console);
526
527 /* Duplicate the section handle for ourselves */
528 Status = NtDuplicateObject(ProcessData->Process->ProcessHandle,
529 hClientSection,
530 NtCurrentProcess(),
531 &hSection,
532 0, 0, DUPLICATE_SAME_ACCESS);
533 if (!NT_SUCCESS(Status))
534 {
535 DPRINT1("Error when mapping client handle, Status = %lu\n", Status);
536 goto Quit;
537 }
538
539 /* Get a view of the shared section */
540 Status = NtMapViewOfSection(hSection,
541 NtCurrentProcess(),
542 (PVOID*)&pConInfo,
543 0,
544 0,
545 NULL,
546 &ViewSize,
547 ViewUnmap,
548 0,
549 PAGE_READWRITE);
550 if (!NT_SUCCESS(Status))
551 {
552 DPRINT1("Error when mapping view of file, Status = %lu\n", Status);
553 goto Quit;
554 }
555
556 _SEH2_TRY
557 {
558 /* Check that the section is well-sized */
559 if ( (ViewSize < sizeof(CONSOLE_PROPS)) ||
560 (pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) ||
561 (ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) )
562 {
563 DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n");
564 Status = STATUS_INVALID_VIEW_SIZE;
565 _SEH2_YIELD(goto Quit);
566 }
567
568 // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
569
570 /* Retrieve terminal informations */
571 ConInfo = &pConInfo->ci;
572 TermInfo = &pConInfo->TerminalInfo;
573 GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo);
574
575 /*
576 * If we don't set the default parameters,
577 * apply them, otherwise just save them.
578 */
579 if (pConInfo->ShowDefaultParams == FALSE)
580 {
581 /* Set the console informations */
582 ConSrvApplyUserSettings(Console, ConInfo);
583
584 /* Set the terminal informations */
585
586 // memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO));
587
588 /* Change the font */
589 ChangeFont(GuiData,
590 GuiInfo->FaceName,
591 GuiInfo->FontFamily,
592 GuiInfo->FontSize,
593 GuiInfo->FontWeight);
594 // HACK, needed because changing font may change the size of the window
595 /**/TermResizeTerminal(Console);/**/
596
597 /* Move the window to the user's values */
598 GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition;
599 GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin;
600 GuiConsoleMoveWindow(GuiData);
601
602 InvalidateRect(GuiData->hWindow, NULL, TRUE);
603
604 /*
605 * Apply full-screen mode.
606 */
607 if (GuiInfo->FullScreen != GuiData->GuiInfo.FullScreen)
608 {
609 SwitchFullScreen(GuiData, GuiInfo->FullScreen);
610 }
611 }
612
613 /*
614 * Save settings if needed
615 */
616 // FIXME: Do it in the console properties applet ??
617 if (SaveSettings)
618 {
619 DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess);
620 ConSrvWriteUserSettings(ConInfo, ProcessId);
621 GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId);
622 }
623
624 Status = STATUS_SUCCESS;
625 }
626 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
627 {
628 Status = _SEH2_GetExceptionCode();
629 DPRINT1("GuiApplyUserSettings - Caught an exception, Status = %08X\n", Status);
630 }
631 _SEH2_END;
632
633 Quit:
634 /* Finally, close the section and return */
635 if (hSection)
636 {
637 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo);
638 NtClose(hSection);
639 }
640
641 LeaveCriticalSection(&Console->Lock);
642 return;
643 }
644
645 /*
646 * Function for dealing with the undocumented message and structure used by
647 * Windows' console.dll for setting console info.
648 * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c
649 * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf
650 * for more information.
651 */
652 VOID
653 GuiApplyWindowsConsoleSettings(PGUI_CONSOLE_DATA GuiData,
654 HANDLE hClientSection)
655 {
656 NTSTATUS Status = STATUS_SUCCESS;
657 PCONSOLE Console = GuiData->Console;
658 PCONSOLE_PROCESS_DATA ProcessData;
659 HANDLE hSection = NULL;
660 ULONG ViewSize = 0;
661 PCONSOLE_STATE_INFO pConInfo = NULL;
662 CONSOLE_INFO ConInfo;
663 GUI_CONSOLE_INFO GuiInfo;
664 SIZE_T Length;
665
666 if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
667
668 /* Get the console leader process, our client */
669 ProcessData = ConSrvGetConsoleLeaderProcess(Console);
670
671 /* Duplicate the section handle for ourselves */
672 Status = NtDuplicateObject(ProcessData->Process->ProcessHandle,
673 hClientSection,
674 NtCurrentProcess(),
675 &hSection,
676 0, 0, DUPLICATE_SAME_ACCESS);
677 if (!NT_SUCCESS(Status))
678 {
679 DPRINT1("Error when mapping client handle, Status = %lu\n", Status);
680 goto Quit;
681 }
682
683 /* Get a view of the shared section */
684 Status = NtMapViewOfSection(hSection,
685 NtCurrentProcess(),
686 (PVOID*)&pConInfo,
687 0,
688 0,
689 NULL,
690 &ViewSize,
691 ViewUnmap,
692 0,
693 PAGE_READWRITE);
694 if (!NT_SUCCESS(Status))
695 {
696 DPRINT1("Error when mapping view of file, Status = %lu\n", Status);
697 goto Quit;
698 }
699
700 _SEH2_TRY
701 {
702 /* Check that the section is well-sized */
703 if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) ||
704 (pConInfo->cbSize != sizeof(CONSOLE_STATE_INFO)) )
705 {
706 DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n");
707 Status = STATUS_INVALID_VIEW_SIZE;
708 _SEH2_YIELD(goto Quit);
709 }
710
711 // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
712
713 /* Retrieve terminal informations */
714
715 // Console information
716 ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize;
717 ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers;
718 ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup;
719 ConInfo.QuickEdit = !!pConInfo->QuickEdit;
720 ConInfo.InsertMode = !!pConInfo->InsertMode;
721 ConInfo.ScreenBufferSize = pConInfo->ScreenBufferSize;
722 ConInfo.ConsoleSize = pConInfo->WindowSize;
723 ConInfo.CursorSize = pConInfo->CursorSize;
724 ConInfo.ScreenAttrib = pConInfo->ScreenColors;
725 ConInfo.PopupAttrib = pConInfo->PopupColors;
726 memcpy(&ConInfo.Colors, pConInfo->ColorTable, sizeof(ConInfo.Colors));
727 ConInfo.CodePage = pConInfo->CodePage;
728 /**ConInfo.ConsoleTitle[MAX_PATH + 1] = pConInfo->ConsoleTitle; // FIXME: memcpy**/
729 #if 0
730 /* Title of the console, original one corresponding to the one set by the console leader */
731 Length = min(sizeof(pConInfo->ConsoleTitle) / sizeof(pConInfo->ConsoleTitle[0]) - 1,
732 Console->OriginalTitle.Length / sizeof(WCHAR));
733 wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length);
734 #endif
735 // ULONG ConInfo.InputBufferSize = pConInfo->
736 // BOOLEAN ConInfo.CursorBlinkOn = pConInfo->
737 // BOOLEAN ConInfo.ForceCursorOff = pConInfo->
738
739
740 // Terminal information
741 Length = min(wcslen(pConInfo->FaceName) + 1, LF_FACESIZE); // wcsnlen
742 wcsncpy(GuiInfo.FaceName, pConInfo->FaceName, LF_FACESIZE);
743 GuiInfo.FaceName[Length] = L'\0';
744
745 GuiInfo.FontFamily = pConInfo->FontFamily;
746 GuiInfo.FontSize = pConInfo->FontSize;
747 GuiInfo.FontWeight = pConInfo->FontWeight;
748 GuiInfo.FullScreen = !!pConInfo->FullScreen;
749 GuiInfo.AutoPosition = !!pConInfo->AutoPosition;
750 GuiInfo.WindowOrigin = pConInfo->WindowPosition;
751 // WORD GuiInfo.ShowWindow = pConInfo->
752
753
754
755 /*
756 * If we don't set the default parameters,
757 * apply them, otherwise just save them.
758 */
759 #if 0
760 if (pConInfo->ShowDefaultParams == FALSE)
761 #endif
762 {
763 /* Set the console informations */
764 ConSrvApplyUserSettings(Console, &ConInfo);
765
766 /* Set the terminal informations */
767
768 // memcpy(&GuiData->GuiInfo, &GuiInfo, sizeof(GUI_CONSOLE_INFO));
769
770 /* Change the font */
771 ChangeFont(GuiData,
772 GuiInfo.FaceName,
773 GuiInfo.FontFamily,
774 GuiInfo.FontSize,
775 GuiInfo.FontWeight);
776 // HACK, needed because changing font may change the size of the window
777 /**/TermResizeTerminal(Console);/**/
778
779 /* Move the window to the user's values */
780 GuiData->GuiInfo.AutoPosition = GuiInfo.AutoPosition;
781 GuiData->GuiInfo.WindowOrigin = GuiInfo.WindowOrigin;
782 GuiConsoleMoveWindow(GuiData);
783
784 InvalidateRect(GuiData->hWindow, NULL, TRUE);
785
786 /*
787 * Apply full-screen mode.
788 */
789 if (GuiInfo.FullScreen != GuiData->GuiInfo.FullScreen)
790 {
791 SwitchFullScreen(GuiData, GuiInfo.FullScreen);
792 }
793 }
794
795 #if 0
796 /*
797 * Save settings if needed
798 */
799 // FIXME: Do it in the console properties applet ??
800 if (SaveSettings)
801 {
802 DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess);
803 ConSrvWriteUserSettings(&ConInfo, ProcessId);
804 GuiConsoleWriteUserSettings(&GuiInfo, ConInfo.ConsoleTitle, ProcessId);
805 }
806 #endif
807
808 Status = STATUS_SUCCESS;
809 }
810 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
811 {
812 Status = _SEH2_GetExceptionCode();
813 DPRINT1("GuiApplyUserSettings - Caught an exception, Status = %08X\n", Status);
814 }
815 _SEH2_END;
816
817 Quit:
818 /* Finally, close the section and return */
819 if (hSection)
820 {
821 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo);
822 NtClose(hSection);
823 }
824
825 LeaveCriticalSection(&Console->Lock);
826 return;
827 }
828
829 /* EOF */