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 *******************************************************************/
12 /* PSDK/NDK Headers */
14 #define WIN32_NO_STATUS
16 #define COM_NO_WINDOWS_H
20 #include <wingdi.h> // For LF_FACESIZE
24 // #include <winuser.h>
27 // /* Undocumented user definitions */
28 // #include <undocuser.h>
30 #define NTOS_MODE_USER
31 // #include <ndk/cmfuncs.h>
32 // #include <ndk/exfuncs.h>
33 #include <ndk/obfuncs.h>
34 // #include <ndk/psfuncs.h>
35 #include <ndk/rtlfuncs.h>
39 #include <stdio.h> // for swprintf
45 /* GLOBALS ********************************************************************/
47 /* Default cursor size -- see conio_winsrv.h */
48 #define CSR_DEFAULT_CURSOR_SIZE 25
50 /* Default attributes -- see conio.h */
51 #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
52 #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \
53 BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
56 * Default 16-color palette for foreground and background
57 * (corresponding flags in comments).
59 static const COLORREF s_Colors
[16] =
61 RGB(0, 0, 0), // (Black)
62 RGB(0, 0, 128), // BLUE
63 RGB(0, 128, 0), // GREEN
64 RGB(0, 128, 128), // BLUE | GREEN
65 RGB(128, 0, 0), // RED
66 RGB(128, 0, 128), // BLUE | RED
67 RGB(128, 128, 0), // GREEN | RED
68 RGB(192, 192, 192), // BLUE | GREEN | RED
70 RGB(128, 128, 128), // (Grey) INTENSITY
71 RGB(0, 0, 255), // BLUE | INTENSITY
72 RGB(0, 255, 0), // GREEN | INTENSITY
73 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
74 RGB(255, 0, 0), // RED | INTENSITY
75 RGB(255, 0, 255), // BLUE | RED | INTENSITY
76 RGB(255, 255, 0), // GREEN | RED | INTENSITY
77 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
79 // /* Default attributes */
80 // #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
81 // #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | /
82 // BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
84 // #define CSR_DEFAULT_CURSOR_SIZE 25
87 /* FUNCTIONS ******************************************************************/
90 TranslateConsoleName(OUT LPWSTR DestString
,
91 IN LPCWSTR ConsoleName
,
94 #define PATH_SEPARATOR L'\\'
98 if ( DestString
== NULL
|| ConsoleName
== NULL
||
99 *ConsoleName
== L
'\0' || MaxStrLen
== 0 )
104 wLength
= GetSystemWindowsDirectoryW(DestString
, MaxStrLen
);
105 if ((wLength
> 0) && (_wcsnicmp(ConsoleName
, DestString
, wLength
) == 0))
107 StringCchCopyW(DestString
, MaxStrLen
, L
"%SystemRoot%");
108 StringCchCatW(DestString
, MaxStrLen
, ConsoleName
+ wLength
);
112 StringCchCopyW(DestString
, MaxStrLen
, ConsoleName
);
115 /* Replace path separators (backslashes) by underscores */
116 while ((DestString
= wcschr(DestString
, PATH_SEPARATOR
))) *DestString
= L
'_';
120 ConCfgOpenUserSettings(LPCWSTR ConsoleTitle
,
125 BOOLEAN Success
= TRUE
;
127 WCHAR szBuffer
[MAX_PATH
] = L
"Console\\";
128 WCHAR szBuffer2
[MAX_PATH
] = L
"";
129 HKEY hKey
; // CurrentUserKeyHandle
132 * Console properties are stored under the HKCU\Console\* key.
134 * We use the original console title as the subkey name for storing
135 * console properties. We need to distinguish whether we were launched
136 * via the console application directly or via a shortcut.
138 * If the title of the console corresponds to a path (more precisely,
139 * if the title is of the form: C:\ReactOS\<some_path>\<some_app.exe>),
140 * then use the corresponding unexpanded path and with the backslashes
141 * replaced by underscores, to make the registry happy,
142 * i.e. %SystemRoot%_<some_path>_<some_app.exe>
145 /* Open the per-user registry key where the console properties are saved */
146 Status
= RtlOpenCurrentUser(/*samDesired*/MAXIMUM_ALLOWED
, (PHANDLE
)&/*CurrentUserKeyHandle*/hKey
);
147 if (!NT_SUCCESS(Status
))
149 DPRINT1("RtlOpenCurrentUser failed, Status = 0x%08lx\n", Status
);
150 SetLastError(RtlNtStatusToDosError(Status
));
155 * Try to open properties via the console title:
156 * to make the registry happy, replace all the
157 * backslashes by underscores.
159 TranslateConsoleName(szBuffer2
, ConsoleTitle
, ARRAYSIZE(szBuffer2
));
161 /* Create the registry path */
162 StringCchCatW(szBuffer
, MAX_PATH
- wcslen(szBuffer
) - 1, szBuffer2
);
164 /* Create or open the registry key */
168 Success
= (RegCreateKeyExW(hKey
,
171 REG_OPTION_NON_VOLATILE
,
175 NULL
) == ERROR_SUCCESS
);
180 Success
= (RegOpenKeyExW(hKey
,
184 hSubKey
) == ERROR_SUCCESS
);
187 /* Close the parent key and return success or not */
193 ConCfgReadUserSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
194 IN BOOLEAN DefaultSettings
)
196 BOOLEAN Success
= FALSE
;
198 DWORD dwNumSubKeys
= 0;
200 DWORD dwColorIndex
= 0;
202 WCHAR szValueName
[MAX_PATH
];
204 WCHAR szValue
[LF_FACESIZE
] = L
"";
208 if (!ConCfgOpenUserSettings(DefaultSettings
? L
"" : ConsoleInfo
->ConsoleTitle
,
209 &hKey
, KEY_READ
, FALSE
))
211 DPRINT("ConCfgOpenUserSettings failed\n");
215 if (RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
216 &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
218 DPRINT("ConCfgReadUserSettings: RegQueryInfoKeyW failed\n");
223 DPRINT("ConCfgReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
225 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
227 dwValue
= sizeof(Value
);
228 dwValueName
= ARRAYSIZE(szValueName
);
230 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
232 if (dwType
== REG_SZ
)
235 * Retry in case of string value
237 dwValue
= sizeof(szValue
);
238 dwValueName
= ARRAYSIZE(szValueName
);
239 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
248 if (!wcsncmp(szValueName
, L
"ColorTable", wcslen(L
"ColorTable")))
251 swscanf(szValueName
, L
"ColorTable%2d", &dwColorIndex
);
252 if (dwColorIndex
< ARRAYSIZE(ConsoleInfo
->ColorTable
))
254 ConsoleInfo
->ColorTable
[dwColorIndex
] = Value
;
258 if (!wcscmp(szValueName
, L
"CodePage"))
260 if (IsValidCodePage(Value
))
261 ConsoleInfo
->CodePage
= Value
;
264 else if (!wcscmp(szValueName
, L
"FaceName"))
266 wcsncpy(ConsoleInfo
->FaceName
, szValue
, LF_FACESIZE
);
267 ConsoleInfo
->FaceName
[LF_FACESIZE
- 1] = UNICODE_NULL
;
270 else if (!wcscmp(szValueName
, L
"FontFamily"))
272 ConsoleInfo
->FontFamily
= Value
;
275 else if (!wcscmp(szValueName
, L
"FontSize"))
277 ConsoleInfo
->FontSize
.X
= LOWORD(Value
); // Width
278 ConsoleInfo
->FontSize
.Y
= HIWORD(Value
); // Height
281 else if (!wcscmp(szValueName
, L
"FontWeight"))
283 ConsoleInfo
->FontWeight
= Value
;
286 else if (!wcscmp(szValueName
, L
"HistoryBufferSize"))
288 ConsoleInfo
->HistoryBufferSize
= Value
;
291 else if (!wcscmp(szValueName
, L
"NumberOfHistoryBuffers"))
293 ConsoleInfo
->NumberOfHistoryBuffers
= Value
;
296 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
298 ConsoleInfo
->HistoryNoDup
= !!Value
;
301 else if (!wcscmp(szValueName
, L
"QuickEdit"))
303 ConsoleInfo
->QuickEdit
= !!Value
;
306 else if (!wcscmp(szValueName
, L
"InsertMode"))
308 ConsoleInfo
->InsertMode
= !!Value
;
311 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
313 ConsoleInfo
->ScreenBufferSize
.X
= LOWORD(Value
);
314 ConsoleInfo
->ScreenBufferSize
.Y
= HIWORD(Value
);
317 else if (!wcscmp(szValueName
, L
"FullScreen"))
319 ConsoleInfo
->FullScreen
= Value
;
322 else if (!wcscmp(szValueName
, L
"WindowPosition"))
324 ConsoleInfo
->AutoPosition
= FALSE
;
325 ConsoleInfo
->WindowPosition
.x
= LOWORD(Value
);
326 ConsoleInfo
->WindowPosition
.y
= HIWORD(Value
);
329 else if (!wcscmp(szValueName
, L
"WindowSize"))
331 ConsoleInfo
->WindowSize
.X
= LOWORD(Value
);
332 ConsoleInfo
->WindowSize
.Y
= HIWORD(Value
);
335 else if (!wcscmp(szValueName
, L
"CursorSize"))
337 ConsoleInfo
->CursorSize
= min(max(Value
, 0), 100);
340 else if (!wcscmp(szValueName
, L
"ScreenColors"))
342 ConsoleInfo
->ScreenAttributes
= (USHORT
)Value
;
345 else if (!wcscmp(szValueName
, L
"PopupColors"))
347 ConsoleInfo
->PopupAttributes
= (USHORT
)Value
;
357 ConCfgWriteUserSettings(IN PCONSOLE_STATE_INFO ConsoleInfo
,
358 IN BOOLEAN DefaultSettings
)
363 #define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
365 if (DefaultSettings || (!DefaultSettings && (*(Setting) != (DefaultValue)))) \
367 RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
371 RegDeleteValueW(hKey, (SettingName)); \
375 WCHAR szValueName
[15];
378 if (!ConCfgOpenUserSettings(DefaultSettings
? L
"" : ConsoleInfo
->ConsoleTitle
,
379 &hKey
, KEY_WRITE
, TRUE
))
384 for (i
= 0; i
< ARRAYSIZE(ConsoleInfo
->ColorTable
); ++i
)
387 * Write only the new value if we are saving the global settings
388 * or we are saving settings for a particular console, which differs
389 * from the default ones.
391 swprintf(szValueName
, L
"ColorTable%02u", i
);
392 SetConsoleSetting(szValueName
, REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->ColorTable
[i
], s_Colors
[i
]);
395 SetConsoleSetting(L
"CodePage", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->CodePage
, CP_ACP
/* CP_OEMCP */);
396 SetConsoleSetting(L
"FaceName", REG_SZ
, (wcslen(ConsoleInfo
->FaceName
) + 1) * sizeof(WCHAR
), ConsoleInfo
->FaceName
, UNICODE_NULL
); // wcsnlen
397 SetConsoleSetting(L
"FontFamily", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->FontFamily
, FF_DONTCARE
);
399 Storage
= MAKELONG(ConsoleInfo
->FontSize
.X
, ConsoleInfo
->FontSize
.Y
); // Width, Height
400 SetConsoleSetting(L
"FontSize", REG_DWORD
, sizeof(DWORD
), &Storage
, 0);
402 SetConsoleSetting(L
"FontWeight", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->FontWeight
, FW_DONTCARE
);
404 SetConsoleSetting(L
"HistoryBufferSize", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->HistoryBufferSize
, 50);
405 SetConsoleSetting(L
"NumberOfHistoryBuffers", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->NumberOfHistoryBuffers
, 4);
407 Storage
= ConsoleInfo
->HistoryNoDup
;
408 SetConsoleSetting(L
"HistoryNoDup", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
410 Storage
= ConsoleInfo
->QuickEdit
;
411 SetConsoleSetting(L
"QuickEdit", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
413 Storage
= ConsoleInfo
->InsertMode
;
414 SetConsoleSetting(L
"InsertMode", REG_DWORD
, sizeof(DWORD
), &Storage
, TRUE
);
416 Storage
= MAKELONG(ConsoleInfo
->ScreenBufferSize
.X
, ConsoleInfo
->ScreenBufferSize
.Y
);
417 SetConsoleSetting(L
"ScreenBufferSize", REG_DWORD
, sizeof(DWORD
), &Storage
, MAKELONG(80, 300));
419 Storage
= ConsoleInfo
->FullScreen
;
420 SetConsoleSetting(L
"FullScreen", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
422 if (ConsoleInfo
->AutoPosition
== FALSE
)
424 Storage
= MAKELONG(ConsoleInfo
->WindowPosition
.x
, ConsoleInfo
->WindowPosition
.y
);
425 RegSetValueExW(hKey
, L
"WindowPosition", 0, REG_DWORD
, (PBYTE
)&Storage
, sizeof(DWORD
));
429 RegDeleteValueW(hKey
, L
"WindowPosition");
432 Storage
= MAKELONG(ConsoleInfo
->WindowSize
.X
, ConsoleInfo
->WindowSize
.Y
);
433 SetConsoleSetting(L
"WindowSize", REG_DWORD
, sizeof(DWORD
), &Storage
, MAKELONG(80, 25));
435 SetConsoleSetting(L
"CursorSize", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->CursorSize
, CSR_DEFAULT_CURSOR_SIZE
);
437 Storage
= ConsoleInfo
->ScreenAttributes
;
438 SetConsoleSetting(L
"ScreenColors", REG_DWORD
, sizeof(DWORD
), &Storage
, DEFAULT_SCREEN_ATTRIB
);
440 Storage
= ConsoleInfo
->PopupAttributes
;
441 SetConsoleSetting(L
"PopupColors", REG_DWORD
, sizeof(DWORD
), &Storage
, DEFAULT_POPUP_ATTRIB
);
448 ConCfgInitDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
)
450 if (ConsoleInfo
== NULL
) return;
452 // ASSERT(ConsoleInfo->cbSize >= sizeof(CONSOLE_STATE_INFO));
454 /// HKCU,"Console","LoadConIme",0x00010003,1
456 // wcsncpy(ConsoleInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
457 // ConsoleInfo->FontSize = MAKELONG(8, 12); // 0x000C0008; // font is 8x12
458 // ConsoleInfo->FontSize = MAKELONG(16, 16); // font is 16x16
460 wcsncpy(ConsoleInfo
->FaceName
, L
"VGA", LF_FACESIZE
); // HACK: !!
461 // ConsoleInfo->FaceName[0] = UNICODE_NULL;
462 ConsoleInfo
->FontFamily
= FF_DONTCARE
;
463 ConsoleInfo
->FontSize
.X
= 0;
464 ConsoleInfo
->FontSize
.Y
= 0;
465 ConsoleInfo
->FontWeight
= FW_NORMAL
; // HACK: !!
466 // ConsoleInfo->FontWeight = FW_DONTCARE;
468 /* Initialize the default properties */
470 // #define DEFAULT_HISTORY_COMMANDS_NUMBER 50
471 // #define DEFAULT_HISTORY_BUFFERS_NUMBER 4
472 ConsoleInfo
->HistoryBufferSize
= 50;
473 ConsoleInfo
->NumberOfHistoryBuffers
= 4;
474 ConsoleInfo
->HistoryNoDup
= FALSE
;
476 ConsoleInfo
->QuickEdit
= FALSE
;
477 ConsoleInfo
->InsertMode
= TRUE
;
478 // ConsoleInfo->InputBufferSize = 0;
480 // Rule: ScreenBufferSize >= WindowSize
481 ConsoleInfo
->ScreenBufferSize
.X
= 80;
482 ConsoleInfo
->ScreenBufferSize
.Y
= 300;
483 ConsoleInfo
->WindowSize
.X
= 80;
484 ConsoleInfo
->WindowSize
.Y
= 25;
486 ConsoleInfo
->FullScreen
= FALSE
;
487 ConsoleInfo
->AutoPosition
= TRUE
;
488 ConsoleInfo
->WindowPosition
.x
= 0;
489 ConsoleInfo
->WindowPosition
.y
= 0;
491 ConsoleInfo
->CursorSize
= CSR_DEFAULT_CURSOR_SIZE
; // #define SMALL_SIZE 25
493 ConsoleInfo
->ScreenAttributes
= DEFAULT_SCREEN_ATTRIB
;
494 ConsoleInfo
->PopupAttributes
= DEFAULT_POPUP_ATTRIB
;
496 RtlCopyMemory(ConsoleInfo
->ColorTable
, s_Colors
, sizeof(s_Colors
));
498 ConsoleInfo
->CodePage
= GetOEMCP();
502 ConCfgGetDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
)
504 if (ConsoleInfo
== NULL
) return;
507 * 1. Load the default values
509 ConCfgInitDefaultSettings(ConsoleInfo
);
512 * 2. Overwrite them with the ones stored in HKCU\Console.
513 * If the HKCU\Console key doesn't exist, create it
514 * and store the default values inside.
516 if (!ConCfgReadUserSettings(ConsoleInfo
, TRUE
))
517 ConCfgWriteUserSettings(ConsoleInfo
, TRUE
);