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
23 // #include <winuser.h>
26 // /* Undocumented user definitions */
27 // #include <undocuser.h>
29 #define NTOS_MODE_USER
30 // #include <ndk/cmfuncs.h>
31 // #include <ndk/exfuncs.h>
32 #include <ndk/obfuncs.h>
33 // #include <ndk/psfuncs.h>
34 #include <ndk/rtlfuncs.h>
38 #include <stdio.h> // for swprintf
44 /* GLOBALS ********************************************************************/
46 /* Default cursor size -- see conio_winsrv.h */
47 #define CSR_DEFAULT_CURSOR_SIZE 25
49 /* Default attributes -- see conio.h */
50 #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
51 #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \
52 BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
55 * Default 16-color palette for foreground and background
56 * (corresponding flags in comments).
58 static const COLORREF s_Colors
[16] =
60 RGB(0, 0, 0), // (Black)
61 RGB(0, 0, 128), // BLUE
62 RGB(0, 128, 0), // GREEN
63 RGB(0, 128, 128), // BLUE | GREEN
64 RGB(128, 0, 0), // RED
65 RGB(128, 0, 128), // BLUE | RED
66 RGB(128, 128, 0), // GREEN | RED
67 RGB(192, 192, 192), // BLUE | GREEN | RED
69 RGB(128, 128, 128), // (Grey) INTENSITY
70 RGB(0, 0, 255), // BLUE | INTENSITY
71 RGB(0, 255, 0), // GREEN | INTENSITY
72 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
73 RGB(255, 0, 0), // RED | INTENSITY
74 RGB(255, 0, 255), // BLUE | RED | INTENSITY
75 RGB(255, 255, 0), // GREEN | RED | INTENSITY
76 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
78 // /* Default attributes */
79 // #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
80 // #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | /
81 // BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
83 // #define CSR_DEFAULT_CURSOR_SIZE 25
86 /* FUNCTIONS ******************************************************************/
89 TranslateConsoleName(OUT LPWSTR DestString
,
90 IN LPCWSTR ConsoleName
,
93 #define PATH_SEPARATOR L'\\'
97 if ( DestString
== NULL
|| ConsoleName
== NULL
||
98 *ConsoleName
== L
'\0' || MaxStrLen
== 0 )
103 wLength
= GetSystemWindowsDirectoryW(DestString
, MaxStrLen
);
104 if ((wLength
> 0) && (_wcsnicmp(ConsoleName
, DestString
, wLength
) == 0))
106 StringCchCopyW(DestString
, MaxStrLen
, L
"%SystemRoot%");
107 StringCchCatW(DestString
, MaxStrLen
, ConsoleName
+ wLength
);
111 StringCchCopyW(DestString
, MaxStrLen
, ConsoleName
);
114 /* Replace path separators (backslashes) by underscores */
115 while ((DestString
= wcschr(DestString
, PATH_SEPARATOR
))) *DestString
= L
'_';
119 ConCfgOpenUserSettings(LPCWSTR ConsoleTitle
,
124 BOOLEAN RetVal
= TRUE
;
126 WCHAR szBuffer
[MAX_PATH
] = L
"Console\\";
127 WCHAR szBuffer2
[MAX_PATH
] = L
"";
128 HKEY hKey
; // CurrentUserKeyHandle
131 * Console properties are stored under the HKCU\Console\* key.
133 * We use the original console title as the subkey name for storing
134 * console properties. We need to distinguish whether we were launched
135 * via the console application directly or via a shortcut.
137 * If the title of the console corresponds to a path (more precisely,
138 * if the title is of the form: C:\ReactOS\<some_path>\<some_app.exe>),
139 * then use the corresponding unexpanded path and with the backslashes
140 * replaced by underscores, to make the registry happy,
141 * i.e. %SystemRoot%_<some_path>_<some_app.exe>
144 /* Open the per-user registry key where the console properties are saved */
145 Status
= RtlOpenCurrentUser(/*samDesired*/MAXIMUM_ALLOWED
, (PHANDLE
)&/*CurrentUserKeyHandle*/hKey
);
146 if (!NT_SUCCESS(Status
))
148 DPRINT1("RtlOpenCurrentUser failed, Status = 0x%08lx\n", Status
);
149 SetLastError(RtlNtStatusToDosError(Status
));
154 * Try to open properties via the console title:
155 * to make the registry happy, replace all the
156 * backslashes by underscores.
158 TranslateConsoleName(szBuffer2
, ConsoleTitle
, ARRAYSIZE(szBuffer2
));
160 /* Create the registry path */
161 StringCchCatW(szBuffer
, MAX_PATH
- wcslen(szBuffer
) - 1, szBuffer2
);
163 /* Create or open the registry key */
167 RetVal
= (RegCreateKeyExW(hKey
,
170 REG_OPTION_NON_VOLATILE
,
174 NULL
) == ERROR_SUCCESS
);
179 RetVal
= (RegOpenKeyExW(hKey
,
183 hSubKey
) == ERROR_SUCCESS
);
186 /* Close the parent key and return success or not */
192 ConCfgReadUserSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
193 IN BOOLEAN DefaultSettings
)
195 BOOLEAN RetVal
= FALSE
;
197 DWORD dwNumSubKeys
= 0;
199 DWORD dwColorIndex
= 0;
201 WCHAR szValueName
[MAX_PATH
];
203 WCHAR szValue
[LF_FACESIZE
] = L
"";
207 if (!ConCfgOpenUserSettings(DefaultSettings
? L
"" : ConsoleInfo
->ConsoleTitle
,
208 &hKey
, KEY_READ
, FALSE
))
210 DPRINT("ConCfgOpenUserSettings failed\n");
214 if (RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
215 &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
217 DPRINT("ConCfgReadUserSettings: RegQueryInfoKeyW failed\n");
222 DPRINT("ConCfgReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
224 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
226 dwValue
= sizeof(Value
);
227 dwValueName
= ARRAYSIZE(szValueName
);
229 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
231 if (dwType
== REG_SZ
)
234 * Retry in case of string value
236 dwValue
= sizeof(szValue
);
237 dwValueName
= ARRAYSIZE(szValueName
);
238 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
247 if (!wcsncmp(szValueName
, L
"ColorTable", wcslen(L
"ColorTable")))
250 swscanf(szValueName
, L
"ColorTable%2d", &dwColorIndex
);
251 if (dwColorIndex
< ARRAYSIZE(ConsoleInfo
->ColorTable
))
253 ConsoleInfo
->ColorTable
[dwColorIndex
] = Value
;
257 if (!wcscmp(szValueName
, L
"FaceName"))
259 wcsncpy(ConsoleInfo
->FaceName
, szValue
, LF_FACESIZE
);
260 ConsoleInfo
->FaceName
[LF_FACESIZE
- 1] = UNICODE_NULL
;
263 else if (!wcscmp(szValueName
, L
"FontFamily"))
265 ConsoleInfo
->FontFamily
= Value
;
268 else if (!wcscmp(szValueName
, L
"FontSize"))
270 ConsoleInfo
->FontSize
.X
= LOWORD(Value
); // Width
271 ConsoleInfo
->FontSize
.Y
= HIWORD(Value
); // Height
274 else if (!wcscmp(szValueName
, L
"FontWeight"))
276 ConsoleInfo
->FontWeight
= Value
;
279 else if (!wcscmp(szValueName
, L
"HistoryBufferSize"))
281 ConsoleInfo
->HistoryBufferSize
= Value
;
284 else if (!wcscmp(szValueName
, L
"NumberOfHistoryBuffers"))
286 ConsoleInfo
->NumberOfHistoryBuffers
= Value
;
289 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
291 ConsoleInfo
->HistoryNoDup
= !!Value
;
294 else if (!wcscmp(szValueName
, L
"QuickEdit"))
296 ConsoleInfo
->QuickEdit
= !!Value
;
299 else if (!wcscmp(szValueName
, L
"InsertMode"))
301 ConsoleInfo
->InsertMode
= !!Value
;
304 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
306 ConsoleInfo
->ScreenBufferSize
.X
= LOWORD(Value
);
307 ConsoleInfo
->ScreenBufferSize
.Y
= HIWORD(Value
);
310 else if (!wcscmp(szValueName
, L
"FullScreen"))
312 ConsoleInfo
->FullScreen
= Value
;
315 else if (!wcscmp(szValueName
, L
"WindowPosition"))
317 ConsoleInfo
->AutoPosition
= FALSE
;
318 ConsoleInfo
->WindowPosition
.x
= LOWORD(Value
);
319 ConsoleInfo
->WindowPosition
.y
= HIWORD(Value
);
322 else if (!wcscmp(szValueName
, L
"WindowSize"))
324 ConsoleInfo
->WindowSize
.X
= LOWORD(Value
);
325 ConsoleInfo
->WindowSize
.Y
= HIWORD(Value
);
328 else if (!wcscmp(szValueName
, L
"CursorSize"))
330 ConsoleInfo
->CursorSize
= min(max(Value
, 0), 100);
333 else if (!wcscmp(szValueName
, L
"ScreenColors"))
335 ConsoleInfo
->ScreenAttributes
= (USHORT
)Value
;
338 else if (!wcscmp(szValueName
, L
"PopupColors"))
340 ConsoleInfo
->PopupAttributes
= (USHORT
)Value
;
350 ConCfgWriteUserSettings(IN PCONSOLE_STATE_INFO ConsoleInfo
,
351 IN BOOLEAN DefaultSettings
)
356 #define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
358 if (DefaultSettings || (!DefaultSettings && (*(Setting) != (DefaultValue)))) \
360 RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
364 RegDeleteValueW(hKey, (SettingName)); \
368 WCHAR szValueName
[15];
371 if (!ConCfgOpenUserSettings(DefaultSettings
? L
"" : ConsoleInfo
->ConsoleTitle
,
372 &hKey
, KEY_WRITE
, TRUE
))
377 for (i
= 0; i
< ARRAYSIZE(ConsoleInfo
->ColorTable
); ++i
)
380 * Write only the new value if we are saving the global settings
381 * or we are saving settings for a particular console, which differs
382 * from the default ones.
384 swprintf(szValueName
, L
"ColorTable%02u", i
);
385 SetConsoleSetting(szValueName
, REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->ColorTable
[i
], s_Colors
[i
]);
388 SetConsoleSetting(L
"FaceName", REG_SZ
, (wcslen(ConsoleInfo
->FaceName
) + 1) * sizeof(WCHAR
), ConsoleInfo
->FaceName
, UNICODE_NULL
); // wcsnlen
389 SetConsoleSetting(L
"FontFamily", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->FontFamily
, FF_DONTCARE
);
391 Storage
= MAKELONG(ConsoleInfo
->FontSize
.X
, ConsoleInfo
->FontSize
.Y
); // Width, Height
392 SetConsoleSetting(L
"FontSize", REG_DWORD
, sizeof(DWORD
), &Storage
, 0);
394 SetConsoleSetting(L
"FontWeight", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->FontWeight
, FW_DONTCARE
);
396 SetConsoleSetting(L
"HistoryBufferSize", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->HistoryBufferSize
, 50);
397 SetConsoleSetting(L
"NumberOfHistoryBuffers", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->NumberOfHistoryBuffers
, 4);
399 Storage
= ConsoleInfo
->HistoryNoDup
;
400 SetConsoleSetting(L
"HistoryNoDup", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
402 Storage
= ConsoleInfo
->QuickEdit
;
403 SetConsoleSetting(L
"QuickEdit", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
405 Storage
= ConsoleInfo
->InsertMode
;
406 SetConsoleSetting(L
"InsertMode", REG_DWORD
, sizeof(DWORD
), &Storage
, TRUE
);
408 Storage
= MAKELONG(ConsoleInfo
->ScreenBufferSize
.X
, ConsoleInfo
->ScreenBufferSize
.Y
);
409 SetConsoleSetting(L
"ScreenBufferSize", REG_DWORD
, sizeof(DWORD
), &Storage
, MAKELONG(80, 300));
411 Storage
= ConsoleInfo
->FullScreen
;
412 SetConsoleSetting(L
"FullScreen", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
414 if (ConsoleInfo
->AutoPosition
== FALSE
)
416 Storage
= MAKELONG(ConsoleInfo
->WindowPosition
.x
, ConsoleInfo
->WindowPosition
.y
);
417 RegSetValueExW(hKey
, L
"WindowPosition", 0, REG_DWORD
, (PBYTE
)&Storage
, sizeof(DWORD
));
421 RegDeleteValueW(hKey
, L
"WindowPosition");
424 Storage
= MAKELONG(ConsoleInfo
->WindowSize
.X
, ConsoleInfo
->WindowSize
.Y
);
425 SetConsoleSetting(L
"WindowSize", REG_DWORD
, sizeof(DWORD
), &Storage
, MAKELONG(80, 25));
427 SetConsoleSetting(L
"CursorSize", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->CursorSize
, CSR_DEFAULT_CURSOR_SIZE
);
429 Storage
= ConsoleInfo
->ScreenAttributes
;
430 SetConsoleSetting(L
"ScreenColors", REG_DWORD
, sizeof(DWORD
), &Storage
, DEFAULT_SCREEN_ATTRIB
);
432 Storage
= ConsoleInfo
->PopupAttributes
;
433 SetConsoleSetting(L
"PopupColors", REG_DWORD
, sizeof(DWORD
), &Storage
, DEFAULT_POPUP_ATTRIB
);
440 ConCfgInitDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
)
442 if (ConsoleInfo
== NULL
) return;
444 // ASSERT(ConsoleInfo->cbSize >= sizeof(CONSOLE_STATE_INFO));
446 /// HKCU,"Console","LoadConIme",0x00010003,1
448 // wcsncpy(ConsoleInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
449 // ConsoleInfo->FontSize = MAKELONG(8, 12); // 0x000C0008; // font is 8x12
450 // ConsoleInfo->FontSize = MAKELONG(16, 16); // font is 16x16
452 wcsncpy(ConsoleInfo
->FaceName
, L
"VGA", LF_FACESIZE
); // HACK: !!
453 // ConsoleInfo->FaceName[0] = UNICODE_NULL;
454 ConsoleInfo
->FontFamily
= FF_DONTCARE
;
455 ConsoleInfo
->FontSize
.X
= 0;
456 ConsoleInfo
->FontSize
.Y
= 0;
457 ConsoleInfo
->FontWeight
= FW_NORMAL
; // HACK: !!
458 // ConsoleInfo->FontWeight = FW_DONTCARE;
460 /* Initialize the default properties */
462 // #define DEFAULT_HISTORY_COMMANDS_NUMBER 50
463 // #define DEFAULT_HISTORY_BUFFERS_NUMBER 4
464 ConsoleInfo
->HistoryBufferSize
= 50;
465 ConsoleInfo
->NumberOfHistoryBuffers
= 4;
466 ConsoleInfo
->HistoryNoDup
= FALSE
;
468 ConsoleInfo
->QuickEdit
= FALSE
;
469 ConsoleInfo
->InsertMode
= TRUE
;
470 // ConsoleInfo->InputBufferSize = 0;
472 // Rule: ScreenBufferSize >= WindowSize
473 ConsoleInfo
->ScreenBufferSize
.X
= 80;
474 ConsoleInfo
->ScreenBufferSize
.Y
= 300;
475 ConsoleInfo
->WindowSize
.X
= 80;
476 ConsoleInfo
->WindowSize
.Y
= 25;
478 ConsoleInfo
->FullScreen
= FALSE
;
479 ConsoleInfo
->AutoPosition
= TRUE
;
480 ConsoleInfo
->WindowPosition
.x
= 0;
481 ConsoleInfo
->WindowPosition
.y
= 0;
483 ConsoleInfo
->CursorSize
= CSR_DEFAULT_CURSOR_SIZE
; // #define SMALL_SIZE 25
485 ConsoleInfo
->ScreenAttributes
= DEFAULT_SCREEN_ATTRIB
;
486 ConsoleInfo
->PopupAttributes
= DEFAULT_POPUP_ATTRIB
;
488 RtlCopyMemory(ConsoleInfo
->ColorTable
, s_Colors
, sizeof(s_Colors
));
490 ConsoleInfo
->CodePage
= 0;
494 ConCfgGetDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
)
496 if (ConsoleInfo
== NULL
) return;
499 * 1. Load the default values
501 ConCfgInitDefaultSettings(ConsoleInfo
);
504 * 2. Overwrite them with the ones stored in HKCU\Console.
505 * If the HKCU\Console key doesn't exist, create it
506 * and store the default values inside.
508 if (!ConCfgReadUserSettings(ConsoleInfo
, TRUE
))
509 ConCfgWriteUserSettings(ConsoleInfo
, TRUE
);