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
43 /* GLOBALS ********************************************************************/
45 /* Default cursor size -- see conio_winsrv.h */
46 #define CSR_DEFAULT_CURSOR_SIZE 25
48 /* Default attributes -- see conio.h */
49 #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
50 #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \
51 BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
54 * Default 16-color palette for foreground and background
55 * (corresponding flags in comments).
57 static const COLORREF s_Colors
[16] =
59 RGB(0, 0, 0), // (Black)
60 RGB(0, 0, 128), // BLUE
61 RGB(0, 128, 0), // GREEN
62 RGB(0, 128, 128), // BLUE | GREEN
63 RGB(128, 0, 0), // RED
64 RGB(128, 0, 128), // BLUE | RED
65 RGB(128, 128, 0), // GREEN | RED
66 RGB(192, 192, 192), // BLUE | GREEN | RED
68 RGB(128, 128, 128), // (Grey) INTENSITY
69 RGB(0, 0, 255), // BLUE | INTENSITY
70 RGB(0, 255, 0), // GREEN | INTENSITY
71 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
72 RGB(255, 0, 0), // RED | INTENSITY
73 RGB(255, 0, 255), // BLUE | RED | INTENSITY
74 RGB(255, 255, 0), // GREEN | RED | INTENSITY
75 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
77 // /* Default attributes */
78 // #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
79 // #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | /
80 // BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
82 // #define CSR_DEFAULT_CURSOR_SIZE 25
85 /* FUNCTIONS ******************************************************************/
88 TranslateConsoleName(OUT LPWSTR DestString
,
89 IN LPCWSTR ConsoleName
,
92 #define PATH_SEPARATOR L'\\'
96 if ( DestString
== NULL
|| ConsoleName
== NULL
||
97 *ConsoleName
== L
'\0' || MaxStrLen
== 0 )
102 wLength
= GetWindowsDirectoryW(DestString
, MaxStrLen
);
103 if ((wLength
> 0) && (_wcsnicmp(ConsoleName
, DestString
, wLength
) == 0))
105 StringCchCopyW(DestString
, MaxStrLen
, L
"%SystemRoot%");
106 StringCchCatW(DestString
, MaxStrLen
, ConsoleName
+ wLength
);
110 StringCchCopyW(DestString
, MaxStrLen
, ConsoleName
);
113 /* Replace path separators (backslashes) by underscores */
114 while ((DestString
= wcschr(DestString
, PATH_SEPARATOR
))) *DestString
= L
'_';
118 ConCfgOpenUserSettings(LPCWSTR ConsoleTitle
,
123 BOOLEAN RetVal
= TRUE
;
125 WCHAR szBuffer
[MAX_PATH
] = L
"Console\\";
126 WCHAR szBuffer2
[MAX_PATH
] = L
"";
127 HKEY hKey
; // CurrentUserKeyHandle
130 * Console properties are stored under the HKCU\Console\* key.
132 * We use the original console title as the subkey name for storing
133 * console properties. We need to distinguish whether we were launched
134 * via the console application directly or via a shortcut.
136 * If the title of the console corresponds to a path (more precisely,
137 * if the title is of the form: C:\ReactOS\<some_path>\<some_app.exe>),
138 * then use the corresponding unexpanded path and with the backslashes
139 * replaced by underscores, to make the registry happy,
140 * i.e. %SystemRoot%_<some_path>_<some_app.exe>
143 /* Open the per-user registry key where the console properties are saved */
144 Status
= RtlOpenCurrentUser(/*samDesired*/MAXIMUM_ALLOWED
, (PHANDLE
)&/*CurrentUserKeyHandle*/hKey
);
145 if (!NT_SUCCESS(Status
))
147 DPRINT1("RtlOpenCurrentUser failed, Status = 0x%08lx\n", Status
);
148 SetLastError(RtlNtStatusToDosError(Status
));
153 * Try to open properties via the console title:
154 * to make the registry happy, replace all the
155 * backslashes by underscores.
157 TranslateConsoleName(szBuffer2
, ConsoleTitle
, ARRAYSIZE(szBuffer2
));
159 /* Create the registry path */
160 StringCchCatW(szBuffer
, MAX_PATH
- wcslen(szBuffer
) - 1, szBuffer2
);
162 /* Create or open the registry key */
166 RetVal
= (RegCreateKeyExW(hKey
,
169 REG_OPTION_NON_VOLATILE
,
173 NULL
) == ERROR_SUCCESS
);
178 RetVal
= (RegOpenKeyExW(hKey
,
182 hSubKey
) == ERROR_SUCCESS
);
185 /* Close the parent key and return success or not */
191 ConCfgReadUserSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
192 IN BOOLEAN DefaultSettings
)
194 BOOLEAN RetVal
= FALSE
;
196 DWORD dwNumSubKeys
= 0;
198 DWORD dwColorIndex
= 0;
200 WCHAR szValueName
[MAX_PATH
];
202 WCHAR szValue
[LF_FACESIZE
] = L
"";
206 if (!ConCfgOpenUserSettings(DefaultSettings
? L
"" : ConsoleInfo
->ConsoleTitle
,
207 &hKey
, KEY_READ
, FALSE
))
209 DPRINT("ConCfgOpenUserSettings failed\n");
213 if (RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
214 &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
216 DPRINT("ConCfgReadUserSettings: RegQueryInfoKeyW failed\n");
221 DPRINT("ConCfgReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
223 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
225 dwValue
= sizeof(Value
);
226 dwValueName
= ARRAYSIZE(szValueName
);
228 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
230 if (dwType
== REG_SZ
)
233 * Retry in case of string value
235 dwValue
= sizeof(szValue
);
236 dwValueName
= ARRAYSIZE(szValueName
);
237 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
246 if (!wcsncmp(szValueName
, L
"ColorTable", wcslen(L
"ColorTable")))
249 swscanf(szValueName
, L
"ColorTable%2d", &dwColorIndex
);
250 if (dwColorIndex
< ARRAYSIZE(ConsoleInfo
->ColorTable
))
252 ConsoleInfo
->ColorTable
[dwColorIndex
] = Value
;
256 if (!wcscmp(szValueName
, L
"FaceName"))
258 wcsncpy(ConsoleInfo
->FaceName
, szValue
, LF_FACESIZE
);
259 ConsoleInfo
->FaceName
[LF_FACESIZE
- 1] = UNICODE_NULL
;
262 else if (!wcscmp(szValueName
, L
"FontFamily"))
264 ConsoleInfo
->FontFamily
= Value
;
267 else if (!wcscmp(szValueName
, L
"FontSize"))
269 ConsoleInfo
->FontSize
.X
= LOWORD(Value
); // Width
270 ConsoleInfo
->FontSize
.Y
= HIWORD(Value
); // Height
273 else if (!wcscmp(szValueName
, L
"FontWeight"))
275 ConsoleInfo
->FontWeight
= Value
;
278 else if (!wcscmp(szValueName
, L
"HistoryBufferSize"))
280 ConsoleInfo
->HistoryBufferSize
= Value
;
283 else if (!wcscmp(szValueName
, L
"NumberOfHistoryBuffers"))
285 ConsoleInfo
->NumberOfHistoryBuffers
= Value
;
288 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
290 ConsoleInfo
->HistoryNoDup
= !!Value
;
293 else if (!wcscmp(szValueName
, L
"QuickEdit"))
295 ConsoleInfo
->QuickEdit
= !!Value
;
298 else if (!wcscmp(szValueName
, L
"InsertMode"))
300 ConsoleInfo
->InsertMode
= !!Value
;
303 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
305 ConsoleInfo
->ScreenBufferSize
.X
= LOWORD(Value
);
306 ConsoleInfo
->ScreenBufferSize
.Y
= HIWORD(Value
);
309 else if (!wcscmp(szValueName
, L
"FullScreen"))
311 ConsoleInfo
->FullScreen
= Value
;
314 else if (!wcscmp(szValueName
, L
"WindowPosition"))
316 ConsoleInfo
->AutoPosition
= FALSE
;
317 ConsoleInfo
->WindowPosition
.x
= LOWORD(Value
);
318 ConsoleInfo
->WindowPosition
.y
= HIWORD(Value
);
321 else if (!wcscmp(szValueName
, L
"WindowSize"))
323 ConsoleInfo
->WindowSize
.X
= LOWORD(Value
);
324 ConsoleInfo
->WindowSize
.Y
= HIWORD(Value
);
327 else if (!wcscmp(szValueName
, L
"CursorSize"))
329 ConsoleInfo
->CursorSize
= min(max(Value
, 0), 100);
332 else if (!wcscmp(szValueName
, L
"ScreenColors"))
334 ConsoleInfo
->ScreenAttributes
= (USHORT
)Value
;
337 else if (!wcscmp(szValueName
, L
"PopupColors"))
339 ConsoleInfo
->PopupAttributes
= (USHORT
)Value
;
349 ConCfgWriteUserSettings(IN PCONSOLE_STATE_INFO ConsoleInfo
,
350 IN BOOLEAN DefaultSettings
)
355 #define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
357 if (DefaultSettings || (!DefaultSettings && (*(Setting) != (DefaultValue)))) \
359 RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
363 RegDeleteValueW(hKey, (SettingName)); \
367 WCHAR szValueName
[15];
370 if (!ConCfgOpenUserSettings(DefaultSettings
? L
"" : ConsoleInfo
->ConsoleTitle
,
371 &hKey
, KEY_WRITE
, TRUE
))
376 for (i
= 0; i
< ARRAYSIZE(ConsoleInfo
->ColorTable
); ++i
)
379 * Write only the new value if we are saving the global settings
380 * or we are saving settings for a particular console, which differs
381 * from the default ones.
383 swprintf(szValueName
, L
"ColorTable%02u", i
);
384 SetConsoleSetting(szValueName
, REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->ColorTable
[i
], s_Colors
[i
]);
387 SetConsoleSetting(L
"FaceName", REG_SZ
, (wcslen(ConsoleInfo
->FaceName
) + 1) * sizeof(WCHAR
), ConsoleInfo
->FaceName
, UNICODE_NULL
); // wcsnlen
388 SetConsoleSetting(L
"FontFamily", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->FontFamily
, FF_DONTCARE
);
390 Storage
= MAKELONG(ConsoleInfo
->FontSize
.X
, ConsoleInfo
->FontSize
.Y
); // Width, Height
391 SetConsoleSetting(L
"FontSize", REG_DWORD
, sizeof(DWORD
), &Storage
, 0);
393 SetConsoleSetting(L
"FontWeight", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->FontWeight
, FW_DONTCARE
);
395 SetConsoleSetting(L
"HistoryBufferSize", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->HistoryBufferSize
, 50);
396 SetConsoleSetting(L
"NumberOfHistoryBuffers", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->NumberOfHistoryBuffers
, 4);
398 Storage
= ConsoleInfo
->HistoryNoDup
;
399 SetConsoleSetting(L
"HistoryNoDup", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
401 Storage
= ConsoleInfo
->QuickEdit
;
402 SetConsoleSetting(L
"QuickEdit", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
404 Storage
= ConsoleInfo
->InsertMode
;
405 SetConsoleSetting(L
"InsertMode", REG_DWORD
, sizeof(DWORD
), &Storage
, TRUE
);
407 Storage
= MAKELONG(ConsoleInfo
->ScreenBufferSize
.X
, ConsoleInfo
->ScreenBufferSize
.Y
);
408 SetConsoleSetting(L
"ScreenBufferSize", REG_DWORD
, sizeof(DWORD
), &Storage
, MAKELONG(80, 300));
410 Storage
= ConsoleInfo
->FullScreen
;
411 SetConsoleSetting(L
"FullScreen", REG_DWORD
, sizeof(DWORD
), &Storage
, FALSE
);
413 if (ConsoleInfo
->AutoPosition
== FALSE
)
415 Storage
= MAKELONG(ConsoleInfo
->WindowPosition
.x
, ConsoleInfo
->WindowPosition
.y
);
416 RegSetValueExW(hKey
, L
"WindowPosition", 0, REG_DWORD
, (PBYTE
)&Storage
, sizeof(DWORD
));
420 RegDeleteValueW(hKey
, L
"WindowPosition");
423 Storage
= MAKELONG(ConsoleInfo
->WindowSize
.X
, ConsoleInfo
->WindowSize
.Y
);
424 SetConsoleSetting(L
"WindowSize", REG_DWORD
, sizeof(DWORD
), &Storage
, MAKELONG(80, 25));
426 SetConsoleSetting(L
"CursorSize", REG_DWORD
, sizeof(DWORD
), &ConsoleInfo
->CursorSize
, CSR_DEFAULT_CURSOR_SIZE
);
428 Storage
= ConsoleInfo
->ScreenAttributes
;
429 SetConsoleSetting(L
"ScreenColors", REG_DWORD
, sizeof(DWORD
), &Storage
, DEFAULT_SCREEN_ATTRIB
);
431 Storage
= ConsoleInfo
->PopupAttributes
;
432 SetConsoleSetting(L
"PopupColors", REG_DWORD
, sizeof(DWORD
), &Storage
, DEFAULT_POPUP_ATTRIB
);
439 ConCfgInitDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
)
441 if (ConsoleInfo
== NULL
) return;
443 // ASSERT(ConsoleInfo->cbSize >= sizeof(CONSOLE_STATE_INFO));
445 /// HKCU,"Console","LoadConIme",0x00010003,1
447 // wcsncpy(ConsoleInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
448 // ConsoleInfo->FontSize = MAKELONG(8, 12); // 0x000C0008; // font is 8x12
449 // ConsoleInfo->FontSize = MAKELONG(16, 16); // font is 16x16
451 wcsncpy(ConsoleInfo
->FaceName
, L
"VGA", LF_FACESIZE
); // HACK: !!
452 // ConsoleInfo->FaceName[0] = UNICODE_NULL;
453 ConsoleInfo
->FontFamily
= FF_DONTCARE
;
454 ConsoleInfo
->FontSize
.X
= 0;
455 ConsoleInfo
->FontSize
.Y
= 0;
456 ConsoleInfo
->FontWeight
= FW_NORMAL
; // HACK: !!
457 // ConsoleInfo->FontWeight = FW_DONTCARE;
459 /* Initialize the default properties */
461 // #define DEFAULT_HISTORY_COMMANDS_NUMBER 50
462 // #define DEFAULT_HISTORY_BUFFERS_NUMBER 4
463 ConsoleInfo
->HistoryBufferSize
= 50;
464 ConsoleInfo
->NumberOfHistoryBuffers
= 4;
465 ConsoleInfo
->HistoryNoDup
= FALSE
;
467 ConsoleInfo
->QuickEdit
= FALSE
;
468 ConsoleInfo
->InsertMode
= TRUE
;
469 // ConsoleInfo->InputBufferSize = 0;
471 // Rule: ScreenBufferSize >= WindowSize
472 ConsoleInfo
->ScreenBufferSize
.X
= 80;
473 ConsoleInfo
->ScreenBufferSize
.Y
= 300;
474 ConsoleInfo
->WindowSize
.X
= 80;
475 ConsoleInfo
->WindowSize
.Y
= 25;
477 ConsoleInfo
->FullScreen
= FALSE
;
478 ConsoleInfo
->AutoPosition
= TRUE
;
479 ConsoleInfo
->WindowPosition
.x
= 0;
480 ConsoleInfo
->WindowPosition
.y
= 0;
482 ConsoleInfo
->CursorSize
= CSR_DEFAULT_CURSOR_SIZE
; // #define SMALL_SIZE 25
484 ConsoleInfo
->ScreenAttributes
= DEFAULT_SCREEN_ATTRIB
;
485 ConsoleInfo
->PopupAttributes
= DEFAULT_POPUP_ATTRIB
;
487 RtlCopyMemory(ConsoleInfo
->ColorTable
, s_Colors
, sizeof(s_Colors
));
489 ConsoleInfo
->CodePage
= 0;
493 ConCfgGetDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
)
495 if (ConsoleInfo
== NULL
) return;
498 * 1. Load the default values
500 ConCfgInitDefaultSettings(ConsoleInfo
);
503 * 2. Overwrite them with the ones stored in HKCU\Console.
504 * If the HKCU\Console key doesn't exist, create it
505 * and store the default values inside.
507 if (!ConCfgReadUserSettings(ConsoleInfo
, TRUE
))
508 ConCfgWriteUserSettings(ConsoleInfo
, TRUE
);