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.
 
 
 
 
 
 

1856 lines
54 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
registry.c
Abstract:
Miscellaneous routines for the Registry Operation
Author:
Xiaofeng Zang (xiaoz) 17-Sep-2001 Created(most code stole from base\fs\utils\regedit)
Revision History:
<alias> <date> <comments>
xiaoz 09/25/01 add RegResetValue
--*/
#include "StdAfx.h"
#include "clmt.h"
#include <strsafe.h>
#define MAXVALUENAME_LENGTH 256
#define MAXKEYNAME 256
#define ExtraAllocLen(Type) (IsRegStringType((Type)) ? sizeof(TCHAR) : 0)
#define IsRegStringType(x) (((x) == REG_SZ) || ((x) == REG_EXPAND_SZ) || ((x) == REG_MULTI_SZ))
#define TEXT_REG_RESET_PER_USER_SECTION TEXT("RegistryResetPerUser")
#define TEXT_REG_RESET_PER_SYSTEM_SECTION TEXT("RegistryResetPerSystem")
HRESULT MigrateRegSchemes(HINF, HKEY, LPCTSTR);
HRESULT DoRegReset(HKEY, HINF, LPCTSTR, LPCTSTR);
HRESULT RegBinaryDataReset (HKEY, LPTSTR, LPTSTR, PREG_STRING_REPLACE, LPTSTR[]);
HRESULT RegValueDataReset(HKEY, LPTSTR, LPTSTR, LPTSTR, LPTSTR[]);
HRESULT RegValueNameReset(HKEY, LPTSTR, LPTSTR, LPTSTR, LPTSTR[]);
HRESULT RegKeyNameReset(HKEY, LPTSTR, LPTSTR, LPTSTR, LPTSTR[]);
HRESULT RegWideMatchReset(HKEY, LPTSTR, LPTSTR, LPTSTR, LPTSTR[]);
BOOL bIsValidRegStr(DWORD dwType, DWORD cbLen);
/*******************************************************************************
*
* CopyRegistry
*
* DESCRIPTION:
*
* PARAMETERS:
* hSourceKey,
* hDestinationKey,
*
*************************************************************************************/
BOOL
CopyRegistry(
HKEY hSourceKey,
HKEY hDestinationKey
)
{
BOOL fSuccess = TRUE;
DWORD EnumIndex;
DWORD cchValueName;
DWORD cbValueData;
DWORD Type;
HKEY hSourceSubKey;
HKEY hDestinationSubKey;
TCHAR ValueNameBuffer[MAXVALUENAME_LENGTH];
TCHAR KeyNameBuffer[MAXKEYNAME];
//
// Copy all of the value names and their data.
//
EnumIndex = 0;
while (TRUE)
{
PBYTE pbValueData;
cchValueName = ARRAYSIZE(ValueNameBuffer);
// VALUE DATA
// Query for data size
if (RegEnumValue(hSourceKey, EnumIndex++, ValueNameBuffer,
&cchValueName, NULL, &Type, NULL, &cbValueData) != ERROR_SUCCESS)
{
break;
}
// allocate memory for data
pbValueData = LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type));
if (pbValueData)
{
if (My_QueryValueEx(hSourceKey, ValueNameBuffer,
NULL, &Type, pbValueData, &cbValueData) == ERROR_SUCCESS)
{
RegSetValueEx(hDestinationKey, ValueNameBuffer, 0, Type,
pbValueData, cbValueData);
}
else
{
fSuccess = FALSE;
}
LocalFree(pbValueData);
}
else
{
fSuccess = FALSE;
}
}
if (fSuccess)
{
//
// Copy all of the subkeys and recurse into them.
//
EnumIndex = 0;
while (TRUE) {
if (RegEnumKey(hSourceKey, EnumIndex++, KeyNameBuffer, MAXKEYNAME) !=
ERROR_SUCCESS)
break;
if(RegOpenKeyEx(hSourceKey,KeyNameBuffer,0,KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,&hSourceSubKey) ==
ERROR_SUCCESS) {
if (RegCreateKey(hDestinationKey, KeyNameBuffer,
&hDestinationSubKey) == ERROR_SUCCESS) {
CopyRegistry(hSourceSubKey, hDestinationSubKey);
RegCloseKey(hDestinationSubKey);
}
RegCloseKey(hSourceSubKey);
}
}
}
return fSuccess;
}
/*******************************************************************************
*
* RegDeleteKeyRecursive
*
* DESCRIPTION:
* Adapted from \\kernel\razzle3,mvdm\wow32\wshell.c,WOWRegDeleteKey().
* The Windows 95 implementation of RegDeleteKey recursively deletes all
* the subkeys of the specified registry branch, but the NT implementation
* only deletes leaf keys.
*
* PARAMETERS:
* (see below)
*
*******************************************************************************/
LONG
RegDeleteKeyRecursive(
IN HKEY hKey,
IN LPCTSTR lpszSubKey
)
/*++
Routine Description:
There is a significant difference between the Win3.1 and Win32
behavior of RegDeleteKey when the key in question has subkeys.
The Win32 API does not allow you to delete a key with subkeys,
while the Win3.1 API deletes a key and all its subkeys.
This routine is a recursive worker that enumerates the subkeys
of a given key, applies itself to each one, then deletes itself.
It specifically does not attempt to deal rationally with the
case where the caller may not have access to some of the subkeys
of the key to be deleted. In this case, all the subkeys which
the caller can delete will be deleted, but the api will still
return ERROR_ACCESS_DENIED.
Arguments:
hKey - Supplies a handle to an open registry key.
lpszSubKey - Supplies the name of a subkey which is to be deleted
along with all of its subkeys.
Return Value:
ERROR_SUCCESS - entire subtree successfully deleted.
ERROR_ACCESS_DENIED - given subkey could not be deleted.
--*/
{
DWORD i;
HKEY Key;
LONG Status;
DWORD ClassLength=0;
DWORD SubKeys;
DWORD MaxSubKey;
DWORD MaxClass;
DWORD Values;
DWORD MaxValueName;
DWORD MaxValueData;
DWORD SecurityLength;
FILETIME LastWriteTime;
LPTSTR NameBuffer;
//
// First open the given key so we can enumerate its subkeys
//
Status = RegOpenKeyEx(hKey,
lpszSubKey,
0,
KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
&Key);
if (Status != ERROR_SUCCESS)
{
//
// possibly we have delete access, but not enumerate/query.
// So go ahead and try the delete call, but don't worry about
// any subkeys. If we have any, the delete will fail anyway.
//
return(RegDeleteKey(hKey,lpszSubKey));
}
//
// Use RegQueryInfoKey to determine how big to allocate the buffer
// for the subkey names.
//
Status = RegQueryInfoKey(Key,
NULL,
&ClassLength,
0,
&SubKeys,
&MaxSubKey,
&MaxClass,
&Values,
&MaxValueName,
&MaxValueData,
&SecurityLength,
&LastWriteTime);
if ((Status != ERROR_SUCCESS) &&
(Status != ERROR_MORE_DATA) &&
(Status != ERROR_INSUFFICIENT_BUFFER))
{
RegCloseKey(Key);
return(Status);
}
NameBuffer = (LPTSTR) LocalAlloc(LPTR, (MaxSubKey + 1)*sizeof(TCHAR));
if (NameBuffer == NULL)
{
RegCloseKey(Key);
return(ERROR_NOT_ENOUGH_MEMORY);
}
//
// Enumerate subkeys and apply ourselves to each one.
//
i=0;
do
{
Status = RegEnumKey(Key,
i,
NameBuffer,
MaxSubKey+1);
if (Status == ERROR_SUCCESS)
{
Status = RegDeleteKeyRecursive(Key,NameBuffer);
}
if (Status != ERROR_SUCCESS)
{
//
// Failed to delete the key at the specified index. Increment
// the index and keep going. We could probably bail out here,
// since the api is going to fail, but we might as well keep
// going and delete everything we can.
//
++i;
}
} while ( (Status != ERROR_NO_MORE_ITEMS) && (i < SubKeys) );
LocalFree((HLOCAL) NameBuffer);
RegCloseKey(Key);
return(RegDeleteKey(hKey,lpszSubKey));
}
//-----------------------------------------------------------------------------
//
// Function: RegRenameValueName
//
// Synopsis: Rename the value name in registry by copying the data from
// old value to new value, then delete the old value.
//
// Returns: Win32 Error Code
//
// History: 09/17/2001 Xiaoz Created
// 02/14/2001 rerkboos Add dynamic buffer allocation
// 03/05/2002 rerkboos Code clean up
//
// Notes: hKey parameter must have been opened with KEY_SET_VALUE access
//
//-----------------------------------------------------------------------------
LONG RegRenameValueName(
HKEY hKey, // Handle to registry key containing the value
LPCTSTR lpOldValName, // Old value name to be changed
LPCTSTR lpNewValName // New value name
)
{
LONG lResult;
DWORD dwType;
DWORD cbData;
LPBYTE lpData = NULL;
DWORD ClassLength=0;
DWORD SubKeys;
DWORD MaxSubKey;
DWORD MaxClass;
DWORD Values;
DWORD MaxValueName;
DWORD MaxValueData;
DWORD SecurityLength;
FILETIME LastWriteTime;
if (lpOldValName == NULL || lpNewValName == NULL)
{
// invalid parameter
return ERROR_INVALID_PARAMETER;
}
if (MyStrCmpI(lpOldValName, lpNewValName) == LSTR_EQUAL)
{
return ERROR_SUCCESS;
}
//
// Get the registry info under hkey
//
lResult = RegQueryInfoKey(hKey,
NULL,
&ClassLength,
0,
&SubKeys,
&MaxSubKey,
&MaxClass,
&Values,
&MaxValueName,
&MaxValueData,
&SecurityLength,
&LastWriteTime);
if ((lResult != ERROR_SUCCESS) &&
(lResult != ERROR_MORE_DATA) &&
(lResult != ERROR_INSUFFICIENT_BUFFER))
{
goto Cleanup;
}
MaxValueData += 2*sizeof(TCHAR);
if (NULL == (lpData = malloc(MaxValueData)))
{
lResult = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// Query the value of old value name
//
cbData = MaxValueData;
lResult = My_QueryValueEx(hKey,
lpOldValName,
0,
&dwType,
lpData,
&cbData);
if (ERROR_SUCCESS != lResult)
{
goto Cleanup;
}
//
// Create a new value name using old data
//
lResult = RegSetValueEx(hKey,
lpNewValName,
0,
dwType,
lpData,
cbData);
if (lResult != ERROR_SUCCESS)
{
DPF(dlError,
TEXT("RegRenameValueName: Failed to create value [%s]"),
lpNewValName);
goto Cleanup;
}
//
// Delete the old value name, after successfully created a new one
//
lResult = RegDeleteValue(hKey, lpOldValName);
if (lResult != ERROR_SUCCESS)
{
DPF(dlError,
TEXT("RegRenameValueName: Cannot delete old value [%s]"),
lpOldValName);
// if we cannot delete old value, new value shouldn't be created
RegDeleteValue(hKey, lpNewValName);
goto Cleanup;
}
Cleanup:
// BUG 561546: Free the allocated buffer
if (lpData)
{
free(lpData);
}
return lResult;
}
/**
Routine Description:
RegResetValue check whether the current value equals szOldValue,
if yes , change the value to szNewValue,otherwise it does not do anything
however if szOldValue is NULL, then , it will always set value
if szOldValue is "", then , it will add this value
Arguments:
hKeyRoot - Specifies the root of registry key
szKeyName - Specifies registry key path
szValueName - Specifies the name of value field
dwType - specifies string type, should be one of REG_SZ/REG_EXPAND_SZ/REG_MULTI_SZ
szOldValue - specifies the expected old value
szNewValue - specifies the new value
Return Value:
TRUE - Success
FALSE - Failure
--*/
LONG RegResetValue(
HKEY hKeyRoot, // Root of registry key
LPCTSTR lpKeyName, // Registry key path
LPCTSTR lpValueName, // Name of value field
DWORD dwType, // Value type
LPCTSTR lpOldValue, // Expected old value
LPCTSTR lpNewValue, // New value to be set
DWORD dwValueSize, // New value data size
LPCTSTR lpszUsersid // User Sid
)
{
LONG lResult;
HKEY hKey = NULL;
DWORD dw;
DWORD ClassLength=0;
DWORD SubKeys;
DWORD MaxSubKey;
DWORD MaxClass;
DWORD Values;
DWORD MaxValueName;
DWORD MaxValueData;
DWORD SecurityLength;
FILETIME LastWriteTime;
LPTSTR szData = NULL;
DWORD dwSize = 0;
BOOL bTry = TRUE;
BOOL bNeedCLoseKey = TRUE;
//if lpOldValue is NULL , mean Set to lpNewValue and do not care the old one
if ( !lpOldValue || !lpOldValue[0])
{
if (!lpKeyName)
{
hKey = hKeyRoot;
bNeedCLoseKey = FALSE;
goto SkipKeyOpen;
}
if (lpOldValue)
{
DWORD dwDisposition;
TryAgain1:
lResult = RegCreateKeyEx(hKeyRoot,
lpKeyName,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisposition);
if (lResult != ERROR_SUCCESS)
{
if (bTry && lResult == ERROR_ACCESS_DENIED)
{
AdjustRegSecurity(hKeyRoot, lpKeyName, lpszUsersid, TRUE);
bTry = FALSE;
goto TryAgain1;
}
goto Cleanup;
}
}
else
{
TryAgain2:
lResult = RegOpenKeyEx(hKeyRoot,
lpKeyName,
0,
KEY_ALL_ACCESS,
&hKey);
if (lResult != ERROR_SUCCESS)
{
if (bTry && lResult == ERROR_ACCESS_DENIED)
{
AdjustRegSecurity(hKeyRoot, lpKeyName, lpszUsersid, TRUE);
bTry = FALSE;
goto TryAgain2;
}
goto Cleanup;
}
}
SkipKeyOpen:
switch (dwType & 0xffff)
{
case REG_SZ:
case REG_EXPAND_SZ:
dwSize = (lstrlen(lpNewValue) + 1) * sizeof(TCHAR);
break;
case REG_MULTI_SZ:
dwSize = MultiSzLen(lpNewValue) * sizeof(TCHAR);
break;
case REG_BINARY:
dwSize = dwValueSize;
break;
}
}
else
{
TryAgain3:
//if lpOldValue !="", it mean set the lpNewValue, but check whether the current
// registry value is szOldValue
//Open the subket and got the handle in hKey
lResult = RegOpenKeyEx(hKeyRoot,
lpKeyName,
0,
KEY_ALL_ACCESS,
&hKey);
if (lResult != ERROR_SUCCESS)
{
if (bTry && lResult == ERROR_ACCESS_DENIED)
{
AdjustRegSecurity(hKeyRoot, lpKeyName, lpszUsersid, TRUE);
bTry = FALSE;
goto TryAgain3;
}
goto Cleanup;
}
lResult = RegQueryInfoKey(hKey,
NULL,
&ClassLength,
0,
&SubKeys,
&MaxSubKey,
&MaxClass,
&Values,
&MaxValueName,
&MaxValueData,
&SecurityLength,
&LastWriteTime);
if ((lResult != ERROR_SUCCESS) &&
(lResult != ERROR_MORE_DATA) &&
(lResult != ERROR_INSUFFICIENT_BUFFER))
{
goto Cleanup;
}
MaxValueData += 2*sizeof(TCHAR);
if (NULL == (szData = malloc(MaxValueData)))
{
lResult = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
dwSize = MaxValueData;
lResult = My_QueryValueEx (hKey,
lpValueName,
0,
&dw,
(LPBYTE) szData,
&dwSize);
if (lResult != ERROR_SUCCESS)
{
goto Cleanup;
}
if ( ((dwType & 0xffff) == REG_SZ) || ((dwType & 0xffff) == REG_EXPAND_SZ) )
{
if (MyStrCmpI(szData, lpOldValue) != LSTR_EQUAL)
{
lResult = ERROR_SUCCESS;
goto Cleanup;
}
else
{
dwSize = (lstrlen(lpNewValue) + 1) * sizeof(TCHAR);
}
}
else
{//dwType == REG_MULTI_SZ
if (!CmpMultiSzi(szData, lpOldValue))
{
lResult = ERROR_SUCCESS;
goto Cleanup;
}
else
{
dwSize = MultiSzLen(lpNewValue) * sizeof(TCHAR);
}
}
if ( dwType & 0xffff0000)
{
if ((dwType & 0xffff0000)>>16 != dw )
{
// Key type in registry mismatches the caller-supplied type
lResult = ERROR_SUCCESS;
goto Cleanup;
}
}
else
{
if (dwType != dw)
{
// Key type in registry mismatches the caller-supplied type
lResult = ERROR_SUCCESS;
goto Cleanup;
}
}
}
//
// Set the new value
//
if ( dwType & 0xffff0000)
{
dwType = (dwType & 0xffff0000)>>16;
}
lResult = RegSetValueEx(hKey,
lpValueName,
0,
dwType,
(LPBYTE) lpNewValue,
dwSize);
Cleanup:
if (hKey && bNeedCLoseKey)
{
RegCloseKey(hKey);
}
if (!bTry)
{
AdjustRegSecurity(hKeyRoot, lpKeyName, lpszUsersid, FALSE);
}
FreePointer(szData);
return lResult;
}
//-----------------------------------------------------------------------------
//
// Function: RegResetValueName
//
// Synopsis: Reset value name to new name if the old name matches the
// user-supply lpOldValueName.
//
// Returns: Win32 Error Code
//
// History: 02/07/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
LONG RegResetValueName(
HKEY hRootKey, // Root key
LPCTSTR lpSubKeyName, // Sub key name under HKEY_Users\{user hive}
LPCTSTR lpOldValueName, // Old value name to be changed
LPCTSTR lpNewValueName, // New value name
LPCTSTR lpszUsersid // User Sid
)
{
LONG lRet;
HKEY hKey;
BOOL bTry = TRUE;
TryAgain:
lRet = RegOpenKeyEx(hRootKey,
lpSubKeyName,
0,
KEY_WRITE | KEY_READ,
&hKey);
if (lRet == ERROR_SUCCESS)
{
lRet = RegRenameValueName(hKey,
lpOldValueName,
lpNewValueName);
RegCloseKey(hKey);
if (!bTry)
AdjustRegSecurity(hRootKey, lpSubKeyName, lpszUsersid, FALSE);
} else if (bTry && lRet == ERROR_ACCESS_DENIED)
{
AdjustRegSecurity(hRootKey, lpSubKeyName, lpszUsersid, TRUE);
bTry = FALSE;
goto TryAgain;
}
return lRet;
}
//-----------------------------------------------------------------------------
//
// Function: RegResetKeyName
//
// Synopsis: Reset the registry key
//
// Returns: Win32 Error Code
//
// History: 05/06/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
LONG RegResetKeyName(
HKEY hRootKey, // Root key
LPCTSTR lpSubKey, // Sub key
LPCTSTR lpOldKeyName, // Old key name to be changed
LPCTSTR lpNewKeyName // New key name
)
{
LONG lRet;
HKEY hKey;
HKEY hOldKey;
HKEY hNewKey;
lRet = RegOpenKeyEx(hRootKey,
lpSubKey,
0,
KEY_READ | KEY_WRITE,
&hKey);
if (lRet == ERROR_SUCCESS)
{
lRet = RegOpenKeyEx(hKey,
lpOldKeyName,
0,
KEY_READ | KEY_WRITE,
&hOldKey);
if (lRet == ERROR_SUCCESS)
{
lRet = RegCreateKeyEx(hKey,
lpNewKeyName,
0,
TEXT(""),
REG_OPTION_NON_VOLATILE,
KEY_WRITE | KEY_READ,
NULL,
&hNewKey,
NULL);
if (lRet == ERROR_SUCCESS)
{
if (CopyRegistry(hOldKey, hNewKey))
{
RegDeleteKeyRecursive(hKey, lpOldKeyName);
}
RegCloseKey(hNewKey);
}
RegCloseKey(hOldKey);
}
RegCloseKey(hKey);
}
return lRet;
}
LONG RegGetValue(
HKEY hKeyRoot,
LPTSTR szKeyName,
LPTSTR szValueName,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData)
{
LONG lResult ;
HKEY hKey = NULL;
lResult = RegOpenKeyEx(hKeyRoot,
szKeyName,
0,
KEY_READ,
&hKey);
if (lResult != ERROR_SUCCESS)
{
goto Cleanup;
}
lResult = My_QueryValueEx (hKey,
szValueName,
0,
lpType,
lpData,
lpcbData);
Cleanup:
if (hKey)
{
RegCloseKey(hKey);
}
return lResult;
}
HRESULT MigrateRegSchemes(
HINF hInf, // Handle to template INF
HKEY hKey, // Handle to root key
LPCTSTR lpUserName // User name
)
{
HRESULT hr = E_FAIL;
BOOL bRet;
LONG lComponentCount;
LONG lLineIndex;
INFCONTEXT context;
LPCTSTR lpSectionName;
const TCHAR szPerSystemSection[] = TEXT_REG_RESET_PER_SYSTEM_SECTION;
const TCHAR szPerUserSection[] = TEXT_REG_RESET_PER_USER_SECTION;
if (hInf == INVALID_HANDLE_VALUE)
{
return E_INVALIDARG;
}
DPF(REGmsg, TEXT("Enter MigrateRegSchemes:"));
lpSectionName = (lpUserName ? szPerUserSection : szPerSystemSection);
// Get all components from appropriate section
lComponentCount = SetupGetLineCount(hInf, lpSectionName);
for (lLineIndex = 0 ; lLineIndex < lComponentCount ; lLineIndex++)
{
bRet = SetupGetLineByIndex(hInf,
lpSectionName,
lLineIndex,
&context);
if (bRet)
{
TCHAR szComponentName[MAX_PATH];
DWORD cchReqSize;
bRet = SetupGetStringField(&context,
1,
szComponentName,
ARRAYSIZE(szComponentName),
&cchReqSize);
if (bRet)
{
//
// Do the registry reset
//
hr = DoRegReset(hKey, hInf, szComponentName, lpUserName);
if (FAILED(hr))
{
DPF(REGerr,
TEXT("Failed to do registry migration for [%s] schemes"),
szComponentName);
break;
}
}
}
if (!bRet)
{
hr = HRESULT_FROM_WIN32(GetLastError());
break;
}
}
DPF(REGmsg, TEXT("Exit MigrateRegSchemes:"));
return hr;
}
HRESULT DoRegReset(
HKEY hKey, // Handle to root key
HINF hInf, // Handle to template INF
LPCTSTR lpSection, // Section name in INF
LPCTSTR lpUserName // User name
)
{
#define MAX_VALUE_DATA_RESET_FIELD 6
#define MAX_VALUE_NAME_RESET_FIELD 4
#define MAX_KEY_NAME_RESET_FIELD 4
HRESULT hr = S_OK;
BOOL bRet;
HKEY hRootKey;
LONG lItemCount;
LONG lLineCount;
INFCONTEXT context;
LPTSTR lpSubKey;
LPTSTR lpOutputKey;
LPTSTR lpField[16];
DWORD i;
DWORD dwLastField[] = {
MAX_VALUE_DATA_RESET_FIELD,
MAX_VALUE_NAME_RESET_FIELD,
MAX_KEY_NAME_RESET_FIELD,
MAX_KEY_NAME_RESET_FIELD,
};
if (hInf == INVALID_HANDLE_VALUE || lpSection == NULL)
{
return E_INVALIDARG;
}
DPF(REGmsg, TEXT("Enter DoRegReset for [%s] component"), lpSection);
// Loop through all lines under current component section
lItemCount = SetupGetLineCount(hInf, lpSection);
for (lLineCount = 0 ; lLineCount < lItemCount ; lLineCount++)
{
// Get the INF context for each line under current component
bRet = SetupGetLineByIndex(hInf, lpSection, lLineCount, &context);
if (bRet)
{
TCHAR szResetType[2];
DWORD dwReqSize;
// Get the reset-type from field 1
bRet = SetupGetStringField(&context,
1,
szResetType,
ARRAYSIZE(szResetType),
&dwReqSize);
if (bRet)
{
LONG lResetType = _ttol(szResetType);
hr = ReadFieldFromContext(&context, lpField, 2, dwLastField[lResetType]);
if (SUCCEEDED(hr))
{
if (hKey == NULL)
{
//
// Per-System reg key
//
lpOutputKey = lpField[2];
Str2KeyPath2(lpField[2], &hRootKey, &lpSubKey);
}
else
{
//
// Per-User reg key
//
lpOutputKey = lpField[2];
lpSubKey = lpField[2];
hRootKey = hKey;
}
switch (lResetType)
{
case 0:
if (MyStrCmpI(lpField[3], TEXT("REG_BINARY")) == 0)
hr = RegBinaryDataReset (hRootKey,
(LPTSTR) lpUserName,
lpSubKey,
&g_StrReplaceTable,
lpField);
else
hr = RegValueDataReset(hRootKey,
(LPTSTR) lpUserName,
lpSubKey,
lpOutputKey,
lpField);
break;
case 1:
hr = RegValueNameReset( hRootKey,
(LPTSTR) lpUserName,
lpSubKey,
lpOutputKey,
lpField);
break;
case 2:
hr = RegKeyNameReset(hRootKey,
(LPTSTR) lpUserName,
lpSubKey,
lpOutputKey,
lpField);
break;
case 3:
hr = RegWideMatchReset(hRootKey,
(LPTSTR) lpUserName,
lpSubKey,
lpOutputKey,
lpField);
break;
}
for (i = 0 ; i <= dwLastField[lResetType] ; i++)
{
MEMFREE(lpField[i]);
}
}
}
}
if (!bRet)
{
hr = HRESULT_FROM_WIN32(GetLastError());
break;
}
}
DPF(REGmsg, TEXT("Exit DoRegReset for [%s] component:"), lpSection);
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: MigrateRegSchemesPerSystem
//
// Synopsis: Migrate Per-System scheme settings in registry to English.
// Scheme settings can be registry value data or
// registry value name.
//
// Returns: S_OK if operation succeed
//
// History: 03/15/2002 Rerkboos Created
//
// Notes: Per-System means that the registry data is not under HKEY_USERS
//
//-----------------------------------------------------------------------------
HRESULT MigrateRegSchemesPerSystem(
HINF hInf
)
{
return MigrateRegSchemes(hInf, NULL, NULL);
}
//-----------------------------------------------------------------------------
//
// Function: MigrateRegSchemesPerUser
//
// Synopsis: Migrate Per-User scheme settings in registry to English.
// Scheme settings can be registry value data or
// registry value name.
//
// Returns: S_OK if operation succeed
//
// History: 03/15/2002 Rerkboos Created
//
// Notes: This is a callback function for LoopUser() function.
// It will be called everytime LoopUser() loads registry hive for
// each user available in the system.
//
//-----------------------------------------------------------------------------
HRESULT MigrateRegSchemesPerUser(
HKEY hKeyUser, // Handle to user's root key
LPCTSTR lpUserName, // User name
LPCTSTR lpDomainName, // Domain name of user name
LPCTSTR lpUserSid // Sid of user
)
{
return MigrateRegSchemes(g_hInf, hKeyUser, lpUserName);
}
HRESULT RegBinaryDataReset (
HKEY hRootKey, // Handle to root key
LPTSTR lpUserName, // (optional) name of user for current hRootKey
LPTSTR lpSubKey, // Sub key used to search in registry
PREG_STRING_REPLACE lpRegStr, // String table
LPTSTR lpField[]) // Pointer to field value from template file
{
HRESULT hr = S_OK;
if (MyStrCmpI(lpField[5], TEXT("UpdatePSTpath")) == 0)
{
hr = UpdatePSTpath(hRootKey, lpUserName, lpSubKey, lpField[4], lpRegStr);
}
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: RegValueDataReset
//
// Synopsis: Reset the value data in registry, one value data at a time.
// The value data to be reset is retrieved from INF line context.
//
// Returns: S_OK if operation succeeded
//
// History: 03/15/2002 Rerkboos Created
//
// Notes: lpUserName can be NULL if this function is to reset per-system
// registry settings. Otherwise, lpUserName contains user name
// for the supplied hRootKey.
//
//-----------------------------------------------------------------------------
HRESULT RegValueDataReset(
HKEY hRootKey, // Handle to root key
LPTSTR lpUserName, // (optional) name of user for current hRootKey
LPTSTR lpSubKey, // Sub key used to search in registry
LPTSTR lpOutputKey, // Output registry to save in CLMTDO.inf
LPTSTR lpField[] // Pointer to field value from template file
)
{
HRESULT hr = S_OK;
HKEY hKey;
DWORD cbSize;
DWORD dwAttrib = 0;
LONG lRet;
lRet = RegOpenKeyEx(hRootKey,
lpSubKey,
0,
KEY_WRITE | KEY_READ,
&hKey);
if (lRet == ERROR_SUCCESS)
{
lRet = GetRegistryValue(hRootKey,
lpSubKey, // Sub key
lpField[4], // Value name
NULL,
&cbSize);
if (lRet == ERROR_SUCCESS)
{
LPWSTR lpValue;
DWORD dwType = Str2REG(lpField[3]); // Registry type
lpValue = (LPWSTR) MEMALLOC(cbSize);
if (lpValue)
{
GetRegistryValue(hRootKey,
lpSubKey,
lpField[4],
(LPBYTE) lpValue,
&cbSize);
// Old value matches, do reg value reset
if (MyStrCmpI(lpValue, lpField[5]) == LSTR_EQUAL)
{
DPF(REGinf, TEXT("Reset registry value [%s]"), lpField[4]);
//
// Add the value data to be rename into CLMTDO.INF
//
hr = AddRegValueRename(lpOutputKey, // Reg key
lpField[4], // Value name
NULL,
lpField[5], // Old value data
lpField[6], // New value data
dwType,
dwAttrib,
(LPTSTR) lpUserName);
if (FAILED(hr))
{
DPF(REGwar,
TEXT("Failed to add registry value [%s] to defer change"),
lpField[4]);
}
}
MEMFREE(lpValue);
}
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
DPF(REGwar, TEXT("Value [%s] not found in registry"), lpField[4]);
hr = S_FALSE;
}
else
{
DPF(REGerr, TEXT("Failed to read value [%s]"), lpField[4]);
hr = HRESULT_FROM_WIN32(lRet);
}
RegCloseKey(hKey);
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
DPF(REGwar, TEXT("Key [%s] not found in registry"), lpOutputKey);
hr = S_FALSE;
}
else
{
DPF(REGerr, TEXT("Failed to open key [%s]"), lpOutputKey);
hr = HRESULT_FROM_WIN32(lRet);
}
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: RegValueNameReset
//
// Synopsis: Reset the value name in registry, one value name at a time.
// The value name to be reset is retrieved from INF line context.
//
// Returns: S_OK if operation succeeded
//
// History: 03/15/2002 Rerkboos Created
//
// Notes: lpUserName can be NULL if this function is to reset per-system
// registry settings. Otherwise, lpUserName contains user name
// for the supplied hRootKey.
//
//-----------------------------------------------------------------------------
HRESULT RegValueNameReset(
HKEY hRootKey, // Handle to root key
LPTSTR lpUserName, // (optional) name of user for current hRootKey
LPTSTR lpSubKey, // Sub key used to search in registry
LPTSTR lpOutputKey, // Output registry to save in CLMTDO.inf
LPTSTR lpField[] // Pointer to field value from template file
)
{
HRESULT hr = S_OK;
HKEY hKey;
DWORD cbSize;
DWORD dwAttrib = 0;
LONG lRet;
// Do value name reset If old value name and new value name in INF are different
if (lstrcmp((LPCTSTR) lpField[3], (LPCTSTR) lpField[4]) != LSTR_EQUAL)
{
lRet = RegOpenKeyEx(hRootKey,
lpSubKey,
0,
KEY_WRITE | KEY_READ,
&hKey);
if (lRet == ERROR_SUCCESS)
{
lRet = GetRegistryValue(hRootKey,
lpSubKey,
lpField[3], // Old value name
NULL,
&cbSize);
if (lRet == ERROR_SUCCESS)
{
DPF(REGinf, TEXT("Reset registry value name [%s]"), lpField[3]);
hr = AddRegValueRename(lpOutputKey,
lpField[3], // Old value name
lpField[4], // New value name
NULL,
NULL,
0,
dwAttrib,
(LPTSTR) lpUserName);
if (FAILED(hr))
{
DPF(REGwar,
TEXT("Failed to add registry value name [%s] to defer change list"),
lpField[3]);
}
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
DPF(REGwar, TEXT("Value [%s] not found in registry"), lpField[3]);
hr = S_FALSE;
}
else
{
DPF(REGerr, TEXT("Failed to read value [%s]"), lpField[3]);
hr = HRESULT_FROM_WIN32(lRet);
}
RegCloseKey(hKey);
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
DPF(REGwar, TEXT("Key [%s] not found in registry"), lpOutputKey);
hr = S_FALSE;
}
else
{
DPF(REGerr, TEXT("Failed to open key [%s]"), lpOutputKey);
hr = HRESULT_FROM_WIN32(lRet);
}
}
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: RegKeyNameReset
//
// Synopsis: Reset the key name in registry,
//
// Returns: S_OK if operation succeeded
//
// History: 03/15/2002 Rerkboos Created
//
// Notes: lpUserName can be NULL if this function is to reset per-system
// registry settings. Otherwise, lpUserName contains user name
// for the supplied hRootKey.
//
//-----------------------------------------------------------------------------
HRESULT RegKeyNameReset(
HKEY hRootKey, // Handle to root key
LPTSTR lpUserName, // (optional) name of user for current hRootKey
LPTSTR lpSubKey, // Sub key used to search in registry
LPTSTR lpOutputKey, // Output registry sub key to save in CLMTDO.inf
LPTSTR lpField[] // Pointer to field value from template file
)
{
HRESULT hr;
LONG lRet;
HKEY hKey;
HKEY hOldKey;
HKEY hNewKey;
// Do the key rename if old key name and new key name in INF are different
if (lstrcmpi(lpField[3], lpField[4]) == LSTR_EQUAL)
{
return S_FALSE;
}
// Check if we can access the subkey or not
lRet = RegOpenKeyEx(hRootKey,
lpSubKey,
0,
KEY_READ | KEY_WRITE,
&hKey);
if (lRet == ERROR_SUCCESS)
{
// Check the existence of old registry key
lRet = RegOpenKeyEx(hKey,
lpField[3],
0,
KEY_READ | KEY_WRITE,
&hOldKey);
if (lRet == ERROR_SUCCESS)
{
// Old reg key exists. Then, check the existence of new registry key
lRet = RegOpenKeyEx(hKey,
lpField[4],
0,
KEY_READ,
&hNewKey);
if (lRet == ERROR_SUCCESS)
{
hr = S_FALSE;
RegCloseKey(hNewKey);
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
// New key does not exist, ok to rename the old reg key
hr = AddRegKeyRename(lpOutputKey,
lpField[3],
lpField[4],
lpUserName);
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
DPF(REGerr, TEXT("Failed to open key [%s\\%s], hr = 0x%x"), lpSubKey, lpField[4], hr);
}
RegCloseKey(hOldKey);
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
hr = S_FALSE;
}
else
{
hr = HRESULT_FROM_WIN32(lRet);
DPF(REGerr, TEXT("Failed to open key [%s\\%s], hr = 0x%x"), lpSubKey, lpField[3], hr);
}
RegCloseKey(hKey);
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
hr = S_FALSE;
}
else
{
hr = HRESULT_FROM_WIN32(lRet);
DPF(REGerr, TEXT("Failed to open key [%s], hr = 0x%x"), lpSubKey, hr);
}
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: ReadFieldFromContext
//
// Synopsis: Read fields from INFCONTEXT
//
// Returns: S_OK if succeeded
//
// History: 03/14/2001 Rerkboos Created
//
// Notes: Caller must free the memory allocated in lpField[]
//
//-----------------------------------------------------------------------------
HRESULT ReadFieldFromContext(
PINFCONTEXT lpContext, // INFCONTEXT for each line
LPWSTR lpField[], // Pointer point to each field
DWORD dwFirstField, // First field to read
DWORD dwLastField // Last field to read
)
{
HRESULT hr = S_OK;
DWORD dwFieldIndex;
DWORD cchField;
DWORD cchReqSize;
for (dwFieldIndex = 0 ; dwFieldIndex <= dwLastField ; dwFieldIndex++)
{
lpField[dwFieldIndex] = NULL;
}
//
// Read data INF context into field buffer
//
for (dwFieldIndex = dwFirstField ; dwFieldIndex <= dwLastField ; dwFieldIndex++)
{
// Get the require size big enough to store data
if (SetupGetStringField(lpContext,
dwFieldIndex,
NULL,
0,
&cchField))
{
//Add one more space in case the string converted to MultiSZ
cchField ++;
lpField[dwFieldIndex] = (LPWSTR) MEMALLOC(cchField * sizeof(TCHAR));
if (lpField[dwFieldIndex] == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
// Read data from INF to buffer
SetupGetStringField(lpContext,
dwFieldIndex,
lpField[dwFieldIndex],
cchField,
&cchReqSize);
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
break;
}
}
// Free all the allocated memory if any error occured
if (FAILED(hr))
{
for (dwFieldIndex = 0 ; dwFieldIndex <= dwLastField ; dwFieldIndex++)
{
if (lpField[dwFieldIndex])
{
MEMFREE(lpField[dwFieldIndex]);
}
}
}
return hr;
}
//-----------------------------------------------------------------------------
//
// Function: GetRegistryValue
//
// Synopsis: Wrapper function to get registry value
//
// Returns: ERROR_SUCCESS if value is successefully get
//
// History: 03/14/2001 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
LONG GetRegistryValue(
HKEY hRootKey,
LPCTSTR lpSubKey,
LPCTSTR lpValueName,
LPBYTE lpBuffer,
LPDWORD lpcbBuffer
)
{
LONG lStatus;
HKEY hKey;
DWORD dwSize;
lStatus = RegOpenKeyEx(hRootKey,
lpSubKey,
0,
KEY_READ,
&hKey);
if (lStatus == ERROR_SUCCESS)
{
dwSize = sizeof(DWORD);
lStatus = RegQueryValueEx(hKey,
lpValueName,
NULL,
NULL,
lpBuffer,
lpcbBuffer);
RegCloseKey(hKey);
}
return lStatus;
}
//-----------------------------------------------------------------------------
//
// Function: SetRegistryValue
//
// Synopsis: Wrapper function to set registry value
//
// Returns: ERROR_SUCCESS if value is successefully set
//
// History: 03/14/2001 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
LONG SetRegistryValue(
HKEY hRootKey,
LPCTSTR lpSubKey,
LPCTSTR lpValueName,
DWORD dwType,
LPBYTE lpData,
DWORD cbData
)
{
LONG lStatus;
HKEY hKey;
lStatus = RegCreateKeyEx(hRootKey,
lpSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
NULL);
if (lStatus == ERROR_SUCCESS)
{
lStatus = RegSetValueEx(hKey,
lpValueName,
0,
dwType,
lpData,
cbData);
RegCloseKey(hKey);
}
return lStatus;
}
//--------------------------------------------------------------------------
//
// My_QueryValueEx
//
// wraps RegQueryValueEx and ensures that the returned string is NULL-
// terminated
//
//--------------------------------------------------------------------------
LONG My_QueryValueEx(
HKEY hKey, // handle to key
LPCTSTR lpValueName, // value name
LPDWORD lpReserved, // reserved
LPDWORD lpType, // type buffer
LPBYTE lpData, // data buffer
LPDWORD lpcbData // size of data buffer
)
{
DWORD dwMyType;
LONG lRes;
LPDWORD lpCurrType = &dwMyType;
DWORD cbOriginalDataSize = 0;
LPBYTE lpBuf = NULL;
if (lpType)
{
lpCurrType = lpType;
}
if (lpcbData)
{
cbOriginalDataSize = *lpcbData;
}
lRes = RegQueryValueEx(hKey, lpValueName, lpReserved, lpCurrType, lpData, lpcbData);
if (lRes == ERROR_SUCCESS
&& IsRegStringType(*lpCurrType)
&& lpcbData
&& bIsValidRegStr(*lpCurrType,*lpcbData)
)
{
LPTSTR psz;
int cch = (int)(*lpcbData/sizeof(TCHAR));
if (!lpData) // in this case user is query the buffer size needed
{
lpBuf = (LPBYTE) calloc(*lpcbData, sizeof(BYTE));
if (!lpBuf) {
lRes = ERROR_NOT_ENOUGH_MEMORY;
goto Exit;
}
lRes = RegQueryValueEx(hKey, lpValueName, lpReserved, lpCurrType, lpBuf, lpcbData);
if (lRes != ERROR_SUCCESS)
goto Exit;
psz = (LPTSTR)lpBuf;
if (psz[cch-1])
*lpcbData += 2 * sizeof(TCHAR);
else if (psz[cch-2])
*lpcbData += sizeof(TCHAR);
}
else
{
psz = (LPTSTR)lpData;
if (REG_MULTI_SZ == *lpCurrType)
{
if (psz[cch-1])
{
if (*lpcbData >= (cbOriginalDataSize-sizeof(TCHAR)))
{
lRes = ERROR_MORE_DATA;
}
else
{
psz[cch] = 0;
psz[cch+1] = 0;
*lpcbData += 2 * sizeof(TCHAR);
}
}
else if (psz[cch-2])
{
if (*lpcbData >= cbOriginalDataSize)
{
lRes = ERROR_MORE_DATA;
}
else
{
psz[cch] = 0;
*lpcbData += sizeof(TCHAR);
}
}
}
else
{
if (psz[cch-1])
{
if (*lpcbData >= cbOriginalDataSize)
{
lRes = ERROR_MORE_DATA;
}
else
{
psz[cch] = 0;
*lpcbData += sizeof(TCHAR);
}
}
}
}
}
Exit:
if (lpBuf)
free (lpBuf);
return lRes;
}
BOOL bIsValidRegStr(
DWORD dwType,
DWORD cbLen)
{
if (!IsRegStringType(dwType))
{
return FALSE;
}
if (dwType == REG_MULTI_SZ)
{
if (cbLen < 2 * sizeof(TCHAR))
{
return FALSE;
}
}
else
{
if (cbLen < sizeof(TCHAR))
{
return FALSE;
}
}
#ifdef UNICODE
if ( (cbLen % sizeof(TCHAR)) == 1 )
{
return FALSE;
}
#endif
return TRUE;
}
LONG MyRegSetDWValue(
HKEY hRootKey, // Root key
LPCTSTR lpSubKeyName, // Sub key name under HKEY_Users\{user hive}
LPCTSTR lpValueName, // value name to be changed
LPCTSTR lpNewValue) // New value
{
LONG lRet;
HKEY hKey = NULL;
DWORD dwVal;
lRet = RegOpenKeyEx(hRootKey,
lpSubKeyName,
0,
KEY_WRITE | KEY_READ,
&hKey);
if (ERROR_SUCCESS != lRet)
{
hKey = NULL;
goto exit;
}
dwVal = _tstoi(lpNewValue);
lRet = RegSetValueEx(hKey,lpValueName,0,REG_DWORD,(LPBYTE)&dwVal,sizeof(DWORD));
exit:
if (hKey)
{
RegCloseKey(hKey);
}
return lRet;
}
HRESULT RegWideMatchReset(
HKEY hRootKey, // Handle to root key
LPTSTR lpUserName, // (optional) name of user for current hRootKey
LPTSTR lpSubKey, // Sub key used to search in registry
LPTSTR lpOutputKey, // Output registry sub key to save in CLMTDO.inf
LPTSTR lpField[]) // Pointer to field value from template file
{
REG_STRING_REPLACE myTable;
HKEY hKey;
LONG lRet;
HRESULT hr;
hr = Sz2MultiSZ(lpField[3],TEXT(';'));
if (FAILED(hr))
{
goto exit;
}
hr = Sz2MultiSZ(lpField[4],TEXT(';'));
if (FAILED(hr))
{
goto exit;
}
hr = ConstructUIReplaceStringTable(lpField[3], lpField[4],&myTable);
if (FAILED(hr))
{
goto exit;
}
lRet = RegOpenKeyEx(hRootKey,
lpSubKey,
0,
KEY_READ | KEY_WRITE,
&hKey);
if (ERROR_SUCCESS != lRet)
{
hr = HRESULT_FROM_WIN32(lRet);
goto exit;
}
hr = RegistryAnalyze(hKey,lpUserName,NULL,&myTable,NULL,0,lpOutputKey,FALSE);
exit:
return hr;
}