980 lines
25 KiB
C
980 lines
25 KiB
C
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
registry.c
|
|
|
|
Abstract:
|
|
|
|
This file contains functions to read and _rite values
|
|
to the registry.
|
|
|
|
Author:
|
|
|
|
Jerry Shea (JerrySh) 30-Sep-1994
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include <shlwapi.h>
|
|
|
|
#define CONSOLE_REGISTRY_CURRENTPAGE (L"CurrentPage")
|
|
extern BOOL g_fAutoComplete;
|
|
extern BOOL g_fSaveAutoCompleteState;
|
|
|
|
|
|
NTSTATUS
|
|
MyRegOpenKey(
|
|
IN HANDLE hKey,
|
|
IN LPWSTR lpSubKey,
|
|
OUT PHANDLE phResult
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING SubKey;
|
|
|
|
//
|
|
// Convert the subkey to a counted Unicode string.
|
|
//
|
|
|
|
RtlInitUnicodeString( &SubKey, lpSubKey );
|
|
|
|
//
|
|
// Initialize the OBJECT_ATTRIBUTES structure and open the key.
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
&Obja,
|
|
&SubKey,
|
|
OBJ_CASE_INSENSITIVE,
|
|
hKey,
|
|
NULL
|
|
);
|
|
|
|
return NtOpenKey(
|
|
phResult,
|
|
KEY_READ,
|
|
&Obja
|
|
);
|
|
}
|
|
|
|
NTSTATUS
|
|
MyRegDeleteKey(
|
|
IN HANDLE hKey,
|
|
IN LPWSTR lpSubKey
|
|
)
|
|
{
|
|
UNICODE_STRING SubKey;
|
|
|
|
//
|
|
// Convert the subkey to a counted Unicode string.
|
|
//
|
|
|
|
RtlInitUnicodeString( &SubKey, lpSubKey );
|
|
|
|
//
|
|
// Delete the subkey
|
|
//
|
|
|
|
return NtDeleteValueKey(
|
|
hKey,
|
|
&SubKey
|
|
);
|
|
}
|
|
|
|
NTSTATUS
|
|
MyRegCreateKey(
|
|
IN HANDLE hKey,
|
|
IN LPWSTR lpSubKey,
|
|
OUT PHANDLE phResult
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING SubKey;
|
|
|
|
//
|
|
// Convert the subkey to a counted Unicode string.
|
|
//
|
|
|
|
RtlInitUnicodeString( &SubKey, lpSubKey );
|
|
|
|
//
|
|
// Initialize the OBJECT_ATTRIBUTES structure and open the key.
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
&Obja,
|
|
&SubKey,
|
|
OBJ_CASE_INSENSITIVE,
|
|
hKey,
|
|
NULL
|
|
);
|
|
|
|
return NtCreateKey(
|
|
phResult,
|
|
KEY_READ | KEY_WRITE,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
NTSTATUS
|
|
MyRegQueryValue(
|
|
IN HANDLE hKey,
|
|
IN LPWSTR lpValueName,
|
|
IN DWORD dwValueLength,
|
|
OUT LPBYTE lpData
|
|
)
|
|
{
|
|
UNICODE_STRING ValueName;
|
|
ULONG BufferLength;
|
|
ULONG ResultLength;
|
|
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Convert the subkey to a counted Unicode string.
|
|
//
|
|
|
|
RtlInitUnicodeString( &ValueName, lpValueName );
|
|
|
|
BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + dwValueLength;
|
|
KeyValueInformation = HeapAlloc(RtlProcessHeap(),0,BufferLength);
|
|
if (KeyValueInformation == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
Status = NtQueryValueKey(
|
|
hKey,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
KeyValueInformation,
|
|
BufferLength,
|
|
&ResultLength
|
|
);
|
|
if (NT_SUCCESS(Status)) {
|
|
ASSERT(KeyValueInformation->DataLength <= dwValueLength);
|
|
RtlCopyMemory(lpData,
|
|
KeyValueInformation->Data,
|
|
KeyValueInformation->DataLength);
|
|
if (KeyValueInformation->Type == REG_SZ) {
|
|
if (KeyValueInformation->DataLength + sizeof(WCHAR) > dwValueLength) {
|
|
KeyValueInformation->DataLength -= sizeof(WCHAR);
|
|
}
|
|
lpData[KeyValueInformation->DataLength++] = 0;
|
|
lpData[KeyValueInformation->DataLength] = 0;
|
|
}
|
|
}
|
|
HeapFree(RtlProcessHeap(),0,KeyValueInformation);
|
|
return Status;
|
|
}
|
|
|
|
|
|
#if defined(FE_SB)
|
|
NTSTATUS
|
|
MyRegEnumValue(
|
|
IN HANDLE hKey,
|
|
IN DWORD dwIndex,
|
|
OUT DWORD dwValueLength,
|
|
OUT LPWSTR lpValueName,
|
|
OUT DWORD dwDataLength,
|
|
OUT LPBYTE lpData
|
|
)
|
|
{
|
|
ULONG BufferLength;
|
|
ULONG ResultLength;
|
|
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Convert the subkey to a counted Unicode string.
|
|
//
|
|
|
|
BufferLength = sizeof(KEY_VALUE_FULL_INFORMATION) + dwValueLength + dwDataLength;
|
|
KeyValueInformation = LocalAlloc(LPTR,BufferLength);
|
|
if (KeyValueInformation == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
Status = NtEnumerateValueKey(
|
|
hKey,
|
|
dwIndex,
|
|
KeyValueFullInformation,
|
|
KeyValueInformation,
|
|
BufferLength,
|
|
&ResultLength
|
|
);
|
|
if (NT_SUCCESS(Status)) {
|
|
ASSERT(KeyValueInformation->NameLength <= dwValueLength);
|
|
RtlMoveMemory(lpValueName,
|
|
KeyValueInformation->Name,
|
|
KeyValueInformation->NameLength);
|
|
lpValueName[ KeyValueInformation->NameLength >> 1 ] = UNICODE_NULL;
|
|
|
|
|
|
ASSERT(KeyValueInformation->DataLength <= dwDataLength);
|
|
RtlMoveMemory(lpData,
|
|
(PBYTE)KeyValueInformation + KeyValueInformation->DataOffset,
|
|
KeyValueInformation->DataLength);
|
|
if (KeyValueInformation->Type == REG_SZ ||
|
|
KeyValueInformation->Type ==REG_MULTI_SZ
|
|
) {
|
|
if (KeyValueInformation->DataLength + sizeof(WCHAR) > dwDataLength) {
|
|
KeyValueInformation->DataLength -= sizeof(WCHAR);
|
|
}
|
|
lpData[KeyValueInformation->DataLength++] = 0;
|
|
lpData[KeyValueInformation->DataLength] = 0;
|
|
}
|
|
}
|
|
LocalFree(KeyValueInformation);
|
|
return Status;
|
|
}
|
|
#endif
|
|
|
|
LPWSTR
|
|
TranslateConsoleTitle(
|
|
LPWSTR ConsoleTitle
|
|
)
|
|
/*++
|
|
|
|
this routine translates path characters into '_' characters because
|
|
the NT registry apis do not allow the creation of keys with
|
|
names that contain path characters. it allocates a buffer that
|
|
must be freed.
|
|
|
|
--*/
|
|
{
|
|
int ConsoleTitleLength, i;
|
|
LPWSTR TranslatedTitle;
|
|
|
|
ConsoleTitleLength = lstrlenW(ConsoleTitle) + 1;
|
|
TranslatedTitle = HeapAlloc(RtlProcessHeap(), 0,
|
|
ConsoleTitleLength * sizeof(WCHAR));
|
|
if (TranslatedTitle == NULL) {
|
|
return NULL;
|
|
}
|
|
for (i = 0; i < ConsoleTitleLength; i++) {
|
|
if (ConsoleTitle[i] == '\\') {
|
|
TranslatedTitle[i] = (WCHAR)'_';
|
|
} else {
|
|
TranslatedTitle[i] = ConsoleTitle[i];
|
|
}
|
|
}
|
|
return TranslatedTitle;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MyRegSetValue(
|
|
IN HANDLE hKey,
|
|
IN LPWSTR lpValueName,
|
|
IN DWORD dwType,
|
|
IN LPVOID lpData,
|
|
IN DWORD cbData
|
|
)
|
|
{
|
|
UNICODE_STRING ValueName;
|
|
|
|
//
|
|
// Convert the subkey to a counted Unicode string.
|
|
//
|
|
|
|
RtlInitUnicodeString( &ValueName, lpValueName );
|
|
|
|
return NtSetValueKey(
|
|
hKey,
|
|
&ValueName,
|
|
0,
|
|
dwType,
|
|
lpData,
|
|
cbData
|
|
);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MyRegUpdateValue(
|
|
IN HANDLE hConsoleKey,
|
|
IN HANDLE hKey,
|
|
IN LPWSTR lpValueName,
|
|
IN DWORD dwType,
|
|
IN LPVOID lpData,
|
|
IN DWORD cbData
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
BYTE Data[MAX_PATH];
|
|
|
|
//
|
|
// If this is not the main console key but the value is the same,
|
|
// delete it. Otherwise, set it.
|
|
//
|
|
|
|
if (hConsoleKey != hKey) {
|
|
Status = MyRegQueryValue(hConsoleKey, lpValueName, sizeof(Data), Data);
|
|
if (NT_SUCCESS(Status)) {
|
|
if (RtlCompareMemory(lpData, Data, cbData) == cbData) {
|
|
return MyRegDeleteKey(hKey, lpValueName);
|
|
}
|
|
}
|
|
}
|
|
|
|
return MyRegSetValue(hKey, lpValueName, dwType, lpData, cbData);
|
|
}
|
|
|
|
|
|
PCONSOLE_STATE_INFO
|
|
InitRegistryValues(VOID)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates a state info structure and fill it in with
|
|
default values.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
pStateInfo - pointer to structure to receive information
|
|
|
|
--*/
|
|
|
|
{
|
|
PCONSOLE_STATE_INFO pStateInfo;
|
|
|
|
pStateInfo = HeapAlloc(RtlProcessHeap(), 0, sizeof(CONSOLE_STATE_INFO));
|
|
if (pStateInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
pStateInfo->Length = sizeof(CONSOLE_STATE_INFO);
|
|
pStateInfo->ScreenAttributes = 0x07; // white on black
|
|
pStateInfo->PopupAttributes = 0xf5; // purple on white
|
|
pStateInfo->InsertMode = FALSE;
|
|
pStateInfo->QuickEdit = FALSE;
|
|
pStateInfo->FullScreen = FALSE;
|
|
pStateInfo->ScreenBufferSize.X = 80;
|
|
pStateInfo->ScreenBufferSize.Y = 25;
|
|
pStateInfo->WindowSize.X = 80;
|
|
pStateInfo->WindowSize.Y = 25;
|
|
pStateInfo->WindowPosX = 0;
|
|
pStateInfo->WindowPosY = 0;
|
|
pStateInfo->AutoPosition = TRUE;
|
|
pStateInfo->FontSize.X = 0;
|
|
pStateInfo->FontSize.Y = 0;
|
|
pStateInfo->FontFamily = 0;
|
|
pStateInfo->FontWeight = 0;
|
|
pStateInfo->FaceName[0] = TEXT('\0');
|
|
pStateInfo->CursorSize = 25;
|
|
pStateInfo->HistoryBufferSize = 25;
|
|
pStateInfo->NumberOfHistoryBuffers = 4;
|
|
pStateInfo->HistoryNoDup = 0;
|
|
pStateInfo->ColorTable[ 0] = RGB(0, 0, 0 );
|
|
pStateInfo->ColorTable[ 1] = RGB(0, 0, 0x80);
|
|
pStateInfo->ColorTable[ 2] = RGB(0, 0x80,0 );
|
|
pStateInfo->ColorTable[ 3] = RGB(0, 0x80,0x80);
|
|
pStateInfo->ColorTable[ 4] = RGB(0x80,0, 0 );
|
|
pStateInfo->ColorTable[ 5] = RGB(0x80,0, 0x80);
|
|
pStateInfo->ColorTable[ 6] = RGB(0x80,0x80,0 );
|
|
pStateInfo->ColorTable[ 7] = RGB(0xC0,0xC0,0xC0);
|
|
pStateInfo->ColorTable[ 8] = RGB(0x80,0x80,0x80);
|
|
pStateInfo->ColorTable[ 9] = RGB(0, 0, 0xFF);
|
|
pStateInfo->ColorTable[10] = RGB(0, 0xFF,0 );
|
|
pStateInfo->ColorTable[11] = RGB(0, 0xFF,0xFF);
|
|
pStateInfo->ColorTable[12] = RGB(0xFF,0, 0 );
|
|
pStateInfo->ColorTable[13] = RGB(0xFF,0, 0xFF);
|
|
pStateInfo->ColorTable[14] = RGB(0xFF,0xFF,0 );
|
|
pStateInfo->ColorTable[15] = RGB(0xFF,0xFF,0xFF);
|
|
#if defined(FE_SB)
|
|
pStateInfo->CodePage = OEMCP; // scotthsu
|
|
#endif
|
|
pStateInfo->hWnd = NULL;
|
|
pStateInfo->ConsoleTitle[0] = TEXT('\0');
|
|
|
|
g_fAutoComplete = TRUE;
|
|
|
|
return pStateInfo;
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SZ_REGKEY_CMDAUTOCOMPLETE TEXT("Software\\Microsoft\\Command Processor")
|
|
#define SZ_REGVALUE_CMDAUTOCOMPLETE TEXT("CompletionChar")
|
|
#define DWORD_CMD_TAB_AUTOCOMPLETE_ON 0x00000009 // 9 is tab
|
|
#define DWORD_CMD_TAB_AUTOCOMPLETE_OFF 0x00000020 // 20 is space which turns it off.
|
|
|
|
BOOL
|
|
IsAutoCompleteOn(
|
|
void
|
|
)
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwValue = DWORD_CMD_TAB_AUTOCOMPLETE_ON;
|
|
DWORD cbSize = sizeof(dwValue);
|
|
|
|
if ((ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_CMDAUTOCOMPLETE, SZ_REGVALUE_CMDAUTOCOMPLETE, &dwType, (LPBYTE)&dwValue, &cbSize)) ||
|
|
(REG_DWORD != dwType))
|
|
{
|
|
dwValue = DWORD_CMD_TAB_AUTOCOMPLETE_ON; // Fall back to the default value.
|
|
}
|
|
|
|
return (DWORD_CMD_TAB_AUTOCOMPLETE_ON == dwValue);
|
|
}
|
|
|
|
|
|
void
|
|
SaveAutoCompleteSetting(
|
|
IN BOOL fAutoComplete
|
|
)
|
|
{
|
|
// Only over write the registry value if someone has changed the value.
|
|
if (g_fSaveAutoCompleteState)
|
|
{
|
|
DWORD dwValue = (fAutoComplete ? DWORD_CMD_TAB_AUTOCOMPLETE_ON : DWORD_CMD_TAB_AUTOCOMPLETE_OFF);
|
|
|
|
SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CMDAUTOCOMPLETE, SZ_REGVALUE_CMDAUTOCOMPLETE, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue));
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetRegistryValues(
|
|
PCONSOLE_STATE_INFO pStateInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads in values from the registry and places them
|
|
in the supplied structure.
|
|
|
|
Arguments:
|
|
|
|
pStateInfo - optional pointer to structure to receive information
|
|
|
|
Return Value:
|
|
|
|
current page number
|
|
|
|
--*/
|
|
|
|
{
|
|
HANDLE hCurrentUserKey;
|
|
HANDLE hConsoleKey;
|
|
HANDLE hTitleKey;
|
|
NTSTATUS Status;
|
|
LPWSTR TranslatedTitle;
|
|
DWORD dwValue;
|
|
DWORD dwRet = 0;
|
|
DWORD i;
|
|
WCHAR awchBuffer[LF_FACESIZE];
|
|
|
|
//
|
|
// Open the current user registry key
|
|
//
|
|
|
|
Status = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &hCurrentUserKey);
|
|
if (!NT_SUCCESS(Status)) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Open the console registry key
|
|
//
|
|
|
|
Status = MyRegOpenKey(hCurrentUserKey,
|
|
CONSOLE_REGISTRY_STRING,
|
|
&hConsoleKey);
|
|
if (!NT_SUCCESS(Status)) {
|
|
NtClose(hCurrentUserKey);
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// If there is no structure to fill out, just get the current
|
|
// page and bail out.
|
|
//
|
|
|
|
if (pStateInfo == NULL) {
|
|
if (NT_SUCCESS(MyRegQueryValue(hConsoleKey,
|
|
CONSOLE_REGISTRY_CURRENTPAGE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
dwRet = dwValue;
|
|
}
|
|
goto CloseKeys;
|
|
}
|
|
|
|
//
|
|
// Open the console title subkey, if there is one
|
|
//
|
|
|
|
if (pStateInfo->ConsoleTitle[0] != TEXT('\0')) {
|
|
TranslatedTitle = TranslateConsoleTitle(pStateInfo->ConsoleTitle);
|
|
if (TranslatedTitle == NULL) {
|
|
NtClose(hConsoleKey);
|
|
NtClose(hCurrentUserKey);
|
|
return 0;
|
|
}
|
|
Status = MyRegOpenKey(hConsoleKey,
|
|
TranslatedTitle,
|
|
&hTitleKey);
|
|
HeapFree(RtlProcessHeap(),0,TranslatedTitle);
|
|
if (!NT_SUCCESS(Status)) {
|
|
NtClose(hConsoleKey);
|
|
NtClose(hCurrentUserKey);
|
|
return 0;
|
|
}
|
|
} else {
|
|
hTitleKey = hConsoleKey;
|
|
}
|
|
|
|
//
|
|
// Initial screen fill
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FILLATTR,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->ScreenAttributes = (WORD)dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial popup fill
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_POPUPATTR,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->PopupAttributes = (WORD)dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial color table
|
|
//
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
wsprintf(awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i);
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey, awchBuffer,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->ColorTable[i] = dwValue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initial insert mode
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_INSERTMODE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->InsertMode = !!dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial quick edit mode
|
|
//
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_QUICKEDIT,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->QuickEdit = !!dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial autocomplete mode
|
|
//
|
|
g_fAutoComplete = IsAutoCompleteOn();
|
|
|
|
#ifdef i386
|
|
//
|
|
// Initial full screen mode
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FULLSCR,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->FullScreen = !!dwValue;
|
|
}
|
|
#endif
|
|
#if defined(FE_SB) // scotthsu
|
|
//
|
|
// Initial code page
|
|
//
|
|
|
|
ASSERT(OEMCP != 0);
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_CODEPAGE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
if (IsValidCodePage(dwValue)) {
|
|
pStateInfo->CodePage = (UINT) dwValue;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Initial screen buffer size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_BUFFERSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->ScreenBufferSize.X = LOWORD(dwValue);
|
|
pStateInfo->ScreenBufferSize.Y = HIWORD(dwValue);
|
|
}
|
|
|
|
//
|
|
// Initial window size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_WINDOWSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->WindowSize.X = LOWORD(dwValue);
|
|
pStateInfo->WindowSize.Y = HIWORD(dwValue);
|
|
}
|
|
|
|
//
|
|
// Initial window position
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_WINDOWPOS,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->WindowPosX = (SHORT)LOWORD(dwValue);
|
|
pStateInfo->WindowPosY = (SHORT)HIWORD(dwValue);
|
|
pStateInfo->AutoPosition = FALSE;
|
|
}
|
|
|
|
//
|
|
// Initial font size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FONTSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->FontSize.X = LOWORD(dwValue);
|
|
pStateInfo->FontSize.Y = HIWORD(dwValue);
|
|
}
|
|
|
|
//
|
|
// Initial font family
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FONTFAMILY,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->FontFamily = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial font weight
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FONTWEIGHT,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->FontWeight = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial font face name
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FACENAME,
|
|
sizeof(awchBuffer), (PBYTE)awchBuffer))) {
|
|
RtlCopyMemory(pStateInfo->FaceName, awchBuffer, sizeof(awchBuffer));
|
|
}
|
|
|
|
//
|
|
// Initial cursor size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_CURSORSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->CursorSize = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial history buffer size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_HISTORYSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->HistoryBufferSize = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial number of history buffers
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_HISTORYBUFS,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->NumberOfHistoryBuffers = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial history duplication mode
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_HISTORYNODUP,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
pStateInfo->HistoryNoDup = dwValue;
|
|
}
|
|
|
|
//
|
|
// Close the registry keys
|
|
//
|
|
|
|
if (hTitleKey != hConsoleKey) {
|
|
NtClose(hTitleKey);
|
|
}
|
|
|
|
CloseKeys:
|
|
NtClose(hConsoleKey);
|
|
NtClose(hCurrentUserKey);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
VOID
|
|
SetRegistryValues(
|
|
PCONSOLE_STATE_INFO pStateInfo,
|
|
DWORD dwPage
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine writes values to the registry from the supplied
|
|
structure.
|
|
|
|
Arguments:
|
|
|
|
pStateInfo - optional pointer to structure containing information
|
|
dwPage - current page number
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
HANDLE hCurrentUserKey;
|
|
HANDLE hConsoleKey;
|
|
HANDLE hTitleKey;
|
|
NTSTATUS Status;
|
|
LPWSTR TranslatedTitle;
|
|
DWORD dwValue;
|
|
DWORD i;
|
|
WCHAR awchBuffer[LF_FACESIZE];
|
|
|
|
//
|
|
// Open the current user registry key
|
|
//
|
|
|
|
Status = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &hCurrentUserKey);
|
|
if (!NT_SUCCESS(Status)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Open the console registry key
|
|
//
|
|
|
|
Status = MyRegCreateKey(hCurrentUserKey,
|
|
CONSOLE_REGISTRY_STRING,
|
|
&hConsoleKey);
|
|
if (!NT_SUCCESS(Status)) {
|
|
NtClose(hCurrentUserKey);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Save the current page
|
|
//
|
|
|
|
MyRegSetValue(hConsoleKey,
|
|
CONSOLE_REGISTRY_CURRENTPAGE,
|
|
REG_DWORD, &dwPage, sizeof(dwPage));
|
|
|
|
//
|
|
// If we only want to save the current page, bail out
|
|
//
|
|
|
|
if (pStateInfo == NULL) {
|
|
goto CloseKeys;
|
|
}
|
|
|
|
//
|
|
// Open the console title subkey, if there is one
|
|
//
|
|
|
|
if (pStateInfo->ConsoleTitle[0] != TEXT('\0')) {
|
|
TranslatedTitle = TranslateConsoleTitle(pStateInfo->ConsoleTitle);
|
|
if (TranslatedTitle == NULL) {
|
|
NtClose(hConsoleKey);
|
|
NtClose(hCurrentUserKey);
|
|
return;
|
|
}
|
|
Status = MyRegCreateKey(hConsoleKey,
|
|
TranslatedTitle,
|
|
&hTitleKey);
|
|
HeapFree(RtlProcessHeap(),0,TranslatedTitle);
|
|
if (!NT_SUCCESS(Status)) {
|
|
NtClose(hConsoleKey);
|
|
NtClose(hCurrentUserKey);
|
|
return;
|
|
}
|
|
} else {
|
|
hTitleKey = hConsoleKey;
|
|
}
|
|
|
|
//
|
|
// Save screen and popup colors and color table
|
|
//
|
|
|
|
dwValue = pStateInfo->ScreenAttributes;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_FILLATTR,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
dwValue = pStateInfo->PopupAttributes;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_POPUPATTR,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
for (i = 0; i < 16; i++) {
|
|
dwValue = pStateInfo->ColorTable[i];
|
|
wsprintf(awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i);
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, awchBuffer,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
}
|
|
|
|
//
|
|
// Save insert, quickedit, and fullscreen mode settings
|
|
//
|
|
|
|
dwValue = pStateInfo->InsertMode;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_INSERTMODE,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
dwValue = pStateInfo->QuickEdit;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_QUICKEDIT,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
|
|
SaveAutoCompleteSetting(g_fAutoComplete);
|
|
|
|
#ifdef i386
|
|
dwValue = pStateInfo->FullScreen;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_FULLSCR,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
#endif
|
|
#if defined(FE_SB) // scotthsu
|
|
|
|
ASSERT(OEMCP != 0);
|
|
if (gfFESystem) {
|
|
dwValue = (DWORD) pStateInfo->CodePage;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_CODEPAGE,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Save screen buffer size
|
|
//
|
|
|
|
dwValue = MAKELONG(pStateInfo->ScreenBufferSize.X,
|
|
pStateInfo->ScreenBufferSize.Y);
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_BUFFERSIZE,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
|
|
//
|
|
// Save window size
|
|
//
|
|
|
|
dwValue = MAKELONG(pStateInfo->WindowSize.X,
|
|
pStateInfo->WindowSize.Y);
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_WINDOWSIZE,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
|
|
//
|
|
// Save window position
|
|
//
|
|
|
|
if (pStateInfo->AutoPosition) {
|
|
MyRegDeleteKey(hTitleKey, CONSOLE_REGISTRY_WINDOWPOS);
|
|
} else {
|
|
dwValue = MAKELONG(pStateInfo->WindowPosX,
|
|
pStateInfo->WindowPosY);
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_WINDOWPOS,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
}
|
|
|
|
//
|
|
// Save font size, family, weight, and face name
|
|
//
|
|
|
|
dwValue = MAKELONG(pStateInfo->FontSize.X,
|
|
pStateInfo->FontSize.Y);
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_FONTSIZE,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
dwValue = pStateInfo->FontFamily;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_FONTFAMILY,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
dwValue = pStateInfo->FontWeight;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_FONTWEIGHT,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_FACENAME,
|
|
REG_SZ, pStateInfo->FaceName,
|
|
(_tcslen(pStateInfo->FaceName) + 1) * sizeof(TCHAR));
|
|
|
|
//
|
|
// Save cursor size
|
|
//
|
|
|
|
dwValue = pStateInfo->CursorSize;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_CURSORSIZE,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
|
|
//
|
|
// Save history buffer size and number
|
|
//
|
|
|
|
dwValue = pStateInfo->HistoryBufferSize;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_HISTORYSIZE,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
dwValue = pStateInfo->NumberOfHistoryBuffers;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_HISTORYBUFS,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
dwValue = pStateInfo->HistoryNoDup;
|
|
MyRegUpdateValue(hConsoleKey, hTitleKey, CONSOLE_REGISTRY_HISTORYNODUP,
|
|
REG_DWORD, &dwValue, sizeof(dwValue));
|
|
|
|
//
|
|
// Close the registry keys
|
|
//
|
|
|
|
if (hTitleKey != hConsoleKey) {
|
|
NtClose(hTitleKey);
|
|
}
|
|
|
|
CloseKeys:
|
|
NtClose(hConsoleKey);
|
|
NtClose(hCurrentUserKey);
|
|
}
|