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)
10 /* INCLUDES *******************************************************************/
13 #include "include/conio.h"
14 #include "include/settings.h"
15 #include "guisettings.h"
21 VOID
GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData
);
22 VOID
SwitchFullScreen(PGUI_CONSOLE_DATA GuiData
, BOOL FullScreen
);
24 /* FUNCTIONS ******************************************************************/
27 GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo
,
28 IN LPCWSTR ConsoleTitle
,
31 /*****************************************************
32 * Adapted from ConSrvReadUserSettings in settings.c *
33 *****************************************************/
37 DWORD dwNumSubKeys
= 0;
40 WCHAR szValueName
[MAX_PATH
];
42 WCHAR szValue
[LF_FACESIZE
] = L
"\0";
46 if (!ConSrvOpenUserSettings(ProcessId
,
51 DPRINT("ConSrvOpenUserSettings failed\n");
55 if (RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
56 &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
58 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
63 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
65 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
67 dwValue
= sizeof(Value
);
68 dwValueName
= MAX_PATH
; // sizeof(szValueName)/sizeof(szValueName[0])
70 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
75 * Retry in case of string value
77 dwValue
= sizeof(szValue
);
78 dwValueName
= MAX_PATH
; // sizeof(szValueName)/sizeof(szValueName[0])
79 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
88 if (!wcscmp(szValueName
, L
"FaceName"))
90 SIZE_T Length
= min(wcslen(szValue
) + 1, LF_FACESIZE
); // wcsnlen
91 wcsncpy(TermInfo
->FaceName
, szValue
, LF_FACESIZE
);
92 TermInfo
->FaceName
[Length
] = L
'\0';
95 else if (!wcscmp(szValueName
, L
"FontFamily"))
97 TermInfo
->FontFamily
= Value
;
100 else if (!wcscmp(szValueName
, L
"FontSize"))
102 TermInfo
->FontSize
= Value
;
105 else if (!wcscmp(szValueName
, L
"FontWeight"))
107 TermInfo
->FontWeight
= Value
;
110 else if (!wcscmp(szValueName
, L
"FullScreen"))
112 TermInfo
->FullScreen
= Value
;
115 else if (!wcscmp(szValueName
, L
"WindowPosition"))
117 TermInfo
->AutoPosition
= FALSE
;
118 TermInfo
->WindowOrigin
.x
= LOWORD(Value
);
119 TermInfo
->WindowOrigin
.y
= HIWORD(Value
);
129 GuiConsoleWriteUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo
,
130 IN LPCWSTR ConsoleTitle
,
133 /******************************************************
134 * Adapted from ConSrvWriteUserSettings in settings.c *
135 ******************************************************/
137 BOOL GlobalSettings
= (ConsoleTitle
[0] == L
'\0');
141 #define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
143 if (GlobalSettings || (!GlobalSettings && (*(Setting) != (DefaultValue)))) \
145 RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
149 RegDeleteValue(hKey, (SettingName)); \
153 if (!ConSrvOpenUserSettings(ProcessId
,
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 SetConsoleSetting(L
"FontSize", REG_DWORD
, sizeof(DWORD
), &TermInfo
->FontSize
, 0);
164 SetConsoleSetting(L
"FontWeight", REG_DWORD
, sizeof(DWORD
), &TermInfo
->FontWeight
, FW_DONTCARE
);
166 Storage
= TermInfo
->FullScreen
;
167 SetConsoleSetting(L
"FullScreen", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
169 if (TermInfo
->AutoPosition
== FALSE
)
171 Storage
= MAKELONG(TermInfo
->WindowOrigin
.x
, TermInfo
->WindowOrigin
.y
);
172 RegSetValueExW(hKey
, L
"WindowPosition", 0, REG_DWORD
, (PBYTE
)&Storage
, sizeof(DWORD
));
176 RegDeleteValue(hKey
, L
"WindowPosition");
184 GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo
,
187 /*******************************************************
188 * Adapted from ConSrvGetDefaultSettings in settings.c *
189 *******************************************************/
191 if (TermInfo
== NULL
) return;
194 * 1. Load the default values
196 // wcsncpy(TermInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
197 // TermInfo->FontSize = MAKELONG(12, 8); // 0x0008000C; // font is 8x12
198 // TermInfo->FontSize = MAKELONG(16, 16); // font is 16x16
199 // TermInfo->FontWeight = FW_NORMAL;
201 wcsncpy(TermInfo
->FaceName
, L
"Fixedsys", LF_FACESIZE
); // HACK: !!
202 // TermInfo->FaceName[0] = L'\0';
203 TermInfo
->FontFamily
= FF_DONTCARE
;
204 TermInfo
->FontSize
= 0;
205 TermInfo
->FontWeight
= FW_DONTCARE
;
206 TermInfo
->UseRasterFonts
= TRUE
;
208 TermInfo
->FullScreen
= FALSE
;
209 TermInfo
->ShowWindow
= SW_SHOWNORMAL
;
210 TermInfo
->AutoPosition
= TRUE
;
211 TermInfo
->WindowOrigin
.x
= 0;
212 TermInfo
->WindowOrigin
.y
= 0;
215 * 2. Overwrite them with the ones stored in HKCU\Console.
216 * If the HKCU\Console key doesn't exist, create it
217 * and store the default values inside.
219 if (!GuiConsoleReadUserSettings(TermInfo
, L
"", ProcessId
))
221 GuiConsoleWriteUserSettings(TermInfo
, L
"", ProcessId
);
226 GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData
,
230 PCONSOLE Console
= GuiData
->Console
;
231 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= GuiData
->ActiveBuffer
;
232 PCONSOLE_PROCESS_DATA ProcessData
;
233 HANDLE hSection
= NULL
, hClientSection
= NULL
;
234 LARGE_INTEGER SectionSize
;
237 PCONSOLE_PROPS pSharedInfo
= NULL
;
238 PGUI_CONSOLE_INFO GuiInfo
= NULL
;
240 DPRINT("GuiConsoleShowConsoleProperties entered\n");
243 * Create a memory section to share with the applet, and map it.
245 /* Holds data for console.dll + console info + terminal-specific info */
246 SectionSize
.QuadPart
= sizeof(CONSOLE_PROPS
) + sizeof(GUI_CONSOLE_INFO
);
247 Status
= NtCreateSection(&hSection
,
254 if (!NT_SUCCESS(Status
))
256 DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status
);
260 Status
= NtMapViewOfSection(hSection
,
262 (PVOID
*)&pSharedInfo
,
270 if (!NT_SUCCESS(Status
))
272 DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status
);
279 * Setup the shared console properties structure.
283 pSharedInfo
->hConsoleWindow
= GuiData
->hWindow
;
284 pSharedInfo
->ShowDefaultParams
= Defaults
;
287 * We fill-in the fields only if we display
288 * our properties, not the default ones.
292 /* Console information */
293 pSharedInfo
->ci
.HistoryBufferSize
= Console
->HistoryBufferSize
;
294 pSharedInfo
->ci
.NumberOfHistoryBuffers
= Console
->NumberOfHistoryBuffers
;
295 pSharedInfo
->ci
.HistoryNoDup
= Console
->HistoryNoDup
;
296 pSharedInfo
->ci
.QuickEdit
= Console
->QuickEdit
;
297 pSharedInfo
->ci
.InsertMode
= Console
->InsertMode
;
298 pSharedInfo
->ci
.InputBufferSize
= 0;
299 pSharedInfo
->ci
.ScreenBufferSize
= ActiveBuffer
->ScreenBufferSize
;
300 pSharedInfo
->ci
.ConsoleSize
= ActiveBuffer
->ViewSize
;
301 pSharedInfo
->ci
.CursorBlinkOn
;
302 pSharedInfo
->ci
.ForceCursorOff
;
303 pSharedInfo
->ci
.CursorSize
= ActiveBuffer
->CursorInfo
.dwSize
;
304 if (GetType(ActiveBuffer
) == TEXTMODE_BUFFER
)
306 PTEXTMODE_SCREEN_BUFFER Buffer
= (PTEXTMODE_SCREEN_BUFFER
)ActiveBuffer
;
308 pSharedInfo
->ci
.ScreenAttrib
= Buffer
->ScreenDefaultAttrib
;
309 pSharedInfo
->ci
.PopupAttrib
= Buffer
->PopupDefaultAttrib
;
311 else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
313 // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer;
314 DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n");
316 // FIXME: Gather defaults from the registry ?
317 pSharedInfo
->ci
.ScreenAttrib
= DEFAULT_SCREEN_ATTRIB
;
318 pSharedInfo
->ci
.PopupAttrib
= DEFAULT_POPUP_ATTRIB
;
320 pSharedInfo
->ci
.CodePage
;
322 /* GUI Information */
323 pSharedInfo
->TerminalInfo
.Size
= sizeof(GUI_CONSOLE_INFO
);
324 GuiInfo
= pSharedInfo
->TerminalInfo
.TermInfo
= (PGUI_CONSOLE_INFO
)(pSharedInfo
+ 1);
325 Length
= min(wcslen(GuiData
->GuiInfo
.FaceName
) + 1, LF_FACESIZE
); // wcsnlen
326 wcsncpy(GuiInfo
->FaceName
, GuiData
->GuiInfo
.FaceName
, LF_FACESIZE
);
327 GuiInfo
->FaceName
[Length
] = L
'\0';
328 GuiInfo
->FontFamily
= GuiData
->GuiInfo
.FontFamily
;
329 GuiInfo
->FontSize
= GuiData
->GuiInfo
.FontSize
;
330 GuiInfo
->FontWeight
= GuiData
->GuiInfo
.FontWeight
;
331 GuiInfo
->UseRasterFonts
= GuiData
->GuiInfo
.UseRasterFonts
;
332 GuiInfo
->FullScreen
= GuiData
->GuiInfo
.FullScreen
;
333 /// GuiInfo->WindowPosition = GuiData->GuiInfo.WindowPosition;
334 GuiInfo
->AutoPosition
= GuiData
->GuiInfo
.AutoPosition
;
335 GuiInfo
->WindowOrigin
= GuiData
->GuiInfo
.WindowOrigin
;
337 pSharedInfo
->TerminalInfo
.TermInfo
= (PVOID
)((ULONG_PTR
)GuiInfo
- (ULONG_PTR
)pSharedInfo
);
340 memcpy(pSharedInfo
->ci
.Colors
, Console
->Colors
, sizeof(Console
->Colors
));
342 /* Title of the console, original one corresponding to the one set by the console leader */
343 Length
= min(sizeof(pSharedInfo
->ci
.ConsoleTitle
) / sizeof(pSharedInfo
->ci
.ConsoleTitle
[0]) - 1,
344 Console
->OriginalTitle
.Length
/ sizeof(WCHAR
));
345 wcsncpy(pSharedInfo
->ci
.ConsoleTitle
, Console
->OriginalTitle
.Buffer
, Length
);
350 // FIXME: Load the default parameters from the registry.
353 /* Null-terminate the title */
354 pSharedInfo
->ci
.ConsoleTitle
[Length
] = L
'\0';
358 NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo
);
360 /* Get the console leader process, our client */
361 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Blink
,
362 CONSOLE_PROCESS_DATA
,
365 /* Duplicate the section handle for the client */
366 Status
= NtDuplicateObject(NtCurrentProcess(),
368 ProcessData
->Process
->ProcessHandle
,
370 0, 0, DUPLICATE_SAME_ACCESS
);
371 if (!NT_SUCCESS(Status
))
373 DPRINT1("Error: Impossible to duplicate section handle for client ; Status = %lu\n", Status
);
377 /* Start the properties dialog */
378 if (ProcessData
->PropDispatcher
)
382 HANDLE Thread
= NULL
;
386 Thread
= CreateRemoteThread(ProcessData
->Process
->ProcessHandle
, NULL
, 0,
387 ProcessData
->PropDispatcher
,
388 (PVOID
)hClientSection
, 0, NULL
);
391 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
395 DPRINT("ProcessData->PropDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData
->Process
->ClientId
.UniqueProcess
, ProcessData
->Process
);
396 /// WaitForSingleObject(Thread, INFINITE);
405 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
407 Status
= _SEH2_GetExceptionCode();
408 DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = %08X\n", Status
);
414 /* We have finished, close the section handle */
420 GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData
,
421 HANDLE hClientSection
,
424 NTSTATUS Status
= STATUS_SUCCESS
;
425 PCONSOLE Console
= GuiData
->Console
;
426 PCONSOLE_PROCESS_DATA ProcessData
;
427 HANDLE hSection
= NULL
;
429 PCONSOLE_PROPS pConInfo
= NULL
;
430 PCONSOLE_INFO ConInfo
= NULL
;
431 PTERMINAL_INFO TermInfo
= NULL
;
432 PGUI_CONSOLE_INFO GuiInfo
= NULL
;
434 /* Get the console leader process, our client */
435 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Blink
,
436 CONSOLE_PROCESS_DATA
,
439 /* Duplicate the section handle for ourselves */
440 Status
= NtDuplicateObject(ProcessData
->Process
->ProcessHandle
,
444 0, 0, DUPLICATE_SAME_ACCESS
);
445 if (!NT_SUCCESS(Status
))
447 DPRINT1("Error when mapping client handle, Status = %lu\n", Status
);
451 /* Get a view of the shared section */
452 Status
= NtMapViewOfSection(hSection
,
462 if (!NT_SUCCESS(Status
))
464 DPRINT1("Error when mapping view of file, Status = %lu\n", Status
);
471 /* Check that the section is well-sized */
472 if ( (ViewSize
< sizeof(CONSOLE_PROPS
)) ||
473 (pConInfo
->TerminalInfo
.Size
!= sizeof(GUI_CONSOLE_INFO
)) ||
474 (ViewSize
< sizeof(CONSOLE_PROPS
) + pConInfo
->TerminalInfo
.Size
) )
476 DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n");
477 Status
= STATUS_INVALID_VIEW_SIZE
;
478 _SEH2_YIELD(goto Quit
);
481 // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
483 /* Retrieve terminal informations */
484 ConInfo
= &pConInfo
->ci
;
485 TermInfo
= &pConInfo
->TerminalInfo
;
486 GuiInfo
= TermInfo
->TermInfo
= (PVOID
)((ULONG_PTR
)pConInfo
+ (ULONG_PTR
)TermInfo
->TermInfo
);
489 * If we don't set the default parameters,
490 * apply them, otherwise just save them.
492 if (pConInfo
->ShowDefaultParams
== FALSE
)
494 /* Set the console informations */
495 ConSrvApplyUserSettings(Console
, ConInfo
);
497 /* Set the terminal informations */
499 // memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO));
501 /* Move the window to the user's values */
502 GuiData
->GuiInfo
.AutoPosition
= GuiInfo
->AutoPosition
;
503 GuiData
->GuiInfo
.WindowOrigin
= GuiInfo
->WindowOrigin
;
504 GuiConsoleMoveWindow(GuiData
);
506 InvalidateRect(GuiData
->hWindow
, NULL
, TRUE
);
509 * Apply full-screen mode.
511 if (GuiInfo
->FullScreen
!= GuiData
->GuiInfo
.FullScreen
)
513 SwitchFullScreen(GuiData
, GuiInfo
->FullScreen
);
518 * Save settings if needed
520 // FIXME: Do it in the console properties applet ??
523 DWORD ProcessId
= HandleToUlong(ProcessData
->Process
->ClientId
.UniqueProcess
);
524 ConSrvWriteUserSettings(ConInfo
, ProcessId
);
525 GuiConsoleWriteUserSettings(GuiInfo
, ConInfo
->ConsoleTitle
, ProcessId
);
528 Status
= STATUS_SUCCESS
;
530 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
532 Status
= _SEH2_GetExceptionCode();
533 DPRINT1("GuiApplyUserSettings - Caught an exception, Status = %08X\n", Status
);
538 /* Finally, close the section and return */
539 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo
);