Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1345 lines
42 KiB

/****************************** Module Header ******************************\
* Module Name: profile.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* This module contains code to emulate ini file mapping.
*
* History:
* 30-Nov-1993 SanfordS Created.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/***************************************************************************\
* aFastRegMap[]
*
* This array maps section ids (PMAP_) to cached registry keys and section
* addresses within the registry. IF INI FILE MAPPING CHANGES ARE MADE,
* THIS TABLE MUST BE UPDATED.
*
* The first character of the szSection field indicates what root the
* section is in. (or locked open status)
* M = LocalMachine
* U = CurrentUser
* L = Locked open - used only on M mappings.
*
* History:
\***************************************************************************/
#define PROOT_CPANEL 0
#define PROOT_ACCESS 1
#define PROOT_CURRENTM 2
#define PROOT_CURRENTU 3
#define PROOT_CONTROL 4
#define PROOT_SERVICES 5
#define PROOT_KEYBOARD 6
#define PROOT_SYSTEM 7
typedef struct tagFASTREGMAP {
UINT idRoot;
PCWSTR szSection;
} FASTREGMAP, *PFASTREGMAP;
CONST PCWSTR aFastRegRoot[] = {
L"UControl Panel\\", // PROOT_CPANEL
L"UControl Panel\\Accessibility\\", // PROOT_ACCESS
L"MSoftware\\Microsoft\\Windows NT\\CurrentVersion\\", // PROOT_CURRENTM
L"USoftware\\Microsoft\\Windows NT\\CurrentVersion\\", // PROOT_CURRENTU
L"MSystem\\CurrentControlSet\\Control\\", // PROOT_CONTROL
L"MSystem\\CurrentControlSet\\Services\\", // PROOT_SERVICES
L"UKeyboard Layout\\", // PROOT_KEYBOARD
L"MSystem\\", // PROOT_SYSTEM
};
CONST FASTREGMAP aFastRegMap[PMAP_LAST + 1] = {
{ PROOT_CPANEL, L"Colors" }, // PMAP_COLORS
{ PROOT_CPANEL, L"Cursors" }, // PMAP_CURSORS
{ PROOT_CURRENTM, L"Windows" }, // PMAP_WINDOWSM
{ PROOT_CURRENTU, L"Windows" }, // PMAP_WINDOWSU
{ PROOT_CPANEL, L"Desktop" }, // PMAP_DESKTOP
{ PROOT_CPANEL, L"Icons" }, // PMAP_ICONS
{ PROOT_CURRENTM, L"Fonts" }, // PMAP_FONTS
{ PROOT_CURRENTU, L"TrueType" }, // PMAP_TRUETYPE
{ PROOT_CONTROL, L"Keyboard Layout" }, // PMAP_KBDLAYOUT
{ PROOT_SERVICES, L"RIT" }, // PMAP_INPUT
{ PROOT_CURRENTM, L"Compatibility" }, // PMAP_COMPAT
{ PROOT_CONTROL, L"Session Manager\\SubSystems" }, // PMAP_SUBSYSTEMS
{ PROOT_CPANEL, L"Sound" }, // PMAP_BEEP
{ PROOT_CPANEL, L"Mouse" }, // PMAP_MOUSE
{ PROOT_CPANEL, L"Keyboard" }, // PMAP_KEYBOARD
{ PROOT_ACCESS, L"StickyKeys" }, // PMAP_STICKYKEYS
{ PROOT_ACCESS, L"Keyboard Response" }, // PMAP_KEYBOARDRESPONSE
{ PROOT_ACCESS, L"MouseKeys" }, // PMAP_MOUSEKEYS
{ PROOT_ACCESS, L"ToggleKeys" }, // PMAP_TOGGLEKEYS
{ PROOT_ACCESS, L"TimeOut" }, // PMAP_TIMEOUT
{ PROOT_ACCESS, L"SoundSentry" }, // PMAP_SOUNDSENTRY
{ PROOT_ACCESS, L"ShowSounds" }, // PMAP_SHOWSOUNDS
{ PROOT_CURRENTM, L"AeDebug" }, // PMAP_AEDEBUG
{ PROOT_CONTROL, L"NetworkProvider" }, // PMAP_NETWORK
{ PROOT_CPANEL, L"Desktop\\WindowMetrics" }, // PMAP_METRICS
{ PROOT_KEYBOARD, L"" }, // PMAP_UKBDLAYOUT
{ PROOT_KEYBOARD, L"Toggle" }, // PMAP_UKBDLAYOUTTOGGLE
{ PROOT_CURRENTM, L"Winlogon" }, // PMAP_WINLOGON
{ PROOT_ACCESS, L"Keyboard Preference" }, // PMAP_KEYBOARDPREF
{ PROOT_ACCESS, L"Blind Access" }, // PMAP_SCREENREADER
{ PROOT_ACCESS, L"HighContrast" }, // PMAP_HIGHCONTRAST
{ PROOT_CURRENTM, L"IME Compatibility" }, // PMAP_IMECOMPAT
{ PROOT_CURRENTM, L"IMM" }, // PMAP_IMM
{ PROOT_CONTROL, L"Session Manager\\SubSystems\\Pool" }, // PMAP_POOLLIMITS
{ PROOT_CURRENTM, L"Compatibility32" }, // PMAP_COMPAT32
{ PROOT_CURRENTM, L"WOW\\SetupPrograms" }, // PMAP_SETUPPROGRAMNAMES
{ PROOT_CPANEL, L"Input Method" }, // PMAP_INPUTMETHOD
{ PROOT_CURRENTM, L"Compatibility2" }, // PMAP_COMPAT2
{ PROOT_SERVICES, L"Mouclass\\Parameters" }, // PMAP_MOUCLASS_PARAMS
{ PROOT_SERVICES, L"Kbdclass\\Parameters" }, // PMAP_KBDCLASS_PARAMS
{ PROOT_CONTROL, L"ComputerName\\ComputerName" }, // PMAP_COMPUTERNAME
{ PROOT_CONTROL, L"Terminal Server" }, // PMAP_TS
{ PROOT_SYSTEM, L"WPA\\TabletPC" }, // PMAP_TABLETPC
{ PROOT_SYSTEM, L"WPA\\MediaCenter" }, // PMAP_MEDIACENTER
{ PROOT_CURRENTM, L"Windows" }, // PMAP_TS_EXCLUDE_DESKTOP_VERSION
};
WCHAR PreviousUserStringBuf[256];
UNICODE_STRING PreviousUserString = {0, sizeof PreviousUserStringBuf, PreviousUserStringBuf};
LUID luidPrevious;
CONST WCHAR wszDefaultUser[] = L"\\Registry\\User\\.Default";
UNICODE_STRING DefaultUserString = {sizeof wszDefaultUser - sizeof(WCHAR), sizeof wszDefaultUser, (WCHAR *)wszDefaultUser};
void InitPreviousUserString(void) {
UNICODE_STRING UserString;
LUID luidCaller;
CheckCritIn();
/*
* Speed hack, check if luid of this process == system or previous to
* save work.
*/
if (NT_SUCCESS(GetProcessLuid(NULL, &luidCaller))) {
if (RtlEqualLuid(&luidCaller, &luidPrevious)) {
return; // same as last time - no work.
}
luidPrevious = luidCaller;
if (RtlEqualLuid(&luidCaller, &luidSystem))
goto DefaultUser;
} else {
luidPrevious = RtlConvertLongToLuid(0);
}
/*
* Set up current user registry base string.
*/
if (!NT_SUCCESS(RtlFormatCurrentUserKeyPath(&UserString))) {
DefaultUser:
RtlCopyUnicodeString(&PreviousUserString, &DefaultUserString);
} else {
UserAssert(sizeof(PreviousUserStringBuf) >= UserString.Length + 4);
RtlCopyUnicodeString(&PreviousUserString, &UserString);
RtlFreeUnicodeString(&UserString);
}
RtlAppendUnicodeToString(&PreviousUserString, L"\\");
}
typedef struct tagPROFILEUSERNAME {
WCHAR awcName[MAXPROFILEBUF];
UNICODE_STRING NameString;
} PROFILEUSERNAME, *PPROFILEUSERNAME;
PUNICODE_STRING CreateProfileUserName(TL *ptl)
{
PPROFILEUSERNAME pMapName;
CheckCritIn();
pMapName = UserAllocPoolWithQuota(sizeof (PROFILEUSERNAME), TAG_PROFILEUSERNAME);
if (!pMapName) {
RIPMSG0(RIP_WARNING, "CreateProfileUserName: Allocation failed");
return NULL;
}
ThreadLockPool(PtiCurrent(), pMapName, ptl);
pMapName->NameString.Length = 0;
pMapName->NameString.MaximumLength = sizeof (pMapName->awcName);
pMapName->NameString.Buffer = pMapName->awcName;
InitPreviousUserString();
RtlCopyUnicodeString(&pMapName->NameString, &PreviousUserString);
return &(pMapName->NameString);
}
void FreeProfileUserName(PUNICODE_STRING pProfileUserName,TL *ptl) {
UNREFERENCED_PARAMETER(ptl);
CheckCritIn();
if (pProfileUserName) {
ThreadUnlockAndFreePool(PtiCurrent(), ptl);
}
}
/*****************************************************************************\
* OpenCacheKeyEx
*
* Attempts to open a cached key for a given section. If we are calling
* for a client thread, we must check the access rights for the key after
* opening it.
*
* Returns fSuccess.
*
* Note -- param 1 can be NULL. If the section name is a per-user registry
* section, we ill use the first parameter if available or set up
* and use the cached one if the first parameter is NULL.
*
* History:
* 03-Dec-1993 SanfordS Created.
\*****************************************************************************/
HANDLE OpenCacheKeyEx(
PUNICODE_STRING pMapName OPTIONAL,
UINT idSection,
ACCESS_MASK amRequest,
PDWORD pdwPolicyFlags
)
{
OBJECT_ATTRIBUTES OA;
WCHAR UnicodeStringBuf[256];
WCHAR pszSessionId[13];
UNICODE_STRING UnicodeString;
LONG Status;
HANDLE hKey = NULL;
PEPROCESS peCurrent = PsGetCurrentProcess();
DWORD dwPolicyFlags;
CheckCritIn();
UserAssert(idSection <= PMAP_LAST);
/*
* If we're opening the desktop or CPL\keyboard key for read access, we should be checking
* for relevant policy.
*/
if ((amRequest == KEY_READ) && (idSection == PMAP_DESKTOP)) {
UserAssert(pdwPolicyFlags);
UserAssert(!(*pdwPolicyFlags & ~POLICY_VALID));
dwPolicyFlags = *pdwPolicyFlags;
} else {
/*
* if we are here because Policy was changed and there is not POLICY_ flags set then return.
*/
if (pdwPolicyFlags && (*pdwPolicyFlags & POLICY_ONLY)) {
*pdwPolicyFlags = 0;
UserAssert(FALSE);
return NULL;
}
dwPolicyFlags = POLICY_NONE;
}
TryAgain:
UnicodeString.Length = 0;
UnicodeString.MaximumLength = sizeof(UnicodeStringBuf);
UnicodeString.Buffer = UnicodeStringBuf;
if (dwPolicyFlags & POLICY_MACHINE) {
dwPolicyFlags &= ~POLICY_MACHINE;
RtlAppendUnicodeToString(&UnicodeString,
L"\\Registry\\Machine\\");
RtlAppendUnicodeToString(&UnicodeString,
L"Software\\Policies\\Microsoft\\Windows\\");
} else {
if (aFastRegRoot[aFastRegMap[idSection].idRoot][0] == L'M') {
RtlAppendUnicodeToString(&UnicodeString, L"\\Registry\\Machine\\");
} else {
if (!pMapName) {
InitPreviousUserString();
RtlAppendUnicodeStringToString(
&UnicodeString,
&PreviousUserString);
} else {
RtlAppendUnicodeStringToString(
&UnicodeString,
pMapName);
}
}
if (dwPolicyFlags & POLICY_USER) {
dwPolicyFlags &= ~POLICY_USER;
RtlAppendUnicodeToString(&UnicodeString,
L"Software\\Policies\\Microsoft\\Windows\\");
}
else if (dwPolicyFlags & POLICY_REMOTE) {
dwPolicyFlags &= ~POLICY_REMOTE;
RtlAppendUnicodeToString(&UnicodeString,
L"Remote\\");
swprintf(pszSessionId, L"%ld\\", gSessionId);
RtlAppendUnicodeToString(&UnicodeString, pszSessionId);
} else {
/*
* if we are here because Policy was changed then do not try preferences.
*/
if (pdwPolicyFlags && (*pdwPolicyFlags & POLICY_ONLY)) {
*pdwPolicyFlags = 0;
return NULL;
}
dwPolicyFlags &= ~POLICY_NONE;
}
}
RtlAppendUnicodeToString(&UnicodeString,
(PWSTR)&aFastRegRoot[aFastRegMap[idSection].idRoot][1]);
RtlAppendUnicodeToString(&UnicodeString,
(PWSTR)aFastRegMap[idSection].szSection);
/*
* Open the key for kernel mode access
*/
InitializeObjectAttributes(&OA,
&UnicodeString,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwOpenKey(&hKey, amRequest, &OA);
if (
(amRequest == KEY_READ) || /*
* We must be able to read
* our registry settings.
*/
(peCurrent == gpepCSRSS) ||
(peCurrent == gpepInit)
) {
} else {
/*
* Now check if the user has access to the key
*/
if (NT_SUCCESS(Status)) {
PVOID pKey;
NTSTATUS Status2;
Status2 = ObReferenceObjectByHandle(hKey,
amRequest,
NULL,
KernelMode,
&pKey,
NULL);
if (NT_SUCCESS(Status2)) {
if (!AccessCheckObject(pKey, amRequest, UserMode, &KeyMapping)) {
ZwClose(hKey);
Status = STATUS_ACCESS_DENIED;
}
ObDereferenceObject(pKey);
} else {
ZwClose(hKey);
Status = STATUS_ACCESS_DENIED;
}
}
}
#if DBG
if (!NT_SUCCESS(Status)) {
UnicodeStringBuf[UnicodeString.Length / 2] = 0;
if (PsGetCurrentProcessId() != gpidLogon) {
if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
RIPMSG1(RIP_WARNING | RIP_THERESMORE, "OpenCacheKeyEx failed with Status = %lx key:", Status);
RIPMSG1(RIP_WARNING | RIP_THERESMORE | RIP_NONAME | RIP_NONEWLINE, " %ws\\", UnicodeStringBuf);
}
}
}
#endif
/*
* If we didn't succeed and we're not down to bottom of policy chain, try again.
*/
if (!NT_SUCCESS(Status) && dwPolicyFlags) {
goto TryAgain;
}
/*
* Update policy level
*/
if (pdwPolicyFlags) {
*pdwPolicyFlags = dwPolicyFlags;
}
return (NT_SUCCESS(Status) ? hKey : NULL);
}
/*****************************************************************************\
* CheckDesktopPolicy
*
* Check if a desktop value has an associated policy.
*
* Returns TRUE if there is a policy, FALSE otherwise.
*
* History:
* 07-Feb-2000 JerrySh Created.
\*****************************************************************************/
BOOL CheckDesktopPolicy(
PUNICODE_STRING pProfileUserName OPTIONAL,
PCWSTR lpKeyName
)
{
WCHAR szKey[80];
HANDLE hKey;
DWORD cbSize;
NTSTATUS Status;
UNICODE_STRING UnicodeString;
KEY_VALUE_BASIC_INFORMATION KeyInfo;
DWORD dwPolicyFlags = gdwPolicyFlags & (POLICY_MACHINE | POLICY_USER);
/*
* If there is no policy or the caller is winlogon, let it go.
*/
if (!dwPolicyFlags || PsGetCurrentProcessId() == gpidLogon) {
return FALSE;
}
/*
* Convert the ID to a string if we need to.
*/
if (!IS_PTR(lpKeyName)) {
ServerLoadString(hModuleWin, PTR_TO_ID(lpKeyName), szKey, ARRAY_SIZE(szKey));
lpKeyName = szKey;
}
TryAgain:
/*
* Try to open a key.
*/
if ((hKey = OpenCacheKeyEx(pProfileUserName,
PMAP_DESKTOP,
KEY_READ,
&dwPolicyFlags)) == NULL) {
return FALSE;
}
/*
* See if the value exists.
*/
RtlInitUnicodeString(&UnicodeString, lpKeyName);
Status = ZwQueryValueKey(hKey,
&UnicodeString,
KeyValueBasicInformation,
&KeyInfo,
sizeof(KeyInfo),
&cbSize);
ZwClose(hKey);
if (!NT_ERROR(Status)) {
return TRUE;
} else if (dwPolicyFlags) {
goto TryAgain;
} else {
return FALSE;
}
}
/*****************************************************************************\
* CheckDesktopPolicyChange
*
* Check if policy has changed since last time we checked.
*
* Returns TRUE if policy changed, FASLE otherwise.
*
* History:
* 07-Feb-2000 JerrySh Created.
\*****************************************************************************/
BOOL CheckDesktopPolicyChange(
PUNICODE_STRING pProfileUserName OPTIONAL
)
{
static LARGE_INTEGER LastMachineWriteTime;
static LARGE_INTEGER LastUserWriteTime;
KEY_BASIC_INFORMATION KeyInfo;
BOOL bPolicyChanged = FALSE;
HANDLE hKey;
DWORD cbSize;
DWORD dwPolicyFlags;
/*
* Check if machine policy has changed since last time we checked.
*/
dwPolicyFlags = POLICY_MACHINE;
KeyInfo.LastWriteTime.QuadPart = 0;
hKey = OpenCacheKeyEx(pProfileUserName,
PMAP_DESKTOP,
KEY_READ,
&dwPolicyFlags);
if (hKey) {
if (hKey) {
ZwQueryKey(hKey,
KeyValueBasicInformation,
&KeyInfo,
sizeof(KeyInfo),
&cbSize);
ZwClose(hKey);
}
gdwPolicyFlags |= POLICY_MACHINE;
} else {
gdwPolicyFlags &= ~POLICY_MACHINE;
}
if (LastMachineWriteTime.QuadPart != KeyInfo.LastWriteTime.QuadPart) {
LastMachineWriteTime.QuadPart = KeyInfo.LastWriteTime.QuadPart;
bPolicyChanged = TRUE;
}
/*
* Check if user policy has changed since last time we checked.
*/
dwPolicyFlags = POLICY_USER;
KeyInfo.LastWriteTime.QuadPart = 0;
hKey = OpenCacheKeyEx(pProfileUserName,
PMAP_DESKTOP,
KEY_READ,
&dwPolicyFlags);
if (hKey) {
ZwQueryKey(hKey,
KeyValueBasicInformation,
&KeyInfo,
sizeof(KeyInfo),
&cbSize);
ZwClose(hKey);
gdwPolicyFlags |= POLICY_USER;
} else {
gdwPolicyFlags &= ~POLICY_USER;
}
if (LastUserWriteTime.QuadPart != KeyInfo.LastWriteTime.QuadPart) {
LastUserWriteTime.QuadPart = KeyInfo.LastWriteTime.QuadPart;
bPolicyChanged = TRUE;
}
return bPolicyChanged;
}
/*****************************************************************************\
* FastGetProfileDwordW
*
* Reads a REG_DWORD type key from the registry.
*
* returns value read or default value on failure.
*
* History:
* 02-Dec-1993 SanfordS Created.
\*****************************************************************************/
BOOL FastGetProfileDwordW(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
LPCWSTR lpKeyName,
DWORD dwDefault,
PDWORD pdwReturn,
DWORD dwPolicyOnly
)
{
HANDLE hKey;
DWORD cbSize;
DWORD dwRet;
LONG Status;
UNICODE_STRING UnicodeString;
BYTE Buf[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)];
DWORD dwPolicyFlags = gdwPolicyFlags | dwPolicyOnly;
UserAssert(idSection <= PMAP_LAST);
TryAgain:
if ((hKey = OpenCacheKeyEx(pProfileUserName,
idSection,
KEY_READ,
&dwPolicyFlags)) == NULL) {
RIPMSG1(RIP_WARNING | RIP_NONAME, "%ws", lpKeyName);
if (dwPolicyOnly & POLICY_ONLY) {
return FALSE;
}
if (pdwReturn) {
*pdwReturn = dwDefault;
}
return TRUE;
}
RtlInitUnicodeString(&UnicodeString, lpKeyName);
Status = ZwQueryValueKey(hKey,
&UnicodeString,
KeyValuePartialInformation,
(PKEY_VALUE_PARTIAL_INFORMATION)Buf,
sizeof(Buf),
&cbSize);
dwRet = dwDefault;
if (NT_SUCCESS(Status)) {
dwRet = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)Buf)->Data);
} else if (dwPolicyFlags) {
ZwClose(hKey);
goto TryAgain;
} else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
RIPMSG1(RIP_WARNING,
"FastGetProfileDwordW: ObjectName not found: %ws",
lpKeyName);
}
ZwClose(hKey);
if (pdwReturn) {
*pdwReturn = dwRet;
}
return TRUE;
}
/*****************************************************************************\
* FastGetProfileKeysW()
*
* Reads all key names in the given section.
*
* History:
* 15-Dec-1994 JimA Created.
\*****************************************************************************/
DWORD FastGetProfileKeysW(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
LPCWSTR lpDefault,
LPWSTR *lpReturnedString
)
{
HANDLE hKey;
DWORD cchSize;
DWORD cchKey;
LONG Status;
WCHAR Buffer[256 + 6];
PKEY_VALUE_BASIC_INFORMATION pKeyInfo;
ULONG iValue;
LPWSTR lpTmp;
LPWSTR lpKeys = NULL;
DWORD dwPoolSize;
UserAssert(idSection <= PMAP_LAST);
if ((hKey = OpenCacheKeyEx(pProfileUserName,
idSection,
KEY_READ,
NULL)) == NULL) {
RIPMSG0(RIP_WARNING | RIP_NONAME, "");
goto DefExit;
}
pKeyInfo = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
cchSize = 0;
*lpReturnedString = NULL;
iValue = 0;
while (TRUE) {
#if DBG
wcscpy(Buffer + 256, L"DON'T");
#endif
Status = ZwEnumerateValueKey(hKey,
iValue,
KeyValueBasicInformation,
pKeyInfo,
sizeof(Buffer),
&cchKey);
UserAssert(_wcsicmp(Buffer + 256, L"DON'T") == 0);
if (Status == STATUS_NO_MORE_ENTRIES) {
break;
} else if (!NT_SUCCESS(Status)) {
if (lpKeys) {
UserFreePool(lpKeys);
lpKeys = NULL;
}
goto DefExit;
}
UserAssert(pKeyInfo->NameLength * sizeof(WCHAR) <=
sizeof(Buffer) - sizeof(KEY_VALUE_BASIC_INFORMATION));
UserAssert(cchKey <= sizeof(Buffer));
/*
* A key was found. Allocate space for it. Note that
* NameLength is in bytes.
*/
cchKey = cchSize;
cchSize += pKeyInfo->NameLength + sizeof(WCHAR);
if (lpKeys == NULL) {
dwPoolSize = cchSize + sizeof(WCHAR);
lpKeys = UserAllocPoolWithQuota(dwPoolSize, TAG_PROFILE);
} else {
lpTmp = lpKeys;
lpKeys = UserReAllocPoolWithQuota(lpTmp,
dwPoolSize,
cchSize + sizeof(WCHAR),
TAG_PROFILE);
/*
* Free the original buffer if the allocation fails
*/
if (lpKeys == NULL) {
UserFreePool(lpTmp);
}
dwPoolSize = cchSize + sizeof(WCHAR);
}
/*
* Check for out of memory.
*/
if (lpKeys == NULL)
goto DefExit;
/*
* NULL terminate the string and append it to
* the key list.
*/
UserAssert(pKeyInfo->NameLength < sizeof(Buffer) - sizeof(KEY_VALUE_BASIC_INFORMATION));
RtlCopyMemory(&lpKeys[cchKey / sizeof(WCHAR)], pKeyInfo->Name, pKeyInfo->NameLength);
lpKeys[(cchKey + pKeyInfo->NameLength) / sizeof(WCHAR)] = 0;
iValue++;
}
/*
* If no keys were found, return the default.
*/
if (iValue == 0) {
DefExit:
cchSize = wcslen(lpDefault)+1;
lpKeys = UserAllocPoolWithQuota((cchSize+1) * sizeof(WCHAR), TAG_PROFILE);
if (lpKeys)
wcscpy(lpKeys, lpDefault);
else
cchSize = 0;
} else {
/*
* Turn the byte count into a char count.
*/
cchSize /= sizeof(WCHAR);
}
/*
* Make sure hKey is closed.
*/
if (hKey)
ZwClose(hKey);
/*
* Append the ending NULL.
*/
if (lpKeys)
lpKeys[cchSize] = 0;
*lpReturnedString = lpKeys;
return cchSize;
}
/*****************************************************************************\
* FastGetProfileStringW()
*
* Implements a fast version of the standard API using predefined registry
* section indecies (PMAP_) that reference lazy-opened, cached registry
* handles. FastCloseProfileUserMapping() should be called to clean up
* cached entries when fast profile calls are completed.
*
* This api does NOT implement the NULL lpKeyName feature of the real API.
*
* History:
* 02-Dec-1993 SanfordS Created.
\*****************************************************************************/
DWORD FastGetProfileStringW(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD cchBuf,
DWORD dwPolicyOnly
)
{
HANDLE hKey = NULL;
DWORD cbSize;
LONG Status;
UNICODE_STRING UnicodeString;
PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo;
DWORD dwPolicyFlags = gdwPolicyFlags | dwPolicyOnly;
UserAssert(idSection <= PMAP_LAST);
UserAssert(lpKeyName != NULL);
TryAgain:
if ((hKey = OpenCacheKeyEx(pProfileUserName,
idSection,
KEY_READ,
&dwPolicyFlags)) == NULL) {
#if DBG
if (PsGetCurrentProcessId() != gpidLogon) {
RIPMSG1(RIP_WARNING | RIP_NONAME, "%ws", lpKeyName);
}
#endif
if (dwPolicyOnly & POLICY_ONLY) {
return 0;
}
goto DefExit;
}
cbSize = (cchBuf * sizeof(WCHAR)) +
FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
if ((pKeyInfo = UserAllocPoolWithQuota(cbSize, TAG_PROFILE)) == NULL) {
goto DefExit;
}
RtlInitUnicodeString(&UnicodeString, lpKeyName);
Status = ZwQueryValueKey(hKey,
&UnicodeString,
KeyValuePartialInformation,
pKeyInfo,
cbSize,
&cbSize);
if (Status == STATUS_BUFFER_OVERFLOW) {
RIPMSG0(RIP_WARNING, "FastGetProfileStringW: Buffer overflow");
Status = STATUS_SUCCESS;
}
UserAssert(NT_SUCCESS(Status) || (Status == STATUS_OBJECT_NAME_NOT_FOUND));
if (NT_SUCCESS(Status)) {
if (pKeyInfo->DataLength >= sizeof(WCHAR)) {
((LPWSTR)(pKeyInfo->Data))[cchBuf - 1] = L'\0';
wcscpy(lpReturnedString, (LPWSTR)pKeyInfo->Data);
} else {
/*
* Appears to be a bug with empty strings - only first
* byte is set to NULL. (SAS)
*/
lpReturnedString[0] = TEXT('\0');
}
cchBuf = pKeyInfo->DataLength;
UserFreePool(pKeyInfo);
ZwClose(hKey);
/*
* data length includes terminating zero [bodind]
*/
return (cchBuf / sizeof(WCHAR));
} else if (dwPolicyFlags) {
UserFreePool(pKeyInfo);
ZwClose(hKey);
goto TryAgain;
}
UserFreePool(pKeyInfo);
DefExit:
/*
* Make sure the key is closed.
*/
if (hKey)
ZwClose(hKey);
/*
* wcscopy copies terminating zero, but the length returned by
* wcslen does not, so add 1 to be consistent with success
* return [bodind]
*/
if (lpDefault != NULL) {
cchBuf = wcslen(lpDefault) + 1;
RtlCopyMemory(lpReturnedString, lpDefault, cchBuf * sizeof(WCHAR));
return cchBuf;
}
return 0;
}
/*****************************************************************************\
* FastGetProfileIntW()
*
* Implements a fast version of the standard API using predefined registry
* section indecies (PMAP_) that reference lazy-opened, cached registry
* handles. FastCloseProfileUserMapping() should be called to clean up
* cached entries when fast profile calls are completed.
*
* History:
* 02-Dec-1993 SanfordS Created.
\*****************************************************************************/
BOOL FastGetProfileIntW(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
LPCWSTR lpKeyName,
UINT nDefault,
PUINT puiReturn,
DWORD dwPolicyOnly
)
{
WCHAR ValueBuf[40];
UNICODE_STRING Value;
UINT ReturnValue;
UserAssert(idSection <= PMAP_LAST);
UserAssert(puiReturn);
if (!FastGetProfileStringW(pProfileUserName,
idSection,
lpKeyName,
NULL,
ValueBuf,
sizeof(ValueBuf) / sizeof(WCHAR),
dwPolicyOnly
)) {
if (dwPolicyOnly & POLICY_ONLY) {
return FALSE;
}
*puiReturn = nDefault;
return TRUE;
}
/*
* Convert string to int.
*/
RtlInitUnicodeString(&Value, ValueBuf);
RtlUnicodeStringToInteger(&Value, 10, &ReturnValue);
*puiReturn = ReturnValue;
return TRUE;
}
/*****************************************************************************\
* FastWriteProfileStringW
*
* Implements a fast version of the standard API using predefined registry
* section indecies (PMAP_) that reference lazy-opened, cached registry
* handles. FastCloseProfileUserMapping() should be called to clean up
* cached entries when fast profile calls are completed.
*
* History:
* 02-Dec-1993 SanfordS Created.
\*****************************************************************************/
BOOL FastWriteProfileStringW(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
LPCWSTR lpKeyName,
LPCWSTR lpString
)
{
HANDLE hKey;
LONG Status;
UNICODE_STRING UnicodeString;
UserAssert(idSection <= PMAP_LAST);
/*
* We shouldn't be writing values that are controlled by policy.
*/
if (idSection == PMAP_DESKTOP) {
UserAssert(!CheckDesktopPolicy(pProfileUserName, lpKeyName));
}
if ((hKey = OpenCacheKeyEx(pProfileUserName,
idSection,
KEY_WRITE,
NULL)) == NULL) {
RIPMSG1(RIP_WARNING | RIP_NONAME, "%ws", lpKeyName);
return FALSE;
}
RtlInitUnicodeString(&UnicodeString, lpKeyName);
Status = ZwSetValueKey(hKey,
&UnicodeString,
0,
REG_SZ,
(PVOID)lpString,
(wcslen(lpString) + 1) * sizeof(WCHAR));
ZwClose(hKey);
return (NT_SUCCESS(Status));
}
/*****************************************************************************\
* FastGetProfileIntFromID
*
* Just like FastGetProfileIntW except it reads the USER string table for the
* key name.
*
* History:
* 02-Dec-1993 SanfordS Created.
* 25-Feb-1995 BradG Added TWIPS -> Pixel conversion.
\*****************************************************************************/
BOOL FastGetProfileIntFromID(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
UINT idKey,
int def,
PINT pResult,
DWORD dwPolicyOnly
)
{
int result;
WCHAR szKey[80];
UserAssert(idSection <= PMAP_LAST);
ServerLoadString(hModuleWin, idKey, szKey, ARRAY_SIZE(szKey));
if (FastGetProfileIntW(pProfileUserName,idSection, szKey, def, &result, dwPolicyOnly))
{
/*
* If you change the below list of STR_* make sure you make a
* corresponding change in SetWindowMetricInt (rare.c)
*/
switch (idKey) {
case STR_BORDERWIDTH:
case STR_SCROLLWIDTH:
case STR_SCROLLHEIGHT:
case STR_CAPTIONWIDTH:
case STR_CAPTIONHEIGHT:
case STR_SMCAPTIONWIDTH:
case STR_SMCAPTIONHEIGHT:
case STR_MENUWIDTH:
case STR_MENUHEIGHT:
case STR_ICONHORZSPACING:
case STR_ICONVERTSPACING:
case STR_MINWIDTH:
case STR_MINHORZGAP:
case STR_MINVERTGAP:
/*
* Convert any registry values stored in TWIPS back to pixels
*/
if (result < 0)
result = MultDiv(-result, gpsi->dmLogPixels, 72 * 20);
break;
}
if (pResult) {
*pResult = result;
}
return TRUE;
}
return FALSE;
}
/*****************************************************************************\
* FastGetProfileIntFromID
*
* Just like FastGetProfileStringW except it reads the USER string table for
* the key name.
*
* History:
* 02-Dec-1993 SanfordS Created.
\*****************************************************************************/
DWORD FastGetProfileStringFromIDW(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
UINT idKey,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD cch,
DWORD dwPolicyOnly
)
{
WCHAR szKey[80];
UserAssert(idSection <= PMAP_LAST);
ServerLoadString(hModuleWin, idKey, szKey, ARRAY_SIZE(szKey));
return FastGetProfileStringW(pProfileUserName,
idSection,
szKey,
lpDefault,
lpReturnedString,
cch,
dwPolicyOnly);
}
/*****************************************************************************\
* FastWriteProfileValue
*
* History:
* 06/10/96 GerardoB Renamed and added uType parameter
\*****************************************************************************/
BOOL FastWriteProfileValue(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
LPCWSTR lpKeyName,
UINT uType,
LPBYTE lpStruct,
UINT cbSizeStruct
)
{
HANDLE hKey;
LONG Status;
UNICODE_STRING UnicodeString;
WCHAR szKey[SERVERSTRINGMAXSIZE];
UserAssert(idSection <= PMAP_LAST);
if (!IS_PTR(lpKeyName)) {
*szKey = (WCHAR)0;
ServerLoadString(hModuleWin, PTR_TO_ID(lpKeyName), szKey, ARRAY_SIZE(szKey));
UserAssert(*szKey != (WCHAR)0);
lpKeyName = szKey;
}
/*
* We shouldn't be writing values that are controlled by policy.
*/
if (idSection == PMAP_DESKTOP) {
UserAssert(!CheckDesktopPolicy(pProfileUserName, lpKeyName));
}
if ((hKey = OpenCacheKeyEx(pProfileUserName,
idSection,
KEY_WRITE,
NULL)) == NULL) {
RIPMSG1(RIP_WARNING, "FastWriteProfileValue: Failed to open cache-key (%ws)", lpKeyName);
return FALSE;
}
RtlInitUnicodeString(&UnicodeString, lpKeyName);
Status = ZwSetValueKey(hKey,
&UnicodeString,
0,
uType,
lpStruct,
cbSizeStruct);
ZwClose(hKey);
#if DBG
if (!NT_SUCCESS(Status)) {
RIPMSG3 (RIP_WARNING, "FastWriteProfileValue: ZwSetValueKey Failed. Status:%#lx idSection:%#lx KeyName:%s",
Status, idSection, UnicodeString.Buffer);
}
#endif
return (NT_SUCCESS(Status));
}
/*****************************************************************************\
* FastGetProfileValue
*
* If cbSizeReturn is 0, just return the size of the data
*
* History:
* 06/10/96 GerardoB Renamed
\*****************************************************************************/
DWORD FastGetProfileValue(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
LPCWSTR lpKeyName,
LPBYTE lpDefault,
LPBYTE lpReturn,
UINT cbSizeReturn,
DWORD dwPolicyOnly
)
{
HANDLE hKey;
UINT cbSize;
LONG Status;
UNICODE_STRING UnicodeString;
PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo;
WCHAR szKey[SERVERSTRINGMAXSIZE];
KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
DWORD dwPolicyFlags = gdwPolicyFlags | dwPolicyOnly;
UserAssert(idSection <= PMAP_LAST);
if (!IS_PTR(lpKeyName)) {
*szKey = (WCHAR)0;
ServerLoadString(hModuleWin, PTR_TO_ID(lpKeyName), szKey, ARRAY_SIZE(szKey));
UserAssert(*szKey != (WCHAR)0);
lpKeyName = szKey;
}
TryAgain:
if ((hKey = OpenCacheKeyEx(pProfileUserName,
idSection,
KEY_READ,
&dwPolicyFlags)) == NULL) {
// if hi-word of lpKeName is 0, it is a resource number not a string
if (!IS_PTR(lpKeyName))
RIPMSG1(RIP_WARNING, "FastGetProfileValue: Failed to open cache-key (%08x)", lpKeyName);
else
RIPMSG1(RIP_WARNING | RIP_NONAME, "%ws", lpKeyName);
if (dwPolicyOnly & POLICY_ONLY) {
return 0;
}
goto DefExit;
}
if (cbSizeReturn == 0) {
cbSize = sizeof(KeyInfo);
pKeyInfo = &KeyInfo;
} else {
cbSize = cbSizeReturn + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
if ((pKeyInfo = UserAllocPoolWithQuota(cbSize, TAG_PROFILE)) == NULL) {
goto DefExit;
}
}
RtlInitUnicodeString(&UnicodeString, lpKeyName);
Status = ZwQueryValueKey(hKey,
&UnicodeString,
KeyValuePartialInformation,
pKeyInfo,
cbSize,
&cbSize);
if (NT_SUCCESS(Status)) {
UserAssert(cbSizeReturn >= pKeyInfo->DataLength);
cbSize = pKeyInfo->DataLength;
RtlCopyMemory(lpReturn, pKeyInfo->Data, cbSize);
if (cbSizeReturn != 0) {
UserFreePool(pKeyInfo);
}
ZwClose(hKey);
return cbSize;
} else if ((Status == STATUS_BUFFER_OVERFLOW) && (cbSizeReturn == 0)) {
ZwClose(hKey);
return pKeyInfo->DataLength;
} else if (dwPolicyFlags) {
if (cbSizeReturn != 0) {
UserFreePool(pKeyInfo);
}
ZwClose(hKey);
goto TryAgain;
}
#if DBG
if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
RIPMSG3 (RIP_WARNING, "FastGetProfileValue: ZwQueryValueKey Failed. Status:%#lx idSection:%#lx KeyName:%s",
Status, idSection, UnicodeString.Buffer);
}
#endif
if (cbSizeReturn != 0) {
UserFreePool(pKeyInfo);
}
DefExit:
if (hKey)
ZwClose(hKey);
if (lpDefault) {
RtlMoveMemory(lpReturn, lpDefault, cbSizeReturn);
return cbSizeReturn;
}
return 0;
}
/*****************************************************************************\
* UT_FastGetProfileIntsW
*
* Repeatedly calls FastGetProfileIntW on the given table.
*
* History:
* 02-Dec-1993 SanfordS Created.
\*****************************************************************************/
BOOL FastGetProfileIntsW(PUNICODE_STRING pProfileUserName OPTIONAL,
PPROFINTINFO ppii,
DWORD dwPolicyOnly
)
{
WCHAR szKey[40];
while (ppii->idSection != 0) {
ServerLoadString(hModuleWin,
PTR_TO_ID(ppii->lpKeyName),
szKey,
ARRAY_SIZE(szKey));
FastGetProfileIntW(pProfileUserName,
ppii->idSection,
szKey,
ppii->nDefault,
ppii->puResult,
dwPolicyOnly);
ppii++;
}
return TRUE;
}
/***************************************************************************\
* UpdateWinIni
*
* Handles impersonation stuff and writes the given value to the registry.
*
* History:
* 28-Jun-1991 MikeHar Ported.
* 03-Dec-1993 SanfordS Used FastProfile calls, moved to profile.c
\***************************************************************************/
BOOL FastUpdateWinIni(PUNICODE_STRING pProfileUserName OPTIONAL,
UINT idSection,
UINT wKeyNameId,
LPWSTR lpszValue
)
{
WCHAR szKeyName[40];
BOOL bResult = FALSE;
UserAssert(idSection <= PMAP_LAST);
ServerLoadString(hModuleWin,
wKeyNameId,
szKeyName,
ARRAY_SIZE(szKeyName));
bResult = FastWriteProfileStringW(pProfileUserName,
idSection, szKeyName, lpszValue);
return bResult;
}