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.
366 lines
10 KiB
366 lines
10 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
regrep.c
|
|
|
|
Abstract:
|
|
|
|
Implements a registry search/replace tool.
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 19-Apr-1999
|
|
|
|
Revision History:
|
|
|
|
jimschm 26-May-1999 Moved from win9xupg, ported to use different
|
|
utilities
|
|
Santanuc 14-Feb-2002 Rewrite the RegistrySearchAndReplaceW to use
|
|
standard registry api rather than going through
|
|
reg & mem wrapper api's.
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
|
|
UINT
|
|
CountInstancesOfSubStringW (
|
|
IN PCWSTR SourceString,
|
|
IN PCWSTR SearchString,
|
|
IN UINT SearchChars
|
|
)
|
|
{
|
|
UINT Count;
|
|
UINT SourceChars;
|
|
PCWSTR End;
|
|
|
|
Count = 0;
|
|
SourceChars = lstrlenW (SourceString);
|
|
|
|
End = SourceString + SourceChars - SearchChars;
|
|
|
|
if (!SearchChars) {
|
|
return 0;
|
|
}
|
|
|
|
while (SourceString <= End) {
|
|
if (!_wcsnicmp (SourceString, SearchString, SearchChars)) {
|
|
Count++;
|
|
SourceString += SearchChars;
|
|
} else {
|
|
SourceString++;
|
|
}
|
|
}
|
|
|
|
return Count;
|
|
}
|
|
|
|
|
|
PWSTR
|
|
StringSearchAndReplaceW (
|
|
IN PCWSTR SourceString,
|
|
IN PCWSTR SearchString,
|
|
IN PCWSTR ReplaceString,
|
|
IN DWORD* pcbNewString
|
|
)
|
|
{
|
|
PWSTR NewString;
|
|
PBYTE p;
|
|
PBYTE Dest;
|
|
UINT Count;
|
|
UINT Size;
|
|
UINT SearchBytes;
|
|
UINT ReplaceBytes;
|
|
UINT SearchChars;
|
|
|
|
//
|
|
// Count occurances within the string
|
|
//
|
|
|
|
if (pcbNewString) {
|
|
*pcbNewString = 0;
|
|
}
|
|
|
|
SearchBytes = ByteCountW (SearchString);
|
|
SearchChars = SearchBytes / sizeof (WCHAR);
|
|
ReplaceBytes = ByteCountW (ReplaceString);
|
|
|
|
Count = CountInstancesOfSubStringW (
|
|
SourceString,
|
|
SearchString,
|
|
SearchChars
|
|
);
|
|
|
|
if (!Count) {
|
|
return NULL;
|
|
}
|
|
|
|
Size = SizeOfStringW (SourceString) -
|
|
Count * SearchBytes +
|
|
Count * ReplaceBytes;
|
|
|
|
NewString = (PWSTR) LocalAlloc(LPTR, Size);
|
|
if (!NewString) {
|
|
return NULL;
|
|
}
|
|
|
|
if (pcbNewString) {
|
|
*pcbNewString = Size;
|
|
}
|
|
|
|
p = (PBYTE) SourceString;
|
|
Dest = (PBYTE) NewString;
|
|
|
|
while (*((PWSTR) p)) {
|
|
if (!_wcsnicmp ((PWSTR) p, SearchString, SearchChars)) {
|
|
CopyMemory (Dest, ReplaceString, ReplaceBytes);
|
|
Dest += ReplaceBytes;
|
|
p += SearchBytes;
|
|
} else {
|
|
*((PWSTR) Dest) = *((PWSTR) p);
|
|
p += sizeof (WCHAR);
|
|
Dest += sizeof (WCHAR);
|
|
}
|
|
}
|
|
|
|
*((PWSTR) Dest) = 0;
|
|
|
|
return NewString;
|
|
}
|
|
|
|
|
|
VOID
|
|
RegistrySearchAndReplaceW (
|
|
IN HKEY hRoot,
|
|
IN PCWSTR szKey,
|
|
IN PCWSTR Search,
|
|
IN PCWSTR Replace)
|
|
{
|
|
HKEY hKey = NULL;
|
|
HKEY hSubKey = NULL;
|
|
DWORD dwType;
|
|
DWORD cchMaxSubKeyName, cchNewMaxSubKeyName;
|
|
DWORD cchMaxValueName, cchNewMaxValueName, cchLocalValueName;
|
|
DWORD cbMaxValue, cbNewMaxValue, cbLocalValue, cbNewLocalValue;
|
|
PWSTR szValueName = NULL, szNewValueName = NULL;
|
|
PWSTR szSubKeyName = NULL, szNewSubKeyName = NULL;
|
|
PBYTE pbValue = NULL, pbNewValue = NULL;
|
|
LONG lResult;
|
|
DWORD dwIndex;
|
|
UNICODE_STRING Unicode_String;
|
|
|
|
lResult = RegOpenKey(hRoot, szKey, &hKey);
|
|
if (ERROR_SUCCESS != lResult) {
|
|
DEBUGMSG ((DM_VERBOSE, "Fail to open key %s. Error %d", szKey, lResult));
|
|
return;
|
|
}
|
|
|
|
lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
|
|
&cchMaxSubKeyName, NULL, NULL,
|
|
&cchMaxValueName, &cbMaxValue,
|
|
NULL, NULL);
|
|
if (ERROR_SUCCESS != lResult) {
|
|
DEBUGMSG ((DM_VERBOSE, "Fail to query info for key %s. Error %d", szKey, lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
cchMaxSubKeyName++; // Include the terminating NULL
|
|
cchMaxValueName++; // Include the terminating NULL
|
|
|
|
//
|
|
// Now starts enumerating the value and replace value names &
|
|
// string data with "Replace" string in place of "Search" string
|
|
//
|
|
|
|
// Allocate enough memory
|
|
|
|
szValueName = (LPWSTR) LocalAlloc(LPTR, cchMaxValueName * sizeof(WCHAR));
|
|
if (!szValueName) {
|
|
goto Exit;
|
|
}
|
|
|
|
pbValue = (LPBYTE) LocalAlloc(LPTR, cbMaxValue);
|
|
if (!pbValue) {
|
|
goto Exit;
|
|
}
|
|
|
|
dwIndex = 0;
|
|
cchLocalValueName = cchMaxValueName;
|
|
cbLocalValue = cbMaxValue;
|
|
|
|
while (RegEnumValue(hKey, dwIndex++, szValueName,
|
|
&cchLocalValueName, NULL,
|
|
&dwType, pbValue, &cbLocalValue) == ERROR_SUCCESS) {
|
|
|
|
if (dwType == REG_SZ || dwType == REG_MULTI_SZ || dwType == REG_EXPAND_SZ) {
|
|
|
|
// Construct the new data value only if it's a string
|
|
pbNewValue = (LPBYTE) StringSearchAndReplaceW((PCWSTR)pbValue, Search, Replace, &cbNewLocalValue);
|
|
}
|
|
|
|
// Now construct the new value name by replacing
|
|
|
|
szNewValueName = StringSearchAndReplaceW(szValueName, Search, Replace, NULL);
|
|
|
|
// If the value name or data has changed then write a new value
|
|
|
|
if (szNewValueName || pbNewValue) {
|
|
lResult = RegSetValueEx(hKey,
|
|
szNewValueName ? szNewValueName : szValueName,
|
|
0,
|
|
dwType,
|
|
pbNewValue ? pbNewValue : pbValue,
|
|
pbNewValue ? cbNewLocalValue : cbLocalValue);
|
|
}
|
|
|
|
if (pbNewValue) {
|
|
LocalFree(pbNewValue);
|
|
pbNewValue = NULL;
|
|
}
|
|
|
|
if (szNewValueName) {
|
|
LocalFree(szNewValueName);
|
|
szNewValueName = NULL;
|
|
|
|
if (RegDeleteValue(hKey, szValueName) == ERROR_SUCCESS) {
|
|
//
|
|
// Start from begining, as enumeration index no longer valid
|
|
// with insertion/deletion of value under the key
|
|
//
|
|
|
|
dwIndex = 0;
|
|
|
|
lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, &cchNewMaxValueName,
|
|
&cbNewMaxValue, NULL, NULL);
|
|
if (ERROR_SUCCESS != lResult) {
|
|
DEBUGMSG ((DM_VERBOSE, "Fail to query info for key %s. Error %d", szKey, lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
cchNewMaxValueName++; // Include the terminating NULL
|
|
|
|
if (cchNewMaxValueName > cchMaxValueName) {
|
|
LocalFree(szValueName);
|
|
szValueName = NULL;
|
|
|
|
cchMaxValueName = cchNewMaxValueName;
|
|
szValueName = (LPWSTR) LocalAlloc(LPTR, cchMaxValueName * sizeof(WCHAR));
|
|
if (!szValueName) {
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (cbNewMaxValue > cbMaxValue) {
|
|
LocalFree(pbValue);
|
|
pbValue = NULL;
|
|
|
|
cbMaxValue = cbNewMaxValue;
|
|
pbValue = (LPBYTE) LocalAlloc(LPTR, cbMaxValue);
|
|
if (!pbValue) {
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
cchLocalValueName = cchMaxValueName;
|
|
cbLocalValue = cbMaxValue;
|
|
}
|
|
|
|
LocalFree(szValueName);
|
|
szValueName = NULL;
|
|
LocalFree(pbValue);
|
|
pbValue = NULL;
|
|
|
|
//
|
|
// Now enumerate all the sub keys and replace the name as
|
|
// required in a recursive fashion
|
|
//
|
|
|
|
szSubKeyName = (LPWSTR) LocalAlloc(LPTR, cchMaxSubKeyName * sizeof(WCHAR));
|
|
if (!szSubKeyName) {
|
|
goto Exit;
|
|
}
|
|
|
|
dwIndex = 0;
|
|
|
|
while (RegEnumKey(hKey, dwIndex++,
|
|
szSubKeyName, cchMaxSubKeyName) == ERROR_SUCCESS) {
|
|
|
|
// recursively replace in the sub key tree
|
|
RegistrySearchAndReplaceW(hKey, szSubKeyName, Search, Replace);
|
|
|
|
szNewSubKeyName = StringSearchAndReplaceW(szSubKeyName, Search, Replace, NULL);
|
|
|
|
if (szNewSubKeyName) {
|
|
if (RegOpenKey(hKey, szSubKeyName, &hSubKey) == ERROR_SUCCESS) {
|
|
|
|
Unicode_String.Length = ByteCountW(szNewSubKeyName);
|
|
Unicode_String.MaximumLength = Unicode_String.Length + sizeof(WCHAR);
|
|
Unicode_String.Buffer = szNewSubKeyName;
|
|
|
|
lResult = NtRenameKey(hSubKey, &Unicode_String);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
//
|
|
// Start from begining, as enumeration index no longer valid
|
|
// with rename of sub-keys under the key
|
|
//
|
|
|
|
dwIndex = 0;
|
|
|
|
lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
|
|
&cchNewMaxSubKeyName, NULL, NULL,
|
|
NULL, NULL, NULL, NULL);
|
|
if (ERROR_SUCCESS != lResult) {
|
|
DEBUGMSG ((DM_VERBOSE, "Fail to query info for key %s. Error %d", szKey, lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
cchNewMaxSubKeyName++; // Include the terminating NULL
|
|
|
|
if (cchNewMaxSubKeyName > cchMaxSubKeyName) {
|
|
LocalFree(szSubKeyName);
|
|
szSubKeyName = NULL;
|
|
|
|
cchMaxSubKeyName = cchNewMaxSubKeyName;
|
|
szSubKeyName = (LPWSTR) LocalAlloc(LPTR, cchMaxSubKeyName * sizeof(WCHAR));
|
|
if (!szSubKeyName) {
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
LocalFree(szNewSubKeyName);
|
|
szNewSubKeyName = NULL;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (hKey) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if (szValueName) {
|
|
LocalFree(szValueName);
|
|
}
|
|
|
|
if (pbValue) {
|
|
LocalFree(pbValue);
|
|
}
|
|
|
|
if (szSubKeyName) {
|
|
LocalFree(szSubKeyName);
|
|
}
|
|
}
|
|
|