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.

595 lines
13 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. regrep.c
  5. Abstract:
  6. Implements a registry search/replace tool.
  7. Author:
  8. Jim Schmidt (jimschm) 19-Apr-1999
  9. Revision History:
  10. <full name> (<alias>) <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. HANDLE g_hHeap;
  14. HINSTANCE g_hInst;
  15. #ifdef DEBUG
  16. #pragma message ("WARNING: Checked builds are very slow")
  17. #endif
  18. BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
  19. BOOL
  20. pCallEntryPoints (
  21. DWORD Reason
  22. )
  23. {
  24. HINSTANCE Instance;
  25. //
  26. // Simulate DllMain
  27. //
  28. Instance = g_hInst;
  29. //
  30. // Initialize the common libs
  31. //
  32. if (!MigUtil_Entry (Instance, Reason, NULL)) {
  33. return FALSE;
  34. }
  35. return TRUE;
  36. }
  37. BOOL
  38. Init (
  39. VOID
  40. )
  41. {
  42. g_hHeap = GetProcessHeap();
  43. g_hInst = GetModuleHandle (NULL);
  44. return pCallEntryPoints (DLL_PROCESS_ATTACH);
  45. }
  46. VOID
  47. Terminate (
  48. VOID
  49. )
  50. {
  51. pCallEntryPoints (DLL_PROCESS_DETACH);
  52. }
  53. VOID
  54. HelpAndExit (
  55. VOID
  56. )
  57. {
  58. //
  59. // This routine is called whenever command line args are wrong
  60. //
  61. _ftprintf (
  62. stderr,
  63. TEXT("Command Line Syntax:\n\n")
  64. TEXT(" regrep <srch> <rep> [-r:root] [-p]\n")
  65. TEXT("\nDescription:\n\n")
  66. TEXT(" RegRep implements a registry search and replace. It updates\n")
  67. TEXT(" all instances of <srch> with <rep>.\n")
  68. TEXT("\nArguments:\n\n")
  69. TEXT(" <srch> Specifies the search text\n")
  70. TEXT(" <rep> Specifies the replace text\n")
  71. TEXT(" -r Specifies the root key to process, such as HKLM\\Software.\n")
  72. TEXT(" If not specified, the entire registry is processed.\n")
  73. TEXT(" -p Enables progress output\n")
  74. );
  75. exit (1);
  76. }
  77. VOID
  78. pUpdateKeyNames (
  79. IN PCTSTR Search,
  80. IN PCTSTR Replace,
  81. IN PCTSTR RootKey
  82. );
  83. VOID
  84. pUpdateValueNames (
  85. IN PCTSTR Search,
  86. IN PCTSTR Replace,
  87. IN PCTSTR RootKey
  88. );
  89. VOID
  90. pUpdateValueData (
  91. IN PCTSTR Search,
  92. IN PCTSTR Replace,
  93. IN PCTSTR RootKey
  94. );
  95. BOOL g_ShowProgress = FALSE;
  96. VOID
  97. pProgress (
  98. VOID
  99. )
  100. {
  101. static CHAR String[] = "...... ";
  102. static DWORD Ticks = 0;
  103. PSTR p;
  104. if (GetTickCount() - Ticks < 500) {
  105. return;
  106. }
  107. Ticks = GetTickCount();
  108. if (!g_ShowProgress) {
  109. return;
  110. }
  111. p = strchr (String, ' ');
  112. *p = '.';
  113. p++;
  114. if (!*p) {
  115. p = String;
  116. }
  117. *p = ' ';
  118. printf ("%s\r", String);
  119. }
  120. INT
  121. __cdecl
  122. _tmain (
  123. INT argc,
  124. PCTSTR argv[]
  125. )
  126. {
  127. INT i;
  128. PCTSTR Root = NULL;
  129. PCTSTR Search = NULL;
  130. PCTSTR Replace = NULL;
  131. //
  132. // TODO: Parse command line here
  133. //
  134. for (i = 1 ; i < argc ; i++) {
  135. if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) {
  136. switch (_totlower (_tcsnextc (&argv[i][1]))) {
  137. case TEXT('r'):
  138. if (Root) {
  139. HelpAndExit();
  140. }
  141. if (argv[i][2] == TEXT(':')) {
  142. Root = &argv[i][3];
  143. } else if (i + 1 < argc) {
  144. Root = argv[++i];
  145. } else {
  146. HelpAndExit();
  147. }
  148. break;
  149. case TEXT('p'):
  150. if (g_ShowProgress) {
  151. HelpAndExit();
  152. }
  153. g_ShowProgress = TRUE;
  154. break;
  155. default:
  156. HelpAndExit();
  157. }
  158. } else {
  159. //
  160. // Parse other args that don't require / or -
  161. //
  162. if (!Search) {
  163. Search = argv[i];
  164. } else if (!Replace) {
  165. Replace = argv[i];
  166. } else {
  167. HelpAndExit();
  168. }
  169. }
  170. }
  171. if (!Replace) {
  172. HelpAndExit();
  173. }
  174. //
  175. // Begin processing
  176. //
  177. if (!Init()) {
  178. return 0;
  179. }
  180. //
  181. // Pass one - fix all the registry key names
  182. //
  183. if (!Root) {
  184. pUpdateKeyNames (Search, Replace, TEXT("HKLM"));
  185. pUpdateKeyNames (Search, Replace, TEXT("HKU"));
  186. } else {
  187. pUpdateKeyNames (Search, Replace, Root);
  188. }
  189. //
  190. // Pass two - fix all value names
  191. //
  192. if (!Root) {
  193. pUpdateValueNames (Search, Replace, TEXT("HKLM"));
  194. pUpdateValueNames (Search, Replace, TEXT("HKU"));
  195. } else {
  196. pUpdateValueNames (Search, Replace, Root);
  197. }
  198. //
  199. // Pass three - fix all value data
  200. //
  201. if (!Root) {
  202. pUpdateValueData (Search, Replace, TEXT("HKLM"));
  203. pUpdateValueData (Search, Replace, TEXT("HKU"));
  204. } else {
  205. pUpdateValueData (Search, Replace, Root);
  206. }
  207. //
  208. // End of processing
  209. //
  210. Terminate();
  211. return 0;
  212. }
  213. VOID
  214. pMoveKey (
  215. IN PCTSTR SourceKey,
  216. IN PCTSTR DestKey
  217. )
  218. {
  219. HKEY Src;
  220. HKEY Dest;
  221. REGVALUE_ENUM e;
  222. DWORD Size;
  223. PBYTE Data;
  224. LONG rc;
  225. GROWBUFFER Buf = GROWBUF_INIT;
  226. Src = OpenRegKeyStr (SourceKey);
  227. Dest = CreateRegKeyStr (DestKey);
  228. pProgress();
  229. if (Src && Dest) {
  230. if (EnumFirstRegValue (&e, Src)) {
  231. Buf.End = 0;
  232. Data = GrowBuffer (&Buf, e.DataSize);
  233. if (Data) {
  234. Size = e.DataSize;
  235. rc = RegQueryValueEx (
  236. Src,
  237. e.ValueName,
  238. NULL,
  239. NULL,
  240. Data,
  241. &Size
  242. );
  243. if (rc == ERROR_SUCCESS) {
  244. rc = RegSetValueEx (Dest, e.ValueName, 0, e.Type, Data, Size);
  245. }
  246. }
  247. }
  248. }
  249. CloseRegKey (Src);
  250. CloseRegKey (Dest);
  251. FreeGrowBuffer (&Buf);
  252. }
  253. VOID
  254. pMoveKeyTree (
  255. IN PCTSTR SourceKey,
  256. IN PCTSTR DestKey
  257. )
  258. {
  259. REGTREE_ENUM e;
  260. TCHAR DestSubKey[MAX_REGISTRY_KEY];
  261. PTSTR p;
  262. GROWLIST List = GROWLIST_INIT;
  263. UINT Count;
  264. UINT u;
  265. PCTSTR Item;
  266. DWORD Len;
  267. StringCopy (DestSubKey, DestKey);
  268. p = AppendWack (DestSubKey);
  269. if (EnumFirstRegKeyInTree (&e, SourceKey)) {
  270. do {
  271. StringCopy (p, (PCTSTR) ((PBYTE) e.FullKeyName + e.EnumBaseBytes));
  272. pMoveKey (e.FullKeyName, DestSubKey);
  273. GrowListAppendString (&List, e.FullKeyName);
  274. } while (EnumNextRegKeyInTree (&e));
  275. }
  276. Count = GrowListGetSize (&List);
  277. u = Count;
  278. while (u > 0) {
  279. u--;
  280. Item = GrowListGetString (&List, u);
  281. ConvertRootStringToKey (Item, &Len);
  282. RegDeleteKey (ConvertRootStringToKey (Item, NULL), Item + Len);
  283. }
  284. FreeGrowList (&List);
  285. }
  286. VOID
  287. pUpdateKeyNames (
  288. IN PCTSTR Search,
  289. IN PCTSTR Replace,
  290. IN PCTSTR RootKey
  291. )
  292. {
  293. REGTREE_ENUM e;
  294. GROWLIST List = GROWLIST_INIT;
  295. UINT Count;
  296. UINT u;
  297. PCTSTR OldKey;
  298. PCTSTR NewKey;
  299. if (g_ShowProgress) {
  300. _tprintf ("Scanning for keys to update\n");
  301. }
  302. if (EnumFirstRegKeyInTree (&e, RootKey)) {
  303. do {
  304. pProgress();
  305. if (_tcsistr (e.CurrentKey->KeyName, Search)) {
  306. GrowListAppendString (&List, e.FullKeyName);
  307. }
  308. } while (EnumNextRegKeyInTree (&e));
  309. }
  310. Count = GrowListGetSize (&List);
  311. u = Count;
  312. if (g_ShowProgress) {
  313. _tprintf ("Updating %u keys\n", Count);
  314. }
  315. while (u > 0) {
  316. u--;
  317. _tprintf (TEXT("%s\n"), GrowListGetString (&List, u));
  318. OldKey = GrowListGetString (&List, u);
  319. NewKey = StringSearchAndReplace (
  320. OldKey,
  321. Search,
  322. Replace
  323. );
  324. pMoveKeyTree (OldKey, NewKey);
  325. }
  326. FreeGrowList (&List);
  327. }
  328. VOID
  329. pUpdateValueNames (
  330. IN PCTSTR Search,
  331. IN PCTSTR Replace,
  332. IN PCTSTR RootKey
  333. )
  334. {
  335. REGTREE_ENUM e;
  336. REGVALUE_ENUM ev;
  337. GROWLIST List = GROWLIST_INIT;
  338. HKEY Key;
  339. UINT Count;
  340. UINT u;
  341. PBYTE Data;
  342. DWORD Type;
  343. DWORD Size;
  344. PCTSTR ValueName;
  345. PCTSTR NewValueName;
  346. BOOL b;
  347. LONG rc;
  348. if (g_ShowProgress) {
  349. _tprintf ("Processing all value names in the keys\n");
  350. }
  351. if (EnumFirstRegKeyInTree (&e, RootKey)) {
  352. do {
  353. pProgress();
  354. Key = OpenRegKeyStr (e.FullKeyName);
  355. if (Key) {
  356. if (EnumFirstRegValue (&ev, Key)) {
  357. do {
  358. if (_tcsistr (ev.ValueName, Search)) {
  359. GrowListAppendString (&List, ev.ValueName);
  360. }
  361. } while (EnumNextRegValue (&ev));
  362. Count = GrowListGetSize (&List);
  363. u = Count;
  364. while (u > 0) {
  365. u--;
  366. ValueName = GrowListGetString (&List, u);
  367. b = FALSE;
  368. if (GetRegValueTypeAndSize (Key, ValueName, &Type, &Size)) {
  369. Data = GetRegValueData (Key, ValueName);
  370. if (Data) {
  371. NewValueName = StringSearchAndReplace (
  372. ValueName,
  373. Search,
  374. Replace
  375. );
  376. rc = RegSetValueEx (Key, NewValueName, 0, Type, Data, Size);
  377. if (rc == ERROR_SUCCESS) {
  378. if (!StringIMatch (ValueName, NewValueName)) {
  379. rc = RegDeleteValue (Key, ValueName);
  380. }
  381. }
  382. MemFree (g_hHeap, 0, Data);
  383. FreePathString (NewValueName);
  384. SetLastError (rc);
  385. b = (rc == ERROR_SUCCESS);
  386. }
  387. }
  388. if (b) {
  389. _tprintf (TEXT("%s [%s]\n"), e.FullKeyName, ValueName);
  390. } else {
  391. _ftprintf (stderr, TEXT("Error %u updating %s [%s]\n"), GetLastError(), e.FullKeyName, ValueName);
  392. }
  393. }
  394. }
  395. FreeGrowList (&List);
  396. CloseRegKey (Key);
  397. } else {
  398. _ftprintf (stderr, TEXT("Can't open %s\n"), Key);
  399. }
  400. } while (EnumNextRegKeyInTree (&e));
  401. }
  402. }
  403. VOID
  404. pUpdateValueData (
  405. IN PCTSTR Search,
  406. IN PCTSTR Replace,
  407. IN PCTSTR RootKey
  408. )
  409. {
  410. REGTREE_ENUM e;
  411. REGVALUE_ENUM ev;
  412. HKEY Key;
  413. PCTSTR Data;
  414. PCTSTR NewData;
  415. LONG rc;
  416. if (g_ShowProgress) {
  417. _tprintf ("Processing all value data\n");
  418. }
  419. if (EnumFirstRegKeyInTree (&e, RootKey)) {
  420. do {
  421. pProgress();
  422. Key = OpenRegKeyStr (e.FullKeyName);
  423. if (Key) {
  424. if (EnumFirstRegValue (&ev, Key)) {
  425. do {
  426. Data = GetRegValueString (Key, ev.ValueName);
  427. if (Data) {
  428. if (_tcsistr (Data, Search)) {
  429. NewData = StringSearchAndReplace (Data, Search, Replace);
  430. rc = RegSetValueEx (Key, ev.ValueName, 0, ev.Type, NewData, SizeOfString (NewData));
  431. if (rc == ERROR_SUCCESS) {
  432. _tprintf (TEXT("%s [%s] %s\n"), e.FullKeyName, ev.ValueName, Data);
  433. } else {
  434. _ftprintf (stderr, TEXT("Error %u updating %s [%s] %s\n"), GetLastError(), e.FullKeyName, ev.ValueName, Data);
  435. }
  436. FreePathString (NewData);
  437. }
  438. MemFree (g_hHeap, 0, Data);
  439. }
  440. } while (EnumNextRegValue (&ev));
  441. }
  442. CloseRegKey (Key);
  443. } else {
  444. _ftprintf (stderr, TEXT("Can't open %s\n"), Key);
  445. }
  446. } while (EnumNextRegKeyInTree (&e));
  447. }
  448. }