Source code of Windows XP (NT5)
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.

870 lines
17 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. jimschm 26-May-1999 Moved from win9xupg, ported to use different
  11. utilities
  12. --*/
  13. #include "pch.h"
  14. VOID
  15. pUpdateKeyNames (
  16. IN PCWSTR Search,
  17. IN PCWSTR Replace,
  18. IN PCWSTR RootKey
  19. );
  20. VOID
  21. pUpdateValueNames (
  22. IN PCWSTR Search,
  23. IN PCWSTR Replace,
  24. IN PCWSTR RootKey
  25. );
  26. VOID
  27. pUpdateValueData (
  28. IN PCWSTR Search,
  29. IN PCWSTR Replace,
  30. IN PCWSTR RootKey
  31. );
  32. PWSTR
  33. AppendWackW (
  34. IN PWSTR str
  35. )
  36. {
  37. PCWSTR Last;
  38. if (!str)
  39. return str;
  40. if (*str) {
  41. str = GetEndOfStringW (str);
  42. Last = str - 1;
  43. } else {
  44. Last = str;
  45. }
  46. if (*Last != '\\') {
  47. *str = L'\\';
  48. str++;
  49. *str = 0;
  50. }
  51. return str;
  52. }
  53. VOID
  54. RegistrySearchAndReplaceW (
  55. IN PCWSTR Root,
  56. IN PCWSTR Search,
  57. IN PCWSTR Replace
  58. )
  59. {
  60. pUpdateKeyNames (Search, Replace, Root);
  61. pUpdateValueNames (Search, Replace, Root);
  62. pUpdateValueData (Search, Replace, Root);
  63. }
  64. PCWSTR
  65. _wcsistr (
  66. PCWSTR wstrStr,
  67. PCWSTR wstrSubStr
  68. )
  69. {
  70. PCWSTR wstrStart, wstrStrPos, wstrSubStrPos;
  71. PCWSTR wstrEnd;
  72. wstrEnd = (PWSTR) ((LPBYTE) wstrStr + ByteCountW (wstrStr) - ByteCountW (wstrSubStr));
  73. for (wstrStart = wstrStr ; wstrStart <= wstrEnd ; wstrStart++) {
  74. wstrStrPos = wstrStart;
  75. wstrSubStrPos = wstrSubStr;
  76. while (*wstrSubStrPos &&
  77. towlower (*wstrSubStrPos) == towlower (*wstrStrPos))
  78. {
  79. wstrStrPos++;
  80. wstrSubStrPos++;
  81. }
  82. if (!(*wstrSubStrPos))
  83. return wstrStart;
  84. }
  85. return NULL;
  86. }
  87. #define DEFAULT_GROW_SIZE 8192
  88. PBYTE
  89. GrowBuffer (
  90. IN OUT PGROWBUFFER GrowBuf,
  91. IN DWORD SpaceNeeded
  92. )
  93. /*++
  94. Routine Description:
  95. GrowBuffer makes sure there is enough bytes in the buffer
  96. to accomodate SpaceNeeded. It allocates an initial buffer
  97. when no buffer is allocated, and it reallocates the buffer
  98. in increments of GrowBuf->Size (or DEFAULT_GROW_SIZE) when
  99. needed.
  100. Arguments:
  101. GrowBuf - A pointer to a GROWBUFFER structure.
  102. Initialize this structure to zero for
  103. the first call to GrowBuffer.
  104. SpaceNeeded - The number of free bytes needed in the buffer
  105. Return Value:
  106. A pointer to the SpaceNeeded bytes, or NULL if a memory allocation
  107. error occurred.
  108. --*/
  109. {
  110. PBYTE NewBuffer;
  111. DWORD TotalSpaceNeeded;
  112. DWORD GrowTo;
  113. if (!GrowBuf->Buf) {
  114. GrowBuf->Size = 0;
  115. GrowBuf->End = 0;
  116. }
  117. if (!GrowBuf->GrowSize) {
  118. GrowBuf->GrowSize = DEFAULT_GROW_SIZE;
  119. }
  120. TotalSpaceNeeded = GrowBuf->End + SpaceNeeded;
  121. if (TotalSpaceNeeded > GrowBuf->Size) {
  122. GrowTo = (TotalSpaceNeeded + GrowBuf->GrowSize) - (TotalSpaceNeeded % GrowBuf->GrowSize);
  123. } else {
  124. GrowTo = 0;
  125. }
  126. if (!GrowBuf->Buf) {
  127. GrowBuf->Buf = (PBYTE) MemAlloc (GrowTo);
  128. if (!GrowBuf->Buf) {
  129. DEBUGMSG ((DM_WARNING, "GrowBuffer: Initial alloc failed"));
  130. return NULL;
  131. }
  132. GrowBuf->Size = GrowTo;
  133. } else if (GrowTo) {
  134. NewBuffer = MemReAlloc (GrowBuf->Buf, GrowTo);
  135. if (!NewBuffer) {
  136. DEBUGMSG ((DM_WARNING, "GrowBuffer: Realloc failed"));
  137. return NULL;
  138. }
  139. GrowBuf->Size = GrowTo;
  140. GrowBuf->Buf = NewBuffer;
  141. }
  142. NewBuffer = GrowBuf->Buf + GrowBuf->End;
  143. GrowBuf->End += SpaceNeeded;
  144. return NewBuffer;
  145. }
  146. VOID
  147. FreeGrowBuffer (
  148. IN PGROWBUFFER GrowBuf
  149. )
  150. /*++
  151. Routine Description:
  152. FreeGrowBuffer frees a buffer allocated by GrowBuffer.
  153. Arguments:
  154. GrowBuf - A pointer to the same structure passed to GrowBuffer
  155. Return Value:
  156. none
  157. --*/
  158. {
  159. if (GrowBuf->Buf) {
  160. MemFree (GrowBuf->Buf);
  161. ZeroMemory (GrowBuf, sizeof (GROWBUFFER));
  162. }
  163. }
  164. #define INSERT_LAST 0xffffffff
  165. PBYTE
  166. pGrowListAdd (
  167. IN OUT PGROWLIST GrowList,
  168. IN UINT InsertBefore,
  169. IN PBYTE DataToAdd, OPTIONAL
  170. IN UINT SizeOfData,
  171. IN UINT NulBytesToAdd
  172. )
  173. /*++
  174. Routine Description:
  175. pGrowListAdd allocates memory for a binary block by using a pool, and
  176. then expands an array of pointers, maintaining a quick-access list.
  177. Arguments:
  178. GrowList - Specifies the list to add the entry to
  179. InsertBefore - Specifies the index of the array element to insert
  180. before, or INSERT_LIST to append.
  181. DataToAdd - Specifies the binary block of data to add.
  182. SizeOfData - Specifies the size of data.
  183. NulBytesToAdd - Specifies the number of nul bytes to add to the buffer
  184. Return Value:
  185. A pointer to the binary block if data was copied into the list, 1 if a list
  186. item was created but no data was set for the item, or NULL if an error
  187. occurred.
  188. --*/
  189. {
  190. PBYTE *Item;
  191. PBYTE *InsertAt;
  192. PBYTE Data;
  193. UINT OldEnd;
  194. UINT Size;
  195. UINT TotalSize;
  196. TotalSize = SizeOfData + NulBytesToAdd;
  197. //
  198. // Allocate pool if necessary
  199. //
  200. if (!GrowList->ListData) {
  201. GrowList->ListData = PoolMemInitNamedPool ("GrowList");
  202. if (!GrowList->ListData) {
  203. return NULL;
  204. }
  205. }
  206. //
  207. // Expand list array
  208. //
  209. OldEnd = GrowList->ListArray.End;
  210. Item = (PBYTE *) GrowBuffer (&GrowList->ListArray, sizeof (PBYTE));
  211. if (!Item) {
  212. return NULL;
  213. }
  214. //
  215. // Copy data
  216. //
  217. if (DataToAdd || NulBytesToAdd) {
  218. Data = PoolMemGetAlignedMemory (GrowList->ListData, TotalSize);
  219. if (!Data) {
  220. GrowList->ListArray.End = OldEnd;
  221. return NULL;
  222. }
  223. if (DataToAdd) {
  224. CopyMemory (Data, DataToAdd, SizeOfData);
  225. }
  226. if (NulBytesToAdd) {
  227. ZeroMemory (Data + SizeOfData, NulBytesToAdd);
  228. }
  229. } else {
  230. Data = NULL;
  231. }
  232. //
  233. // Adjust array
  234. //
  235. Size = GrowListGetSize (GrowList);
  236. if (InsertBefore >= Size) {
  237. //
  238. // Append mode
  239. //
  240. *Item = Data;
  241. } else {
  242. //
  243. // Insert mode
  244. //
  245. InsertAt = (PBYTE *) (GrowList->ListArray.Buf) + InsertBefore;
  246. MoveMemory (&InsertAt[1], InsertAt, (Size - InsertBefore) * sizeof (PBYTE));
  247. *InsertAt = Data;
  248. }
  249. return Data ? Data : (PBYTE) 1;
  250. }
  251. VOID
  252. FreeGrowList (
  253. IN PGROWLIST GrowList
  254. )
  255. /*++
  256. Routine Description:
  257. FreeGrowList frees the resources allocated by a GROWLIST.
  258. Arguments:
  259. GrowList - Specifies the list to clean up
  260. Return Value:
  261. none
  262. --*/
  263. {
  264. FreeGrowBuffer (&GrowList->ListArray);
  265. if (GrowList->ListData) {
  266. PoolMemDestroyPool (GrowList->ListData);
  267. }
  268. ZeroMemory (GrowList, sizeof (GROWLIST));
  269. }
  270. PBYTE
  271. GrowListGetItem (
  272. IN PGROWLIST GrowList,
  273. IN UINT Index
  274. )
  275. /*++
  276. Routine Description:
  277. GrowListGetItem returns a pointer to the block of data
  278. for item specified by Index.
  279. Arguments:
  280. GrowList - Specifies the list to access
  281. Index - Specifies zero-based index of item in list to access
  282. Return Value:
  283. A pointer to the item's data, or NULL if the Index does not
  284. represent an actual item.
  285. --*/
  286. {
  287. PBYTE *ItemPtr;
  288. UINT Size;
  289. Size = GrowListGetSize (GrowList);
  290. if (Index >= Size) {
  291. return NULL;
  292. }
  293. ItemPtr = (PBYTE *) (GrowList->ListArray.Buf);
  294. return ItemPtr[Index];
  295. }
  296. UINT
  297. GrowListGetSize (
  298. IN PGROWLIST GrowList
  299. )
  300. /*++
  301. Routine Description:
  302. GrowListGetSize calculates the number of items in the list.
  303. Arguments:
  304. GrowList - Specifies the list to calculate the size of
  305. Return Value:
  306. The number of items in the list, or zero if the list is empty.
  307. --*/
  308. {
  309. return GrowList->ListArray.End / sizeof (PBYTE);
  310. }
  311. PBYTE
  312. GrowListAppend (
  313. IN OUT PGROWLIST GrowList,
  314. IN PBYTE DataToAppend, OPTIONAL
  315. IN UINT SizeOfData
  316. )
  317. /*++
  318. Routine Description:
  319. GrowListAppend appends a black of data as a new list item.
  320. Arguments:
  321. GrowList - Specifies the list to modify
  322. DataToAppend - Specifies a block of data to be copied
  323. SizeOfData - Specifies the number of bytes in DataToAppend
  324. Return Value:
  325. A pointer to the binary block if data was copied into the list, 1 if a list
  326. item was created but no data was set for the item, or NULL if an error
  327. occurred.
  328. --*/
  329. {
  330. return pGrowListAdd (GrowList, INSERT_LAST, DataToAppend, SizeOfData, 0);
  331. }
  332. VOID
  333. pMoveKey (
  334. IN PCWSTR SourceKey,
  335. IN PCWSTR DestKey
  336. )
  337. {
  338. HKEY Src;
  339. HKEY Dest;
  340. REGVALUE_ENUM e;
  341. DWORD Size;
  342. PBYTE Data;
  343. LONG rc;
  344. GROWBUFFER Buf = GROWBUF_INIT;
  345. Src = OpenRegKeyStr (SourceKey);
  346. Dest = CreateRegKeyStr (DestKey);
  347. if (Src && Dest) {
  348. if (EnumFirstRegValue (&e, Src)) {
  349. Buf.End = 0;
  350. Data = GrowBuffer (&Buf, e.DataSize);
  351. if (Data) {
  352. Size = e.DataSize;
  353. rc = RegQueryValueEx (
  354. Src,
  355. e.ValueName,
  356. NULL,
  357. NULL,
  358. Data,
  359. &Size
  360. );
  361. if (rc == ERROR_SUCCESS) {
  362. rc = RegSetValueEx (Dest, e.ValueName, 0, e.Type, Data, Size);
  363. }
  364. }
  365. }
  366. }
  367. CloseRegKey (Src);
  368. CloseRegKey (Dest);
  369. FreeGrowBuffer (&Buf);
  370. }
  371. PBYTE
  372. RealGrowListAppendAddNul (
  373. IN OUT PGROWLIST GrowList,
  374. IN PBYTE DataToAppend, OPTIONAL
  375. IN UINT SizeOfData
  376. )
  377. /*++
  378. Routine Description:
  379. GrowListAppend appends a black of data as a new list item and
  380. appends two zero bytes (used for string termination).
  381. Arguments:
  382. GrowList - Specifies the list to modify
  383. DataToAppend - Specifies a block of data to be copied
  384. SizeOfData - Specifies the number of bytes in DataToAppend
  385. Return Value:
  386. A pointer to the binary block if data was copied into the list, 1 if a list
  387. item was created but no data was set for the item, or NULL if an error
  388. occurred.
  389. --*/
  390. {
  391. return pGrowListAdd (GrowList, INSERT_LAST, DataToAppend, SizeOfData, 2);
  392. }
  393. UINT
  394. CountInstancesOfSubStringW (
  395. IN PCWSTR SourceString,
  396. IN PCWSTR SearchString,
  397. IN UINT SearchChars
  398. )
  399. {
  400. UINT Count;
  401. UINT SourceChars;
  402. PCWSTR End;
  403. Count = 0;
  404. SourceChars = lstrlenW (SourceString);
  405. End = SourceString + SourceChars - SearchChars;
  406. if (!SearchChars) {
  407. return 0;
  408. }
  409. while (SourceString <= End) {
  410. if (!_wcsnicmp (SourceString, SearchString, SearchChars)) {
  411. Count++;
  412. SourceString += SearchChars;
  413. } else {
  414. SourceString++;
  415. }
  416. }
  417. return Count;
  418. }
  419. PCWSTR
  420. StringSearchAndReplaceW (
  421. IN PCWSTR SourceString,
  422. IN PCWSTR SearchString,
  423. IN PCWSTR ReplaceString
  424. )
  425. {
  426. PWSTR NewString;
  427. PBYTE p;
  428. PBYTE Dest;
  429. UINT Count;
  430. UINT Size;
  431. UINT SearchBytes;
  432. UINT ReplaceBytes;
  433. UINT SearchChars;
  434. //
  435. // Count occurances within the string
  436. //
  437. SearchBytes = ByteCountW (SearchString);
  438. SearchChars = SearchBytes / sizeof (WCHAR);
  439. ReplaceBytes = ByteCountW (ReplaceString);
  440. Count = CountInstancesOfSubStringW (
  441. SourceString,
  442. SearchString,
  443. SearchChars
  444. );
  445. if (!Count) {
  446. return NULL;
  447. }
  448. Size = SizeOfStringW (SourceString) -
  449. Count * SearchBytes +
  450. Count * ReplaceBytes;
  451. NewString = (PWSTR) MemAlloc (Size);
  452. if (!NewString) {
  453. return NULL;
  454. }
  455. p = (PBYTE) SourceString;
  456. Dest = (PBYTE) NewString;
  457. while (*((PWSTR) p)) {
  458. if (!_wcsnicmp ((PWSTR) p, SearchString, SearchChars)) {
  459. CopyMemory (Dest, ReplaceString, ReplaceBytes);
  460. Dest += ReplaceBytes;
  461. p += SearchBytes;
  462. } else {
  463. *((PWSTR) Dest) = *((PWSTR) p);
  464. p += sizeof (WCHAR);
  465. Dest += sizeof (WCHAR);
  466. }
  467. }
  468. *((PWSTR) Dest) = 0;
  469. return NewString;
  470. }
  471. VOID
  472. pMoveKeyTree (
  473. IN PCWSTR SourceKey,
  474. IN PCWSTR DestKey
  475. )
  476. {
  477. REGTREE_ENUM e;
  478. WCHAR DestSubKey[MAX_PATH];
  479. PWSTR p;
  480. GROWLIST List = GROWLIST_INIT;
  481. UINT Count;
  482. UINT u;
  483. PCWSTR Item;
  484. DWORD Len;
  485. lstrcpyW (DestSubKey, DestKey);
  486. p = AppendWackW (DestSubKey);
  487. if (EnumFirstRegKeyInTree (&e, SourceKey)) {
  488. do {
  489. lstrcpyW (p, (PCWSTR) ((PBYTE) e.FullKeyName + e.EnumBaseBytes));
  490. pMoveKey (e.FullKeyName, DestSubKey);
  491. GrowListAppendString (&List, e.FullKeyName);
  492. } while (EnumNextRegKeyInTree (&e));
  493. }
  494. Count = GrowListGetSize (&List);
  495. u = Count;
  496. while (u > 0) {
  497. u--;
  498. Item = GrowListGetString (&List, u);
  499. ConvertRootStringToKey (Item, &Len);
  500. RegDeleteKey (ConvertRootStringToKey (Item, NULL), Item + Len);
  501. }
  502. FreeGrowList (&List);
  503. }
  504. VOID
  505. pUpdateKeyNames (
  506. IN PCWSTR Search,
  507. IN PCWSTR Replace,
  508. IN PCWSTR RootKey
  509. )
  510. {
  511. REGTREE_ENUM e;
  512. GROWLIST List = GROWLIST_INIT;
  513. UINT Count;
  514. UINT u;
  515. PCWSTR OldKey;
  516. PCWSTR NewKey;
  517. if (EnumFirstRegKeyInTree (&e, RootKey)) {
  518. do {
  519. if (_wcsistr (e.CurrentKey->KeyName, Search)) {
  520. GrowListAppendString (&List, e.FullKeyName);
  521. }
  522. } while (EnumNextRegKeyInTree (&e));
  523. }
  524. Count = GrowListGetSize (&List);
  525. u = Count;
  526. while (u > 0) {
  527. u--;
  528. OldKey = GrowListGetString (&List, u);
  529. NewKey = StringSearchAndReplaceW (
  530. OldKey,
  531. Search,
  532. Replace
  533. );
  534. pMoveKeyTree (OldKey, NewKey);
  535. }
  536. FreeGrowList (&List);
  537. }
  538. VOID
  539. pUpdateValueNames (
  540. IN PCWSTR Search,
  541. IN PCWSTR Replace,
  542. IN PCWSTR RootKey
  543. )
  544. {
  545. REGTREE_ENUM e;
  546. REGVALUE_ENUM ev;
  547. GROWLIST List = GROWLIST_INIT;
  548. HKEY Key;
  549. UINT Count;
  550. UINT u;
  551. PBYTE Data;
  552. DWORD Type;
  553. DWORD Size;
  554. PCWSTR ValueName;
  555. PCWSTR NewValueName;
  556. BOOL b;
  557. LONG rc;
  558. if (EnumFirstRegKeyInTree (&e, RootKey)) {
  559. do {
  560. Key = OpenRegKeyStr (e.FullKeyName);
  561. if (Key) {
  562. if (EnumFirstRegValue (&ev, Key)) {
  563. do {
  564. if (_wcsistr (ev.ValueName, Search)) {
  565. GrowListAppendString (&List, ev.ValueName);
  566. }
  567. } while (EnumNextRegValue (&ev));
  568. Count = GrowListGetSize (&List);
  569. u = Count;
  570. while (u > 0) {
  571. u--;
  572. ValueName = GrowListGetString (&List, u);
  573. b = FALSE;
  574. if (GetRegValueTypeAndSize (Key, ValueName, &Type, &Size)) {
  575. Data = GetRegValueData (Key, ValueName);
  576. if (Data) {
  577. NewValueName = StringSearchAndReplaceW (
  578. ValueName,
  579. Search,
  580. Replace
  581. );
  582. rc = RegSetValueEx (Key, NewValueName, 0, Type, Data, Size);
  583. if (rc == ERROR_SUCCESS) {
  584. if (lstrcmpiW (ValueName, NewValueName)) {
  585. rc = RegDeleteValue (Key, ValueName);
  586. }
  587. }
  588. MemFree (Data);
  589. MemFree ((PVOID) NewValueName);
  590. SetLastError (rc);
  591. b = (rc == ERROR_SUCCESS);
  592. }
  593. }
  594. }
  595. }
  596. FreeGrowList (&List);
  597. CloseRegKey (Key);
  598. }
  599. } while (EnumNextRegKeyInTree (&e));
  600. }
  601. }
  602. VOID
  603. pUpdateValueData (
  604. IN PCWSTR Search,
  605. IN PCWSTR Replace,
  606. IN PCWSTR RootKey
  607. )
  608. {
  609. REGTREE_ENUM e;
  610. REGVALUE_ENUM ev;
  611. HKEY Key;
  612. PCWSTR Data;
  613. PCWSTR NewData;
  614. LONG rc;
  615. if (EnumFirstRegKeyInTree (&e, RootKey)) {
  616. do {
  617. Key = OpenRegKeyStr (e.FullKeyName);
  618. if (Key) {
  619. if (EnumFirstRegValue (&ev, Key)) {
  620. do {
  621. Data = GetRegValueString (Key, ev.ValueName);
  622. if (Data) {
  623. if (_wcsistr (Data, Search)) {
  624. NewData = StringSearchAndReplaceW (Data, Search, Replace);
  625. rc = RegSetValueEx (Key, ev.ValueName, 0, ev.Type, (PBYTE) NewData, SizeOfStringW (NewData));
  626. MemFree ((PVOID) NewData);
  627. }
  628. MemFree ((PVOID) Data);
  629. }
  630. } while (EnumNextRegValue (&ev));
  631. }
  632. CloseRegKey (Key);
  633. }
  634. } while (EnumNextRegKeyInTree (&e));
  635. }
  636. }