2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/concfg/settings.c
5 * PURPOSE: Console settings management
6 * PROGRAMMERS: Johannes Anderwald
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *******************************************************************/
14 // /* Undocumented user definitions */
15 // #include <undocuser.h>
22 /* GLOBALS ********************************************************************/
24 /* Default cursor size -- see conio_winsrv.h */
25 // #define SMALL_SIZE 25
26 #define CSR_DEFAULT_CURSOR_SIZE 25
28 /* Default attributes -- see conio.h */
29 #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
30 #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \
31 BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
34 * Default 16-color palette for foreground and background
35 * (corresponding flags in comments).
37 static const COLORREF s_Colors
[16] =
39 RGB(0, 0, 0), // (Black)
40 RGB(0, 0, 128), // BLUE
41 RGB(0, 128, 0), // GREEN
42 RGB(0, 128, 128), // BLUE | GREEN
43 RGB(128, 0, 0), // RED
44 RGB(128, 0, 128), // BLUE | RED
45 RGB(128, 128, 0), // GREEN | RED
46 RGB(192, 192, 192), // BLUE | GREEN | RED
48 RGB(128, 128, 128), // (Grey) INTENSITY
49 RGB(0, 0, 255), // BLUE | INTENSITY
50 RGB(0, 255, 0), // GREEN | INTENSITY
51 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
52 RGB(255, 0, 0), // RED | INTENSITY
53 RGB(255, 0, 255), // BLUE | RED | INTENSITY
54 RGB(255, 255, 0), // GREEN | RED | INTENSITY
55 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
59 /* FUNCTIONS ******************************************************************/
63 OUT LPWSTR DestString
,
64 IN LPCWSTR ConsoleName
,
67 #define PATH_SEPARATOR L'\\'
71 if ( DestString
== NULL
|| ConsoleName
== NULL
||
72 *ConsoleName
== L
'\0' || MaxStrLen
== 0 )
77 wLength
= GetSystemWindowsDirectoryW(DestString
, MaxStrLen
);
78 if ((wLength
> 0) && (_wcsnicmp(ConsoleName
, DestString
, wLength
) == 0))
80 StringCchCopyW(DestString
, MaxStrLen
, L
"%SystemRoot%");
81 StringCchCatW(DestString
, MaxStrLen
, ConsoleName
+ wLength
);
85 StringCchCopyW(DestString
, MaxStrLen
, ConsoleName
);
88 /* Replace path separators (backslashes) by underscores */
89 while ((DestString
= wcschr(DestString
, PATH_SEPARATOR
))) *DestString
= L
'_';
93 ConCfgOpenUserSettings(
94 IN LPCWSTR ConsoleTitle
,
99 BOOLEAN Success
= TRUE
;
101 WCHAR szBuffer
[MAX_PATH
] = L
"Console\\";
102 WCHAR szBuffer2
[MAX_PATH
] = L
"";
103 HKEY hKey
; // CurrentUserKeyHandle
106 * Console properties are stored under the HKCU\Console\* key.
108 * We use the original console title as the subkey name for storing
109 * console properties. We need to distinguish whether we were launched
110 * via the console application directly or via a shortcut.
112 * If the title of the console corresponds to a path (more precisely,
113 * if the title is of the form: C:\ReactOS\<some_path>\<some_app.exe>),
114 * then use the corresponding unexpanded path and with the backslashes
115 * replaced by underscores, to make the registry happy,
116 * i.e. %SystemRoot%_<some_path>_<some_app.exe>
119 /* Open the per-user registry key where the console properties are saved */
120 Status
= RtlOpenCurrentUser(/*samDesired*/MAXIMUM_ALLOWED
, (PHANDLE
)&/*CurrentUserKeyHandle*/hKey
);
121 if (!NT_SUCCESS(Status
))
123 DPRINT1("RtlOpenCurrentUser failed, Status = 0x%08lx\n", Status
);
124 SetLastError(RtlNtStatusToDosError(Status
));
129 * Try to open properties via the console title:
130 * to make the registry happy, replace all the
131 * backslashes by underscores.
133 TranslateConsoleName(szBuffer2
, ConsoleTitle
, ARRAYSIZE(szBuffer2
));
135 /* Create the registry path */
136 StringCchCatW(szBuffer
, MAX_PATH
- wcslen(szBuffer
) - 1, szBuffer2
);
138 /* Create or open the registry key */
142 Success
= (RegCreateKeyExW(hKey
,
145 REG_OPTION_NON_VOLATILE
,
149 NULL
) == ERROR_SUCCESS
);
154 Success
= (RegOpenKeyExW(hKey
,
158 phSubKey
) == ERROR_SUCCESS
);
161 /* Close the parent key and return success or not */
167 ConCfgReadUserSettings(
168 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
169 IN BOOLEAN DefaultSettings
)
171 BOOLEAN Success
= FALSE
;
173 DWORD dwNumSubKeys
= 0;
175 DWORD dwColorIndex
= 0;
177 WCHAR szValueName
[MAX_PATH
];
179 WCHAR szValue
[LF_FACESIZE
] = L
"";
183 if (!ConCfgOpenUserSettings(DefaultSettings
? L
"" : ConsoleInfo
->ConsoleTitle
,
184 &hKey
, KEY_READ
, FALSE
))
186 DPRINT("ConCfgOpenUserSettings failed\n");
190 if (RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
191 &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
193 DPRINT("ConCfgReadUserSettings: RegQueryInfoKeyW failed\n");
198 DPRINT("ConCfgReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
200 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
202 dwValue
= sizeof(Value
);
203 dwValueName
= ARRAYSIZE(szValueName
);
205 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
207 if (dwType
== REG_SZ
)
210 * Retry in case of string value
212 dwValue
= sizeof(szValue
);
213 dwValueName
= ARRAYSIZE(szValueName
);
214 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
223 if (!wcsncmp(szValueName
, L
"ColorTable", wcslen(L
"ColorTable")))
226 swscanf(szValueName
, L
"ColorTable%2d", &dwColorIndex
);
227 if (dwColorIndex
< ARRAYSIZE(ConsoleInfo
->ColorTable
))
229 ConsoleInfo
->ColorTable
[dwColorIndex
] = Value
;
233 if (!wcscmp(szValueName
, L
"CodePage"))
235 if (IsValidCodePage(Value
))
236 ConsoleInfo
->CodePage
= Value
;
239 else if (!wcscmp(szValueName
, L
"FaceName"))
241 StringCchCopyNW(ConsoleInfo
->FaceName
, ARRAYSIZE(ConsoleInfo
->FaceName
),
242 szValue
, ARRAYSIZE(szValue
));
245 else if (!wcscmp(szValueName
, L
"FontFamily"))
247 ConsoleInfo
->FontFamily
= Value
;
250 else if (!wcscmp(szValueName
, L
"FontSize"))
252 ConsoleInfo
->FontSize
.X
= LOWORD(Value
); // Width
253 ConsoleInfo
->FontSize
.Y
= HIWORD(Value
); // Height
256 else if (!wcscmp(szValueName
, L
"FontWeight"))
258 ConsoleInfo
->FontWeight
= Value
;
261 else if (!wcscmp(szValueName
, L
"HistoryBufferSize"))
263 ConsoleInfo
->HistoryBufferSize
= Value
;
266 else if (!wcscmp(szValueName
, L
"NumberOfHistoryBuffers"))
268 ConsoleInfo
->NumberOfHistoryBuffers
= Value
;
271 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
273 ConsoleInfo
->HistoryNoDup
= !!Value
;
276 else if (!wcscmp(szValueName
, L
"QuickEdit"))
278 ConsoleInfo
->QuickEdit
= !!Value
;
281 else if (!wcscmp(szValueName
, L
"InsertMode"))
283 ConsoleInfo
->InsertMode
= !!Value
;
286 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
288 ConsoleInfo
->ScreenBufferSize
.X
= LOWORD(Value
);
289 ConsoleInfo
->ScreenBufferSize
.Y
= HIWORD(Value
);
292 else if (!wcscmp(szValueName
, L
"FullScreen"))
294 ConsoleInfo
->FullScreen
= Value
;
297 else if (!wcscmp(szValueName
, L
"WindowPosition"))
299 ConsoleInfo
->AutoPosition
= FALSE
;
300 ConsoleInfo
->WindowPosition
.x
= LOWORD(Value
);
301 ConsoleInfo
->WindowPosition
.y
= HIWORD(Value
);
304 else if (!wcscmp(szValueName
, L
"WindowSize"))
306 ConsoleInfo
->WindowSize
.X
= LOWORD(Value
);
307 ConsoleInfo
->WindowSize
.Y
= HIWORD(Value
);
310 else if (!wcscmp(szValueName
, L
"CursorSize"))
312 ConsoleInfo
->CursorSize
= min(max(Value
, 0), 100);
315 else if (!wcscmp(szValueName
, L
"ScreenColors"))
317 ConsoleInfo
->ScreenAttributes
= (USHORT
)Value
;
320 else if (!wcscmp(szValueName
, L
"PopupColors"))
322 ConsoleInfo
->PopupAttributes
= (USHORT
)Value
;
332 ConCfgWriteUserSettings(
333 IN PCONSOLE_STATE_INFO ConsoleInfo
,
334 IN BOOLEAN DefaultSettings
)
339 #define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
341 if (DefaultSettings || (!DefaultSettings && (*(Setting) != (DefaultValue)))) \
343 RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
347 RegDeleteValueW(hKey, (SettingName)); \
351 WCHAR szValueName
[15];
354 if (!ConCfgOpenUserSettings(DefaultSettings
? L
"" : ConsoleInfo
->ConsoleTitle
,
355 &hKey
, KEY_WRITE
, TRUE
))
360 for (i
= 0; i
< ARRAYSIZE(ConsoleInfo
->ColorTable
); ++i
)
363 * Write only the new value if we are saving the global settings
364 * or we are saving settings for a particular console, which differs
365 * from the default ones.
367 swprintf(szValueName
, L
"ColorTable%02u", i
);
368 SetConsoleSetting(szValueName
, REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->ColorTable
[i
], s_Colors
[i
]);
371 SetConsoleSetting(L
"CodePage", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->CodePage
, CP_ACP
/* CP_OEMCP */);
372 SetConsoleSetting(L
"FaceName", REG_SZ
, (wcslen(ConsoleInfo
->FaceName
) + 1) * sizeof(WCHAR
), ConsoleInfo
->FaceName
, UNICODE_NULL
); // wcsnlen
373 SetConsoleSetting(L
"FontFamily", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->FontFamily
, FF_DONTCARE
);
375 Storage
= MAKELONG(ConsoleInfo
->FontSize
.X
, ConsoleInfo
->FontSize
.Y
); // Width, Height
376 SetConsoleSetting(L
"FontSize", REG_DWORD
, sizeof(DWORD
), &Storage
, 0);
378 SetConsoleSetting(L
"FontWeight", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->FontWeight
, FW_DONTCARE
);
380 SetConsoleSetting(L
"HistoryBufferSize", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->HistoryBufferSize
, 50);
381 SetConsoleSetting(L
"NumberOfHistoryBuffers", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->NumberOfHistoryBuffers
, 4);
383 Storage
= ConsoleInfo
->HistoryNoDup
;
384 SetConsoleSetting(L
"HistoryNoDup", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
386 Storage
= ConsoleInfo
->QuickEdit
;
387 SetConsoleSetting(L
"QuickEdit", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
389 Storage
= ConsoleInfo
->InsertMode
;
390 SetConsoleSetting(L
"InsertMode", REG_DWORD
, sizeof(DWORD
), &Storage
, TRUE
);
392 Storage
= MAKELONG(ConsoleInfo
->ScreenBufferSize
.X
, ConsoleInfo
->ScreenBufferSize
.Y
);
393 SetConsoleSetting(L
"ScreenBufferSize", REG_DWORD
, sizeof(DWORD
), &Storage
, MAKELONG(80, 300));
395 Storage
= ConsoleInfo
->FullScreen
;
396 SetConsoleSetting(L
"FullScreen", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
398 if (ConsoleInfo
->AutoPosition
== FALSE
)
400 Storage
= MAKELONG(ConsoleInfo
->WindowPosition
.x
, ConsoleInfo
->WindowPosition
.y
);
401 RegSetValueExW(hKey
, L
"WindowPosition", 0, REG_DWORD
, (PBYTE
)&Storage
, sizeof(DWORD
));
405 RegDeleteValueW(hKey
, L
"WindowPosition");
408 Storage
= MAKELONG(ConsoleInfo
->WindowSize
.X
, ConsoleInfo
->WindowSize
.Y
);
409 SetConsoleSetting(L
"WindowSize", REG_DWORD
, sizeof(DWORD
), &Storage
, MAKELONG(80, 25));
411 SetConsoleSetting(L
"CursorSize", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->CursorSize
, CSR_DEFAULT_CURSOR_SIZE
);
413 Storage
= ConsoleInfo
->ScreenAttributes
;
414 SetConsoleSetting(L
"ScreenColors", REG_DWORD
, sizeof(DWORD
), &Storage
, DEFAULT_SCREEN_ATTRIB
);
416 Storage
= ConsoleInfo
->PopupAttributes
;
417 SetConsoleSetting(L
"PopupColors", REG_DWORD
, sizeof(DWORD
), &Storage
, DEFAULT_POPUP_ATTRIB
);
424 ConCfgInitDefaultSettings(
425 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
)
427 if (ConsoleInfo
== NULL
) return;
429 // ASSERT(ConsoleInfo->cbSize >= sizeof(CONSOLE_STATE_INFO));
431 /// HKCU,"Console","LoadConIme",0x00010003,1
433 // wcsncpy(ConsoleInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
434 // ConsoleInfo->FontSize = MAKELONG(8, 12); // 0x000C0008; // font is 8x12
436 StringCchCopyW(ConsoleInfo
->FaceName
, ARRAYSIZE(ConsoleInfo
->FaceName
), L
"VGA"); // HACK: !!
437 // ConsoleInfo->FaceName[0] = UNICODE_NULL;
438 // ConsoleInfo->FontSize.X = 8;
439 // ConsoleInfo->FontSize.Y = 12;
440 ConsoleInfo
->FontSize
.X
= 0; // HACK: !!
441 ConsoleInfo
->FontSize
.Y
= 16; // HACK: !!
442 ConsoleInfo
->FontFamily
= FF_DONTCARE
;
443 ConsoleInfo
->FontWeight
= FW_NORMAL
; // FW_DONTCARE;
445 /* Initialize the default properties */
447 // #define DEFAULT_HISTORY_COMMANDS_NUMBER 50
448 // #define DEFAULT_HISTORY_BUFFERS_NUMBER 4
449 ConsoleInfo
->HistoryBufferSize
= 50;
450 ConsoleInfo
->NumberOfHistoryBuffers
= 4;
451 ConsoleInfo
->HistoryNoDup
= FALSE
;
453 ConsoleInfo
->QuickEdit
= FALSE
;
454 ConsoleInfo
->InsertMode
= TRUE
;
455 // ConsoleInfo->InputBufferSize = 0;
457 // Rule: ScreenBufferSize >= WindowSize
458 ConsoleInfo
->ScreenBufferSize
.X
= 80;
459 ConsoleInfo
->ScreenBufferSize
.Y
= 300;
460 ConsoleInfo
->WindowSize
.X
= 80;
461 ConsoleInfo
->WindowSize
.Y
= 25;
463 ConsoleInfo
->FullScreen
= FALSE
;
464 ConsoleInfo
->AutoPosition
= TRUE
;
465 ConsoleInfo
->WindowPosition
.x
= 0;
466 ConsoleInfo
->WindowPosition
.y
= 0;
468 ConsoleInfo
->CursorSize
= CSR_DEFAULT_CURSOR_SIZE
;
470 ConsoleInfo
->ScreenAttributes
= DEFAULT_SCREEN_ATTRIB
;
471 ConsoleInfo
->PopupAttributes
= DEFAULT_POPUP_ATTRIB
;
473 RtlCopyMemory(ConsoleInfo
->ColorTable
, s_Colors
, sizeof(s_Colors
));
475 ConsoleInfo
->CodePage
= GetOEMCP();
479 ConCfgGetDefaultSettings(
480 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
)
482 if (ConsoleInfo
== NULL
) return;
485 * 1. Load the default values
487 ConCfgInitDefaultSettings(ConsoleInfo
);
490 * 2. Overwrite them with the ones stored in HKCU\Console.
491 * If the HKCU\Console key doesn't exist, create it
492 * and store the default values inside.
494 if (!ConCfgReadUserSettings(ConsoleInfo
, TRUE
))
495 ConCfgWriteUserSettings(ConsoleInfo
, TRUE
);