mirror of https://github.com/tongzx/nt5src
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.
1397 lines
28 KiB
1397 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Registry.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of the registry
|
|
wrapper class.
|
|
|
|
Notes:
|
|
|
|
Unicode only.
|
|
|
|
History:
|
|
|
|
01/29/2001 rparsons Created
|
|
03/02/2001 rparsons Major overhaul
|
|
|
|
--*/
|
|
|
|
#include "registry.h"
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocates memory from the heap
|
|
|
|
Arguments:
|
|
|
|
dwBytes - Number of bytes to allocate
|
|
This value will be multiplied
|
|
by the size of a WCHAR
|
|
|
|
Return Value:
|
|
|
|
A pointer to a block of memory
|
|
|
|
--*/
|
|
LPVOID
|
|
CRegistry::Malloc(
|
|
IN SIZE_T dwBytes
|
|
)
|
|
{
|
|
LPVOID lpReturn = NULL;
|
|
|
|
lpReturn = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwBytes*sizeof(WCHAR));
|
|
|
|
return (lpReturn);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Frees memory from the heap
|
|
|
|
Arguments:
|
|
|
|
lpMem - Pointer to a block of memory to free
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
void
|
|
CRegistry::Free(
|
|
IN LPVOID lpMem
|
|
)
|
|
{
|
|
if (NULL != lpMem) {
|
|
HeapFree(GetProcessHeap(), 0, lpMem);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the specified key or opens it if it
|
|
already exists
|
|
|
|
Arguments:
|
|
|
|
hKey - Handle to a predefined key
|
|
lpwSubKey - Path to the sub key to open
|
|
samDesired - The desired access rights
|
|
|
|
Return Value:
|
|
|
|
A handle to the key on success, NULL otherwise
|
|
|
|
--*/
|
|
HKEY
|
|
CRegistry::CreateKey(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN REGSAM samDesired
|
|
)
|
|
{
|
|
HKEY hReturnKey = NULL;
|
|
|
|
if (!hKey || !lpwSubKey || !samDesired) {
|
|
return NULL;
|
|
}
|
|
|
|
RegCreateKeyEx(hKey,
|
|
lpwSubKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
samDesired,
|
|
NULL,
|
|
&hReturnKey,
|
|
0);
|
|
|
|
return (hReturnKey);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Opens the specified key
|
|
|
|
Arguments:
|
|
|
|
hKey - Handle to a predefined key
|
|
lpwSubKey - Path to the sub key to open
|
|
samDesired - The desired access rights
|
|
|
|
Return Value:
|
|
|
|
A handle to the key on success, NULL otherwise
|
|
|
|
--*/
|
|
HKEY
|
|
CRegistry::OpenKey(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN REGSAM samDesired
|
|
)
|
|
{
|
|
HKEY hReturnKey = NULL;
|
|
|
|
if (!hKey || !lpwSubKey || !samDesired) {
|
|
return NULL;
|
|
}
|
|
|
|
RegOpenKeyEx(hKey,
|
|
lpwSubKey,
|
|
0,
|
|
samDesired,
|
|
&hReturnKey);
|
|
|
|
return (hReturnKey);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Closes the specified key handle
|
|
|
|
Arguments:
|
|
|
|
hKey - Handle of the key to close
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::CloseKey(
|
|
IN HKEY hKey
|
|
)
|
|
{
|
|
LONG lResult = 0;
|
|
|
|
lResult = RegCloseKey(hKey);
|
|
|
|
return (lResult == ERROR_SUCCESS ? TRUE : FALSE);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets a size for a specified value name
|
|
|
|
Arguments:
|
|
|
|
hKey - Open key handle (not predefined)
|
|
lpwValueName - Name of data value
|
|
lpType - Receives the type of data
|
|
|
|
Return Value:
|
|
|
|
Number of bytes the value occupies
|
|
|
|
--*/
|
|
DWORD
|
|
CRegistry::GetStringSize(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwValueName,
|
|
OUT LPDWORD lpType OPTIONAL
|
|
)
|
|
{
|
|
DWORD cbSize = 0;
|
|
|
|
if (!hKey || !lpwValueName) {
|
|
return 0;
|
|
}
|
|
|
|
RegQueryValueEx(hKey,
|
|
lpwValueName,
|
|
0,
|
|
lpType,
|
|
NULL,
|
|
&cbSize);
|
|
|
|
return (cbSize);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieves a string value from the registry
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwValueName - Name of data value
|
|
fPredefined - Flag to indicate if a predefined
|
|
key handle was passed
|
|
|
|
Return Value:
|
|
|
|
The requested value data on success, NULL otherwise
|
|
|
|
--*/
|
|
LPWSTR
|
|
CRegistry::GetString(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwValueName,
|
|
IN BOOL fPredefined
|
|
)
|
|
{
|
|
DWORD cbSize = 0;
|
|
BOOL fResult = FALSE;
|
|
LONG lResult = 0;
|
|
LPWSTR lpwReturn = NULL;
|
|
HKEY hLocalKey = NULL;
|
|
|
|
if (!hKey || !lpwValueName) {
|
|
return NULL;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
if (fPredefined) {
|
|
|
|
//
|
|
// We'll need to open the key for them
|
|
//
|
|
hLocalKey = this->OpenKey(hKey, lpwSubKey, KEY_QUERY_VALUE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the required string size and allocate
|
|
// memory for the actual call
|
|
//
|
|
cbSize = this->GetStringSize(hLocalKey, lpwValueName, NULL);
|
|
|
|
if (0 == cbSize) {
|
|
__leave;
|
|
}
|
|
|
|
lpwReturn = (LPWSTR) this->Malloc(cbSize*sizeof(WCHAR));
|
|
|
|
if (NULL == lpwReturn) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Make the actual call to get the data
|
|
//
|
|
lResult = RegQueryValueEx(hLocalKey,
|
|
lpwValueName,
|
|
0,
|
|
NULL,
|
|
(LPBYTE) lpwReturn,
|
|
&cbSize);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
}
|
|
|
|
return (fResult ? lpwReturn : NULL);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieves a DWORD value from the registry
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwValueName - Name of data value
|
|
lpdwData - Pointer to store the value
|
|
fPredefined - Flag to indicate if a predefined
|
|
key handle was passed
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise.
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::GetDword(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwValueName,
|
|
IN LPDWORD lpdwData,
|
|
IN BOOL fPredefined
|
|
)
|
|
{
|
|
DWORD cbSize = MAX_PATH;
|
|
BOOL fResult = FALSE;
|
|
LONG lResult = 0;
|
|
HKEY hLocalKey = NULL;
|
|
|
|
if (!hKey || !lpwValueName || !lpdwData) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
if (fPredefined) {
|
|
|
|
//
|
|
// We'll need to open the key for them
|
|
//
|
|
hLocalKey = this->OpenKey(hKey, lpwSubKey, KEY_QUERY_VALUE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call to get the data
|
|
//
|
|
lResult = RegQueryValueEx(hLocalKey,
|
|
lpwValueName,
|
|
0,
|
|
NULL,
|
|
(LPBYTE) lpdwData,
|
|
&cbSize);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
|
|
} //finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets a DWORD value in the registry
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwValueName - Name of data value
|
|
dwData - Value to store
|
|
fPredefined - Flag to indicate if a predefined
|
|
key handle was passed
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::SetDword(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwValueName,
|
|
IN DWORD dwData,
|
|
IN BOOL fPredefined
|
|
)
|
|
{
|
|
LONG lResult = 0;
|
|
BOOL fResult = FALSE;
|
|
HKEY hLocalKey = NULL;
|
|
|
|
if (!hKey || !lpwValueName) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
if (fPredefined) {
|
|
|
|
//
|
|
// We'll need to open the key for them
|
|
//
|
|
hLocalKey = this->OpenKey(hKey, lpwSubKey, KEY_SET_VALUE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call to set the data
|
|
//
|
|
lResult = RegSetValueEx(hLocalKey,
|
|
lpwValueName,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &dwData,
|
|
sizeof(DWORD));
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets a string value in the registry
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwValueName - Name of data value
|
|
lpwData - Value to store
|
|
fPredefined - Flag to indicate if a predefined
|
|
key handle was passed
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise.
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::SetString(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwValueName,
|
|
IN LPWSTR lpwData,
|
|
IN BOOL fPredefined
|
|
)
|
|
{
|
|
HKEY hLocalKey = NULL;
|
|
BOOL fResult = FALSE;
|
|
LONG lResult = 0;
|
|
|
|
if (!hKey || !lpwValueName) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
if (fPredefined) {
|
|
|
|
//
|
|
// We'll need to open the key for them
|
|
//
|
|
hLocalKey = this->OpenKey(hKey, lpwSubKey, KEY_SET_VALUE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
lResult = RegSetValueEx(hLocalKey,
|
|
lpwValueName,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE) lpwData,
|
|
(wcslen(lpwData)+1)*sizeof(WCHAR));
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deletes the specified value from the registry
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwValueName - Name of the value to delete
|
|
fPredefined - Flag to indicate if a predefined
|
|
key handle was passed
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise.
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::DeleteRegistryString(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwValueName,
|
|
IN BOOL fPredefined
|
|
)
|
|
{
|
|
HKEY hLocalKey = NULL;
|
|
BOOL fResult = FALSE;
|
|
LONG lResult = 0;
|
|
|
|
if (!hKey || !lpwValueName) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
if (fPredefined) {
|
|
|
|
//
|
|
// We'll need to open the key for them
|
|
//
|
|
hLocalKey = this->OpenKey(hKey, lpwSubKey, KEY_WRITE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete the value
|
|
//
|
|
lResult = RegDeleteValue(hLocalKey,
|
|
lpwValueName);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deletes the specified key from the registry
|
|
(At this time, subkeys are not allowed)
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwSubKeyName - Name of the subkey
|
|
fPredefined - Flag to indicate if a predefined
|
|
key handle was passed
|
|
fFlush - Flag to indicate if we should flush the key
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise.
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::DeleteRegistryKey(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwKey,
|
|
IN LPCWSTR lpwSubKeyName,
|
|
IN BOOL fPredefined,
|
|
IN BOOL fFlush
|
|
)
|
|
{
|
|
HKEY hLocalKey = NULL;
|
|
BOOL fResult = FALSE;
|
|
LONG lResult = 0;
|
|
|
|
if (!hKey) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
if (fPredefined) {
|
|
|
|
//
|
|
// We'll need to open the key for them
|
|
//
|
|
hLocalKey = this->OpenKey(hKey, lpwKey, KEY_WRITE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete the value
|
|
//
|
|
lResult = RegDeleteKey(hLocalKey,
|
|
lpwSubKeyName);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
if (fFlush) {
|
|
RegFlushKey(hLocalKey);
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adds a string to a REG_MULTI_SZ key
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwValueName - Name of the value
|
|
lpwEntry - Name of entry to add
|
|
fPredefined - Flag to indicate if a predefined
|
|
key handle was passed
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::AddStringToMultiSz(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwValueName,
|
|
IN LPCWSTR lpwEntry,
|
|
IN BOOL fPredefined
|
|
)
|
|
{
|
|
int nLen = 0;
|
|
HKEY hLocalKey = NULL;
|
|
DWORD cbSize = 0, dwType = 0;
|
|
LPWSTR lpwNew = NULL, lpwData = NULL;
|
|
BOOL fResult = FALSE;
|
|
LONG lResult = 0;
|
|
|
|
if (!hKey || !lpwEntry) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
if (fPredefined) {
|
|
|
|
//
|
|
// We'll need to open the key for them
|
|
//
|
|
hLocalKey = this->OpenKey(hKey,
|
|
lpwSubKey,
|
|
KEY_QUERY_VALUE | KEY_WRITE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the required string size and allocate
|
|
// memory for the actual call
|
|
//
|
|
cbSize = this->GetStringSize(hLocalKey, lpwValueName, &dwType);
|
|
|
|
if ((0 == cbSize) || (dwType != REG_MULTI_SZ)) {
|
|
__leave;
|
|
}
|
|
|
|
lpwData = (LPWSTR) this->Malloc(cbSize * sizeof(WCHAR));
|
|
|
|
if (NULL == lpwData) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Get the actual data
|
|
//
|
|
lResult = RegQueryValueEx(hLocalKey,
|
|
lpwValueName,
|
|
0,
|
|
0,
|
|
(LPBYTE) lpwData,
|
|
&cbSize);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
|
|
lpwNew = lpwData;
|
|
|
|
while (*lpwNew) {
|
|
|
|
nLen = wcslen(lpwNew);
|
|
|
|
//
|
|
// Move to the next string
|
|
//
|
|
lpwNew += nLen + 1;
|
|
|
|
//
|
|
// At end of list of strings, append here
|
|
//
|
|
if (!*lpwNew) {
|
|
|
|
wcscpy(lpwNew, lpwEntry);
|
|
lpwNew += wcslen(lpwEntry) + 1;
|
|
*lpwNew = 0;
|
|
nLen = this->ListStoreLen(lpwData);
|
|
|
|
lResult = RegSetValueEx(hLocalKey,
|
|
lpwValueName,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
(const BYTE*) lpwData,
|
|
nLen);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
__leave;
|
|
|
|
} else {
|
|
fResult = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (lpwData) {
|
|
this->Free(lpwData);
|
|
}
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes a string from a REG_MULTI_SZ key
|
|
|
|
Arguments:
|
|
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwValueName - Name of the value
|
|
lpwEntry - Name of entry to remove
|
|
fPredefined - Flag to indicate if a predefined
|
|
key handle was passed
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::RemoveStringFromMultiSz(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwValueName,
|
|
IN LPCWSTR lpwEntry,
|
|
IN BOOL fPredefined
|
|
)
|
|
{
|
|
LPBYTE lpBuf = NULL;
|
|
HKEY hLocalKey = NULL;
|
|
WCHAR *pFirst = NULL;
|
|
WCHAR *pSecond = NULL;
|
|
DWORD dwType = 0, cbSize = 0;
|
|
DWORD dwNameLen = 0, dwNameOffset = 0, dwSize = 0;
|
|
BOOL fResult = FALSE;
|
|
LONG lResult = 0;
|
|
|
|
if (!hKey || !lpwEntry) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
if (fPredefined) {
|
|
|
|
//
|
|
// We'll need to open the key for them
|
|
//
|
|
hLocalKey = this->OpenKey(hKey,
|
|
lpwSubKey,
|
|
KEY_QUERY_VALUE | KEY_WRITE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the required string size and allocate
|
|
// memory for the actual call
|
|
//
|
|
cbSize = this->GetStringSize(hLocalKey, lpwValueName, &dwType);
|
|
|
|
if ((0 == cbSize) || (dwType != REG_MULTI_SZ)) {
|
|
__leave;
|
|
}
|
|
|
|
lpBuf = (LPBYTE) this->Malloc(cbSize * sizeof(WCHAR));
|
|
|
|
if (NULL == lpBuf) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Get the actual data
|
|
//
|
|
lResult = RegQueryValueEx(hLocalKey,
|
|
lpwValueName,
|
|
0,
|
|
0,
|
|
(LPBYTE) lpBuf,
|
|
&cbSize);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Attempt to find the string we're looking for
|
|
//
|
|
for (pFirst = (WCHAR*) lpBuf; *pFirst; pFirst += dwNameLen) {
|
|
|
|
dwNameLen = wcslen(pFirst) + 1; // Length of name plus NULL
|
|
dwNameOffset += dwNameLen;
|
|
|
|
//
|
|
// Check for a match
|
|
//
|
|
if (_wcsicmp(pFirst, lpwEntry) == 0) {
|
|
|
|
dwSize = wcslen(pFirst) + 1; // Length of name
|
|
pSecond = (WCHAR*) pFirst + dwSize;
|
|
|
|
while(*pSecond)
|
|
while(*pSecond)
|
|
*pFirst++ = *pSecond++;
|
|
*pFirst++ = *pSecond++;
|
|
|
|
*pFirst = '\0';
|
|
|
|
//
|
|
// Found a match - update the key
|
|
//
|
|
lResult = RegSetValueEx(hLocalKey,
|
|
lpwValueName,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
(const BYTE*) lpBuf,
|
|
cbSize -
|
|
(dwSize*sizeof(WCHAR)));
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
__leave;
|
|
|
|
} else {
|
|
fResult = TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (lpBuf) {
|
|
this->Free(lpBuf);
|
|
}
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines if the specified subkey is present
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
|
|
Return Value:
|
|
|
|
TRUE if it's present, FALSE otherwise.
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::IsRegistryKeyPresent(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey
|
|
)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hLocalKey = NULL;
|
|
|
|
if (!hKey || !lpwSubKey) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
hLocalKey = hKey;
|
|
|
|
//
|
|
// Check for the presence of the key
|
|
//
|
|
hLocalKey = this->OpenKey(hKey,
|
|
lpwSubKey,
|
|
KEY_QUERY_VALUE);
|
|
|
|
if (NULL == hLocalKey) {
|
|
__leave;
|
|
|
|
} else {
|
|
fResult = TRUE;
|
|
}
|
|
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey)
|
|
RegCloseKey(hLocalKey);
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Restores the specified registry key
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwFileName - Path & name of the file to restore
|
|
fGrantPrivs - Flag to indicate if we should grant
|
|
privileges to the user
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::RestoreKey(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwFileName,
|
|
IN BOOL fGrantPrivs
|
|
)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hLocalKey = NULL;
|
|
LONG lResult = 0;
|
|
|
|
if (!hKey || !lpwSubKey || !lpwFileName) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
//
|
|
// If necessary, grant privileges for the restore
|
|
//
|
|
if (fGrantPrivs) {
|
|
this->ModifyTokenPrivilege(L"SeRestorePrivilege", TRUE);
|
|
}
|
|
|
|
lResult = RegCreateKeyEx(hKey,
|
|
lpwSubKey,
|
|
0,
|
|
NULL,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hLocalKey,
|
|
0);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Restore the key from the specified file
|
|
//
|
|
lResult = RegRestoreKey(hLocalKey,
|
|
lpwFileName,
|
|
REG_FORCE_RESTORE);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
RegFlushKey(hLocalKey);
|
|
|
|
fResult = TRUE;
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
|
|
if (fGrantPrivs) {
|
|
this->ModifyTokenPrivilege(L"SeRestorePrivilege", FALSE);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Makes a backup of the specified registry key
|
|
|
|
Arguments:
|
|
|
|
hKey - Predefined or open key handle
|
|
lpwSubKey - Path to the subkey
|
|
lpwFileName - Path & name of the file to restore
|
|
fGrantPrivs - Flag to indicate if we should grant
|
|
privileges to the user
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::BackupRegistryKey(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR lpwSubKey,
|
|
IN LPCWSTR lpwFileName,
|
|
IN BOOL fGrantPrivs
|
|
)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hLocalKey = NULL;
|
|
DWORD dwDisposition = 0;
|
|
DWORD dwLastError = 0;
|
|
LONG lResult = 0;
|
|
|
|
if (!hKey || !lpwSubKey || !lpwFileName) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
if (fGrantPrivs) {
|
|
ModifyTokenPrivilege(L"SeBackupPrivilege", TRUE);
|
|
}
|
|
|
|
lResult = RegCreateKeyEx(hKey,
|
|
lpwSubKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_BACKUP_RESTORE,
|
|
KEY_QUERY_VALUE, // this argument is ignored
|
|
NULL,
|
|
&hLocalKey,
|
|
&dwDisposition);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Verify that we didn't create a new key
|
|
//
|
|
if (REG_CREATED_NEW_KEY == dwDisposition) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Save the key to the file
|
|
//
|
|
lResult = RegSaveKey(hLocalKey,
|
|
lpwFileName,
|
|
NULL);
|
|
|
|
if (ERROR_SUCCESS != lResult) {
|
|
__leave;
|
|
|
|
} else {
|
|
fResult = TRUE;
|
|
}
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hLocalKey) {
|
|
RegCloseKey(hLocalKey);
|
|
}
|
|
|
|
if (fGrantPrivs) {
|
|
this->ModifyTokenPrivilege(L"SeBackupPrivilege", FALSE);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function that calculates the size of MULTI_SZ string.
|
|
|
|
Arguments:
|
|
|
|
lpwList - MULTI_SZ string.
|
|
|
|
Return Value:
|
|
|
|
Size of the string.
|
|
|
|
--*/
|
|
int
|
|
CRegistry::ListStoreLen(
|
|
IN LPWSTR lpwList
|
|
)
|
|
{
|
|
int nStoreLen = 2, nLen = 0;
|
|
|
|
if (NULL == lpwList) {
|
|
return 0;
|
|
}
|
|
|
|
while (*lpwList) {
|
|
|
|
nLen = wcslen(lpwList) + 1;
|
|
nStoreLen += nLen * 2;
|
|
lpwList += nLen;
|
|
}
|
|
|
|
return (nStoreLen);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enables or disables a specified privilege
|
|
|
|
Arguments:
|
|
|
|
lpwPrivilege - The name of the privilege
|
|
|
|
fEnable - A flag to indicate if the
|
|
privilege should be enabled
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise
|
|
|
|
--*/
|
|
BOOL
|
|
CRegistry::ModifyTokenPrivilege(
|
|
IN LPCWSTR lpwPrivilege,
|
|
IN BOOL fEnable
|
|
)
|
|
{
|
|
HANDLE hToken = NULL;
|
|
LUID luid;
|
|
BOOL fResult = FALSE;
|
|
TOKEN_PRIVILEGES tp;
|
|
|
|
if (NULL == lpwPrivilege) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
//
|
|
// Get a handle to the access token associated with the current process
|
|
//
|
|
OpenProcessToken(GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
&hToken);
|
|
|
|
if (NULL == hToken) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Obtain a LUID for the specified privilege
|
|
//
|
|
if (!LookupPrivilegeValue(NULL, lpwPrivilege, &luid)) {
|
|
__leave;
|
|
}
|
|
|
|
tp.PrivilegeCount = 1;
|
|
tp.Privileges[0].Luid = luid;
|
|
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
|
|
|
|
//
|
|
// Modify the access token
|
|
//
|
|
if (!AdjustTokenPrivileges(hToken,
|
|
FALSE,
|
|
&tp,
|
|
sizeof(TOKEN_PRIVILEGES),
|
|
NULL,
|
|
NULL)) {
|
|
__leave;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
} // try
|
|
|
|
__finally {
|
|
|
|
if (hToken) {
|
|
CloseHandle(hToken);
|
|
}
|
|
|
|
} // finally
|
|
|
|
return (fResult);
|
|
}
|