/*++ 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: () --*/ #include "pch.h" HANDLE g_hHeap; HINSTANCE g_hInst; #ifdef DEBUG #pragma message ("WARNING: Checked builds are very slow") #endif BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID); BOOL pCallEntryPoints ( DWORD Reason ) { HINSTANCE Instance; // // Simulate DllMain // Instance = g_hInst; // // Initialize the common libs // if (!MigUtil_Entry (Instance, Reason, NULL)) { return FALSE; } return TRUE; } BOOL Init ( VOID ) { g_hHeap = GetProcessHeap(); g_hInst = GetModuleHandle (NULL); return pCallEntryPoints (DLL_PROCESS_ATTACH); } VOID Terminate ( VOID ) { pCallEntryPoints (DLL_PROCESS_DETACH); } VOID HelpAndExit ( VOID ) { // // This routine is called whenever command line args are wrong // _ftprintf ( stderr, TEXT("Command Line Syntax:\n\n") TEXT(" regrep [-r:root] [-p]\n") TEXT("\nDescription:\n\n") TEXT(" RegRep implements a registry search and replace. It updates\n") TEXT(" all instances of with .\n") TEXT("\nArguments:\n\n") TEXT(" Specifies the search text\n") TEXT(" Specifies the replace text\n") TEXT(" -r Specifies the root key to process, such as HKLM\\Software.\n") TEXT(" If not specified, the entire registry is processed.\n") TEXT(" -p Enables progress output\n") ); exit (1); } VOID pUpdateKeyNames ( IN PCTSTR Search, IN PCTSTR Replace, IN PCTSTR RootKey ); VOID pUpdateValueNames ( IN PCTSTR Search, IN PCTSTR Replace, IN PCTSTR RootKey ); VOID pUpdateValueData ( IN PCTSTR Search, IN PCTSTR Replace, IN PCTSTR RootKey ); BOOL g_ShowProgress = FALSE; VOID pProgress ( VOID ) { static CHAR String[] = "...... "; static DWORD Ticks = 0; PSTR p; if (GetTickCount() - Ticks < 500) { return; } Ticks = GetTickCount(); if (!g_ShowProgress) { return; } p = strchr (String, ' '); *p = '.'; p++; if (!*p) { p = String; } *p = ' '; printf ("%s\r", String); } INT __cdecl _tmain ( INT argc, PCTSTR argv[] ) { INT i; PCTSTR Root = NULL; PCTSTR Search = NULL; PCTSTR Replace = NULL; // // TODO: Parse command line here // for (i = 1 ; i < argc ; i++) { if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) { switch (_totlower (_tcsnextc (&argv[i][1]))) { case TEXT('r'): if (Root) { HelpAndExit(); } if (argv[i][2] == TEXT(':')) { Root = &argv[i][3]; } else if (i + 1 < argc) { Root = argv[++i]; } else { HelpAndExit(); } break; case TEXT('p'): if (g_ShowProgress) { HelpAndExit(); } g_ShowProgress = TRUE; break; default: HelpAndExit(); } } else { // // Parse other args that don't require / or - // if (!Search) { Search = argv[i]; } else if (!Replace) { Replace = argv[i]; } else { HelpAndExit(); } } } if (!Replace) { HelpAndExit(); } // // Begin processing // if (!Init()) { return 0; } // // Pass one - fix all the registry key names // if (!Root) { pUpdateKeyNames (Search, Replace, TEXT("HKLM")); pUpdateKeyNames (Search, Replace, TEXT("HKU")); } else { pUpdateKeyNames (Search, Replace, Root); } // // Pass two - fix all value names // if (!Root) { pUpdateValueNames (Search, Replace, TEXT("HKLM")); pUpdateValueNames (Search, Replace, TEXT("HKU")); } else { pUpdateValueNames (Search, Replace, Root); } // // Pass three - fix all value data // if (!Root) { pUpdateValueData (Search, Replace, TEXT("HKLM")); pUpdateValueData (Search, Replace, TEXT("HKU")); } else { pUpdateValueData (Search, Replace, Root); } // // End of processing // Terminate(); return 0; } VOID pMoveKey ( IN PCTSTR SourceKey, IN PCTSTR DestKey ) { HKEY Src; HKEY Dest; REGVALUE_ENUM e; DWORD Size; PBYTE Data; LONG rc; GROWBUFFER Buf = GROWBUF_INIT; Src = OpenRegKeyStr (SourceKey); Dest = CreateRegKeyStr (DestKey); pProgress(); if (Src && Dest) { if (EnumFirstRegValue (&e, Src)) { Buf.End = 0; Data = GrowBuffer (&Buf, e.DataSize); if (Data) { Size = e.DataSize; rc = RegQueryValueEx ( Src, e.ValueName, NULL, NULL, Data, &Size ); if (rc == ERROR_SUCCESS) { rc = RegSetValueEx (Dest, e.ValueName, 0, e.Type, Data, Size); } } } } CloseRegKey (Src); CloseRegKey (Dest); FreeGrowBuffer (&Buf); } VOID pMoveKeyTree ( IN PCTSTR SourceKey, IN PCTSTR DestKey ) { REGTREE_ENUM e; TCHAR DestSubKey[MAX_REGISTRY_KEY]; PTSTR p; GROWLIST List = GROWLIST_INIT; UINT Count; UINT u; PCTSTR Item; DWORD Len; StringCopy (DestSubKey, DestKey); p = AppendWack (DestSubKey); if (EnumFirstRegKeyInTree (&e, SourceKey)) { do { StringCopy (p, (PCTSTR) ((PBYTE) e.FullKeyName + e.EnumBaseBytes)); pMoveKey (e.FullKeyName, DestSubKey); GrowListAppendString (&List, e.FullKeyName); } while (EnumNextRegKeyInTree (&e)); } Count = GrowListGetSize (&List); u = Count; while (u > 0) { u--; Item = GrowListGetString (&List, u); ConvertRootStringToKey (Item, &Len); RegDeleteKey (ConvertRootStringToKey (Item, NULL), Item + Len); } FreeGrowList (&List); } VOID pUpdateKeyNames ( IN PCTSTR Search, IN PCTSTR Replace, IN PCTSTR RootKey ) { REGTREE_ENUM e; GROWLIST List = GROWLIST_INIT; UINT Count; UINT u; PCTSTR OldKey; PCTSTR NewKey; if (g_ShowProgress) { _tprintf ("Scanning for keys to update\n"); } if (EnumFirstRegKeyInTree (&e, RootKey)) { do { pProgress(); if (_tcsistr (e.CurrentKey->KeyName, Search)) { GrowListAppendString (&List, e.FullKeyName); } } while (EnumNextRegKeyInTree (&e)); } Count = GrowListGetSize (&List); u = Count; if (g_ShowProgress) { _tprintf ("Updating %u keys\n", Count); } while (u > 0) { u--; _tprintf (TEXT("%s\n"), GrowListGetString (&List, u)); OldKey = GrowListGetString (&List, u); NewKey = StringSearchAndReplace ( OldKey, Search, Replace ); pMoveKeyTree (OldKey, NewKey); } FreeGrowList (&List); } VOID pUpdateValueNames ( IN PCTSTR Search, IN PCTSTR Replace, IN PCTSTR RootKey ) { REGTREE_ENUM e; REGVALUE_ENUM ev; GROWLIST List = GROWLIST_INIT; HKEY Key; UINT Count; UINT u; PBYTE Data; DWORD Type; DWORD Size; PCTSTR ValueName; PCTSTR NewValueName; BOOL b; LONG rc; if (g_ShowProgress) { _tprintf ("Processing all value names in the keys\n"); } if (EnumFirstRegKeyInTree (&e, RootKey)) { do { pProgress(); Key = OpenRegKeyStr (e.FullKeyName); if (Key) { if (EnumFirstRegValue (&ev, Key)) { do { if (_tcsistr (ev.ValueName, Search)) { GrowListAppendString (&List, ev.ValueName); } } while (EnumNextRegValue (&ev)); Count = GrowListGetSize (&List); u = Count; while (u > 0) { u--; ValueName = GrowListGetString (&List, u); b = FALSE; if (GetRegValueTypeAndSize (Key, ValueName, &Type, &Size)) { Data = GetRegValueData (Key, ValueName); if (Data) { NewValueName = StringSearchAndReplace ( ValueName, Search, Replace ); rc = RegSetValueEx (Key, NewValueName, 0, Type, Data, Size); if (rc == ERROR_SUCCESS) { if (!StringIMatch (ValueName, NewValueName)) { rc = RegDeleteValue (Key, ValueName); } } MemFree (g_hHeap, 0, Data); FreePathString (NewValueName); SetLastError (rc); b = (rc == ERROR_SUCCESS); } } if (b) { _tprintf (TEXT("%s [%s]\n"), e.FullKeyName, ValueName); } else { _ftprintf (stderr, TEXT("Error %u updating %s [%s]\n"), GetLastError(), e.FullKeyName, ValueName); } } } FreeGrowList (&List); CloseRegKey (Key); } else { _ftprintf (stderr, TEXT("Can't open %s\n"), Key); } } while (EnumNextRegKeyInTree (&e)); } } VOID pUpdateValueData ( IN PCTSTR Search, IN PCTSTR Replace, IN PCTSTR RootKey ) { REGTREE_ENUM e; REGVALUE_ENUM ev; HKEY Key; PCTSTR Data; PCTSTR NewData; LONG rc; if (g_ShowProgress) { _tprintf ("Processing all value data\n"); } if (EnumFirstRegKeyInTree (&e, RootKey)) { do { pProgress(); Key = OpenRegKeyStr (e.FullKeyName); if (Key) { if (EnumFirstRegValue (&ev, Key)) { do { Data = GetRegValueString (Key, ev.ValueName); if (Data) { if (_tcsistr (Data, Search)) { NewData = StringSearchAndReplace (Data, Search, Replace); rc = RegSetValueEx (Key, ev.ValueName, 0, ev.Type, NewData, SizeOfString (NewData)); if (rc == ERROR_SUCCESS) { _tprintf (TEXT("%s [%s] %s\n"), e.FullKeyName, ev.ValueName, Data); } else { _ftprintf (stderr, TEXT("Error %u updating %s [%s] %s\n"), GetLastError(), e.FullKeyName, ev.ValueName, Data); } FreePathString (NewData); } MemFree (g_hHeap, 0, Data); } } while (EnumNextRegValue (&ev)); } CloseRegKey (Key); } else { _ftprintf (stderr, TEXT("Can't open %s\n"), Key); } } while (EnumNextRegKeyInTree (&e)); } }