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.
 
 
 
 
 
 

788 lines
25 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
regfind.c
Abstract:
Search registry and reset the specific value data.
Author:
Geoffrey Guo (geoffguo) 08-Oct-2001 Created
Revision History:
<alias> <date> <comments>
--*/
#include "StdAfx.h"
#include "clmt.h"
LONG QueryValue(HKEY, LPTSTR, LPTSTR, PREG_STRING_REPLACE, PVALLIST*, LPTSTR, DWORD, BOOL);
LONG QueryEnumerateKey(HKEY, LPTSTR,LPTSTR,PREG_STRING_REPLACE, LPTSTR, LPTSTR, DWORD, BOOL);
LONG SetRegValueChange (HKEY, LPTSTR, PVALLIST*, LPTSTR);
//-----------------------------------------------------------------------//
//
// RegistryAnalyze()
//
// hRootKey : Regsitry handle
// lpRegStr : Input parameter structure
// lpRegExclusionList: MultiSZ string tells a list of Keypath RegRepace should skip
//
//-----------------------------------------------------------------------//
HRESULT RegistryAnalyze(
HKEY hRootKey,
LPTSTR szUserName,
LPTSTR szUserSid,
PREG_STRING_REPLACE lpRegStr,
LPTSTR lpRegExclusionList,
DWORD TreatAsType,
LPTSTR lpRootKeyPath,
BOOL bStrChk)
{
TCHAR szRoot[MAX_PATH];
LPTSTR lpRoot = TEXT("\0");
HRESULT hResult = S_FALSE;
LONG lResult;
if (szUserName)
{
DPF(REGmsg, L"Enter RegistryAnalyze: szUserName=%s hKey=%d", szUserName, hRootKey);
}
else if (hRootKey == HKEY_CLASSES_ROOT)
{
DPF(REGmsg, L"Enter RegistryAnalyze: HKEY_CLASSES_ROOT");
}
else if (hRootKey == HKEY_LOCAL_MACHINE)
{
DPF(REGmsg, L"Enter RegistryAnalyze: HKEY_LOCAL_MACHINE");
}
else
{
DPF(REGmsg, L"Enter RegistryAnalyze: hKey=%d", hRootKey);
}
if (lpRegExclusionList)
{
hResult = ReplaceCurrentControlSet(lpRegExclusionList);
if (FAILED(hResult))
{
return hResult;
}
}
if (lpRegStr->lpSearchString && lpRegStr->lpReplaceString)
{
UpdateProgress();
lpRegStr->cchMaxStrLen = GetMaxStrLen (lpRegStr);
if (lpRootKeyPath)
{
lpRoot = lpRootKeyPath;
}
else
{
if (HKey2Str(hRootKey,szRoot,MAX_PATH))
{
lpRoot = szRoot;
}
}
lResult = QueryEnumerateKey(hRootKey, szUserName, szUserSid, lpRegStr,
lpRoot,lpRegExclusionList,TreatAsType, bStrChk);
hResult = HRESULT_FROM_WIN32(lResult);
}
DPF(REGmsg, L"Exit RegistryAnalyze:");
return hResult;
}
//-----------------------------------------------------------------------//
//
// ReadValue()
//
// hKey: Registry key
// szValueName: Value name
// lpType: Value type
// lpBuf: Vaule data buffer
// lpSize: Value data size
// lpFullKey: Full sub-key path
//-----------------------------------------------------------------------//
LONG ReadValue (
HKEY hKey,
LPTSTR szValueName,
LPDWORD lpType,
LPBYTE *lpBuf,
LPDWORD lpSize,
LPTSTR lpFullKey)
{
LONG lResult;
//
// First find out how much memory to allocate.
//
lResult = My_QueryValueEx(hKey,
szValueName,
0,
lpType,
NULL,
lpSize);
if (lResult != ERROR_SUCCESS)
{
DPF (REGerr, L"ReadValue1: RegQueryValueEx failed. lResult=%d", lResult);
return lResult;
}
//There is a bug in W2K HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\VideoUpgradeDisplaySettings".
//When the value name = Driver1, *lpSize will be 3. To cover Odd number of size, incease one byte for data buffer.
*lpBuf = (LPBYTE) calloc(*lpSize+sizeof(TCHAR)+1, sizeof(BYTE));
if (!(*lpBuf)) {
DPF (REGerr, L"ReadValue: No enough memory");
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Now get the data
//
lResult = My_QueryValueEx(hKey,
szValueName,
0,
lpType,
*lpBuf,
lpSize);
if (lResult != ERROR_SUCCESS)
{
if (*lpBuf)
free(*lpBuf);
DPF (REGerr, L"ReadValue2: RegQueryValueEx fail. lResult=%d", lResult);
return lResult;
}
return ERROR_SUCCESS;
}
//-----------------------------------------------------------------------//
//
// SetRegValueChange()
//
// Set registry value based on the value list
//
// hKey: Registry key
// lpValList: Updated value list
// lpFullKey: Full sub-key path
//-----------------------------------------------------------------------//
LONG SetRegValueChange (
HKEY hKey,
LPTSTR szUserName,
PVALLIST *lpValList,
LPTSTR lpFullKey)
{
LONG lResult = ERROR_SUCCESS;
HRESULT hResult;
DWORD dwType;
DWORD dwOldValueSize = 1, dwNewValueSize;
LPBYTE lpBuf;
LPTSTR lpOldValueData, lpNewValueData, lpNewValueName;
PVALLIST lpVal;
if (*lpValList)
{
lpVal = *lpValList;
while (lpVal)
{
UpdateProgress();
//Read old value data
lResult = ReadValue(hKey,
lpVal->lpPre_valuename,
&dwType,
&lpBuf,
&dwOldValueSize,
lpFullKey);
if (lResult != ERROR_SUCCESS)
{
DPF (REGerr, L"SetRegValueChange: ReadValue failed");
goto NextData;
}
/* //Set new value name or value data
lResult = RegSetValueEx (hKey,
lpVal->ve.ve_valuename,
0,
lpVal->ve.ve_type,
(LPBYTE)(lpVal->ve.ve_valueptr),
lpVal->ve.ve_valuelen);
*/
//Set old value name or value data
lResult = RegSetValueEx (hKey,
lpVal->lpPre_valuename,
0,
dwType,
lpBuf,
dwOldValueSize);
if (lResult == ERROR_SUCCESS)
{
if (lpVal->val_type & REG_CHANGE_VALUENAME)
{
//Delete old value if value name changed
// lResult = RegDeleteValue(hKey, lpVal->lpPre_valuename);
// if (lResult == ERROR_SUCCESS)
DPF (REGinf, L"SetRegValueChange: Rename value %s to %s Key=%s",
lpVal->lpPre_valuename, lpVal->ve.ve_valuename, lpFullKey);
// else
// DPF (REGerr, L"SetRegValueChange: RegDelValue failed. ValueName=%s Key=%s lResult=%d",
// lpVal->lpPre_valuename, lpFullKey, lResult);
}
else
DPF (REGinf, L"SetRegValueChange: Replace value data. Key=%s\\%s",
lpFullKey, lpVal->ve.ve_valuename);
} else
DPF (REGerr, L"SetRegValueChange: RegSetValueEx Failed. Error=%d", lResult);
if (lpVal->val_type & REG_CHANGE_VALUENAME)
lpNewValueName = lpVal->ve.ve_valuename;
else
lpNewValueName = NULL;
if (lpVal->val_type & REG_CHANGE_VALUEDATA)
{
lpOldValueData = (LPTSTR)lpBuf;
dwNewValueSize = lpVal->ve.ve_valuelen;
lpNewValueData = (LPTSTR)lpVal->ve.ve_valueptr;
} else
{
dwOldValueSize = 0;
lpOldValueData = NULL;
dwNewValueSize = 0;
lpNewValueData = NULL;
}
//Add registry value change information to INF file
hResult = AddRegValueRename(
lpFullKey,
lpVal->lpPre_valuename,
lpNewValueName,
lpOldValueData,
lpNewValueData,
lpVal->ve.ve_type,
lpVal->val_attrib,
szUserName);
lResult = HRESULT_CODE(hResult);
if (lResult != ERROR_SUCCESS)
{
DPF (REGerr, L"SetRegValueChange: AddRegValueRename failed. Key = %s, error = %d", lpFullKey,lResult);
if(lpBuf)
{
free(lpBuf);
lpBuf = NULL;
}
break;
}
if(lpBuf)
{
free(lpBuf);
lpBuf = NULL;
}
NextData:
lpVal = lpVal->pvl_next;
}
RemoveValueList (lpValList);
}
return lResult;
}
//-----------------------------------------------------------------------//
//
// QueryValue()
//
// hKey: Registry key
// szUserName: User name
// szValueName: Value name
// lpRegStr: Input parameter structure
// lpValList: Updated value list
// lpFullKey: Full sub-key path
//-----------------------------------------------------------------------//
LONG QueryValue(
HKEY hKey,
LPTSTR szUserName,
LPTSTR szValueName,
PREG_STRING_REPLACE lpRegStr,
PVALLIST *lpValList,
LPTSTR lpFullKey,
DWORD TreatAsType,
BOOL bStrChk)
{
LONG lResult;
HRESULT hResult;
DWORD dwType;
DWORD cbSize = 1;
LPBYTE lpBuf = NULL;
lResult = ReadValue(hKey,
szValueName,
&dwType,
&lpBuf,
&cbSize,
lpFullKey);
if (lResult != ERROR_SUCCESS)
goto Exit;
switch (dwType)
{
case REG_MULTI_SZ:
case REG_EXPAND_SZ:
case REG_LINK:
case REG_SZ:
case REG_DWORD:
hResult = ReplaceValueSettings (
szUserName,
(LPTSTR)lpBuf,
cbSize,
szValueName,
dwType,
lpRegStr,
lpValList,
lpFullKey,
bStrChk);
lResult = HRESULT_CODE(hResult);
break;
default:
if ( TreatAsType )
{
dwType = dwType <<16;
dwType = dwType + TreatAsType;
hResult = ReplaceValueSettings (
szUserName,
(LPTSTR)lpBuf,
cbSize,
szValueName,
dwType,
lpRegStr,
lpValList,
lpFullKey,
bStrChk);
lResult = HRESULT_CODE(hResult);
}
break;
}
Exit:
if(lpBuf)
free(lpBuf);
return lResult;
}
//-----------------------------------------------------------------------//
//
// QueryEnumerateKey() - Recursive
//
// hKey: Registry key
// szUserName: User name
// lpRegStr: Input parameter structure
// lpFullKey: Full sub-key path
// lpRegExclusionList: MultiSZ string tells a list of Keypath RegRepace should skip
//-----------------------------------------------------------------------//
LONG QueryEnumerateKey(
HKEY hKey,
LPTSTR szUserName,
LPTSTR szUserSid,
PREG_STRING_REPLACE lpRegStr,
LPTSTR szFullKey,
LPTSTR lpRegExclusionList,
DWORD TreatAsType,
BOOL bStrChk)
{
LONG lResult;
HRESULT hResult;
UINT i;
DWORD cchSize, cchLen;
DWORD dwNum;
BOOL dwAccessDenied;
HKEY hSubKey;
TCHAR* szNameBuf = NULL;
TCHAR* szKeyPath;
TCHAR* szNewKeyPath;
PVALLIST lpValList;
// query source key info
DWORD cchLenOfKeyName, cchLenOfValueName;
TCHAR szKeyName[2*MAX_PATH];
UpdateProgress();
if (lpRegExclusionList && IsStrInMultiSz(szFullKey,lpRegExclusionList))
{
lResult = S_OK;
goto Cleanup;
}
lResult = RegQueryInfoKey(hKey,
NULL,
NULL,
NULL,
NULL,
&cchLenOfKeyName,
NULL,
NULL,
&cchLenOfValueName,
NULL,
NULL,
NULL);
if (lResult != ERROR_SUCCESS)
{
DPF (REGerr, L"QueryEnumerateKey1: RegQueryInfoKey failed. Key=%s lResult=%d", szFullKey, lResult);
return ERROR_SUCCESS;
}
// create buffer
cchLenOfValueName++;
szNameBuf = (TCHAR*) calloc(cchLenOfValueName, sizeof(TCHAR));
if (!szNameBuf)
{
DPF (REGerr, L"QueryEnumerateKey1: No enough memory");
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// enumerate all of the values
//
i = 0;
lpValList = NULL;
do
{
UpdateProgress();
cchSize = cchLenOfValueName;
lResult = RegEnumValue(hKey,
i,
szNameBuf,
&cchSize,
NULL,
NULL,
NULL,
NULL);
if (lResult == ERROR_MORE_DATA)
{
free(szNameBuf);
//RegQueryInfoKey has a bug. *lpcMaxValueNameLen return 1 when
//Key=HKLM\\SYSTEM\\ControlSet002\\Control\\Lsa\\SspiCache.
cchSize = MAX_PATH;
szNameBuf = (TCHAR*) calloc(cchSize+1, sizeof(TCHAR));
if (!szNameBuf)
{
DPF (REGerr, L"QueryEnumerateKey2: No enough memory");
return ERROR_NOT_ENOUGH_MEMORY;
}
cchLenOfValueName = cchSize+1;
lResult = RegEnumValue(hKey,
i,
szNameBuf,
&cchSize,
NULL,
NULL,
NULL,
NULL);
}
if (lResult == ERROR_SUCCESS)
{
lResult = QueryValue(hKey, szUserName, szNameBuf, lpRegStr, &lpValList,
szFullKey, TreatAsType, bStrChk);
// continue to query
if(lResult == ERROR_ACCESS_DENIED)
{
DPF(REGerr, L"QueryEnumerateKey: Access denied ValueName=%s Key=%s", szNameBuf, szFullKey);
}
else if (lResult != ERROR_SUCCESS)
{
DPF(REGerr, L"QueryEnumerateKey: QueryValue failed. ValueName=%s Key=%s hResult=%d", szNameBuf, szFullKey, lResult);
}
lResult = ERROR_SUCCESS;
}
else if (lResult == ERROR_NO_MORE_ITEMS)
{
break;
}
else
{
DPF(REGerr, L"QueryEnumerateKey: RegEnumValue fails. Index=%d Key=%s Error=%d",
i, szFullKey, lResult);
}
i++;
} while (1);
lResult = SetRegValueChange (hKey, szUserName, &lpValList, szFullKey);
if (lResult != ERROR_SUCCESS)
{
DPF(REGerr, L"QueryEnumerateKey: SetRegValueChange failed ,error = %d",lResult);
goto Cleanup;
}
if(szNameBuf)
{
free(szNameBuf);
}
//
// Now Enumerate all of the keys
//
cchLenOfKeyName++;
szNameBuf = (TCHAR*) calloc(cchLenOfKeyName, sizeof(TCHAR));
if (!szNameBuf)
{
DPF (REGerr, L"QueryEnumerateKey4: No enough memory");
return ERROR_NOT_ENOUGH_MEMORY;
}
i = 0;
do
{
UpdateProgress();
cchSize = cchLenOfKeyName;
lResult = RegEnumKeyEx(hKey,
i,
szNameBuf,
&cchSize,
NULL,
NULL,
NULL,
NULL);
if (lResult == ERROR_MORE_DATA)
{
free(szNameBuf);
//It should not get here except lpcMaxValueLen return wrong.
cchSize = MAX_PATH;
szNameBuf = (TCHAR*) calloc(cchSize+1, sizeof(TCHAR));
if (!szNameBuf)
{
DPF (REGerr, L"QueryEnumerateKey3: No enough memory");
return ERROR_NOT_ENOUGH_MEMORY;
}
cchLenOfKeyName = cchSize+1;
lResult = RegEnumKeyEx(hKey,
i,
szNameBuf,
&cchSize,
NULL,
NULL,
NULL,
NULL);
}
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_NO_MORE_ITEMS)
{
lResult = ERROR_SUCCESS;
}
else
{
DPF (REGerr, L"QueryEnumerateKey: RegEnumKeyEx failed. Key=%s Error=%d", szFullKey, lResult);
}
break;
}
//BUGBUG:XIAOZ following code is doubtful, why we need lpRegExclusionList != NULL
//to exclude current control set, we should always exlcude it for performace
//and it should be in lpRegExclusionList, we do not any special processing for this
dwAccessDenied = FALSE;
if (lpRegExclusionList)
{
//skip CurrentControlSet since it is a link to existing control set
if (MyStrCmpI(szFullKey, L"HKLM\\SYSTEM") == 0 &&
MyStrCmpI(szNameBuf, L"CurrentControlSet") == 0)
{
goto NextKey;
}
}
//skip exclusive registry keys
if (MyStrCmpI(szFullKey, TEXT("HKLM")) == 0 &&
(MyStrCmpI(szNameBuf, TEXT("SAM")) == 0 || MyStrCmpI(szNameBuf, TEXT("SECURITY")) == 0) ||
MyStrCmpI(szFullKey, TEXT("HKLM\\SYSTEM\\ControlSet001\\Enum\\PCI\\VEN_8086&DEV_7110&SUBSYS_00000000&REV_02\\2&ebb567f&0&38\\Device Parameters")) == 0 &&
MyStrCmpI(szNameBuf, TEXT("BiosConfig")) == 0 )
goto NextKey;
TryAgain:
//
// open up the subkey, and enumerate it
//
lResult = RegOpenKeyEx(hKey,
szNameBuf,
0,
KEY_ALL_ACCESS
// | ACCESS_SYSTEM_SECURITY
,
&hSubKey);
if (lResult != ERROR_SUCCESS)
{
if(lResult == ERROR_ACCESS_DENIED) // Try Read_Only
{
lResult = RegOpenKeyEx(hKey,
szNameBuf,
0,
KEY_READ,
&hSubKey);
if (lResult == ERROR_SUCCESS)
{
DPF(REGwar, L"QueryEnumerateKey: RegOpenKeyEx: Key=%s\\%s Read Only", szFullKey, szNameBuf);
goto DoKey;
}
if (dwAccessDenied)
{
DPF(REGerr, L"QueryEnumerateKey: RegOpenKeyEx: Access Denied. Key=%s\\%s", szFullKey, szNameBuf);
goto NextKey;
}
hResult = RenameRegRoot(szFullKey, szKeyName, 2*MAX_PATH-1, szUserSid, szNameBuf);
AdjustObjectSecurity(szKeyName, SE_REGISTRY_KEY, TRUE);
dwAccessDenied = TRUE;
goto TryAgain;
}
DPF(REGerr, L"QueryEnumerateKey: RegOpenKeyEx failed. Key=%s\\%s Error=%d", szFullKey, szNameBuf, lResult);
//skip the current key since it cannot be opened.
goto NextKey;
}
DoKey:
//
// Build up the needed string and go down enumerating again
//
cchLen = lstrlen(szFullKey) + lstrlen(szNameBuf) + 2;
szKeyPath = (TCHAR*) calloc(cchLen, sizeof(TCHAR));
if (!szKeyPath)
{
lResult = ERROR_NOT_ENOUGH_MEMORY;
DPF (REGerr, L"QueryEnumerateKey5: No enough memory");
RegCloseKey(hSubKey);
goto Cleanup;
}
//We calculte the buffer for szKeyPath, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hResult = StringCchCopy(szKeyPath, cchLen, szFullKey);
hResult = StringCchCat(szKeyPath, cchLen, L"\\");
hResult = StringCchCat(szKeyPath, cchLen, szNameBuf);
dwNum = StrNumInMultiSZ(szNameBuf, lpRegStr->lpSearchString);
if (dwNum != 0xFFFFFFFF)
{
LPTSTR lpKeyName;
lpKeyName = GetStrInMultiSZ(dwNum, lpRegStr->lpReplaceString);
cchLen = lstrlen(szFullKey) + lstrlen(lpKeyName) + 2;
szNewKeyPath = (TCHAR*) calloc(cchLen, sizeof(TCHAR));
if (!szNewKeyPath) {
lResult = ERROR_NOT_ENOUGH_MEMORY;
DPF (REGerr, L"QueryEnumerateKey6: No enough memory");
RegCloseKey(hSubKey);
free(szKeyPath);
goto Cleanup;
}
if (szFullKey)
{
//We calculte the buffer for szNewKeyPath, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hResult = StringCchCopy(szNewKeyPath, cchLen, szFullKey);
}
//We calculte the buffer for szNewKeyPath, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hResult = StringCchCat(szNewKeyPath, cchLen, L"\\");
hResult = StringCchCat(szNewKeyPath, cchLen, lpKeyName);
hResult = AddRegKeyRename(szFullKey, szNameBuf, lpKeyName, szUserName);
if (FAILED(hResult))
{
DPF(REGerr, L"QueryEnumerateKey: AddRegKeyRename failed. Key=%s", szKeyPath);
}
else
{
DPF(REGinf, L"QueryEnumerateKey: AddRegKeyRename succeed. Key=%s", szKeyPath);
}
free (szNewKeyPath);
}
// recursive query
lResult = QueryEnumerateKey(hSubKey,
szUserName,
szUserSid,
lpRegStr,
szKeyPath,
lpRegExclusionList,
TreatAsType,
bStrChk);
if(lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_NOT_ENOUGH_MEMORY)
{
if (szKeyPath)
free(szKeyPath);
RegCloseKey(hSubKey);
goto Cleanup;
} else
DPF(REGerr, L"QueryEnumerateKey: QueryEnumerateKey failed. Key=%s lResult=%d", szKeyPath, lResult);
}
RegCloseKey(hSubKey);
if(szKeyPath)
free(szKeyPath);
NextKey:
if (dwAccessDenied)
AdjustObjectSecurity(szKeyName, SE_REGISTRY_KEY, FALSE);
i++;
} while (1);
Cleanup:
if(szNameBuf)
free(szNameBuf);
return lResult;
}