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.

366 lines
10 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. Santanuc 14-Feb-2002 Rewrite the RegistrySearchAndReplaceW to use
  13. standard registry api rather than going through
  14. reg & mem wrapper api's.
  15. --*/
  16. #include "pch.h"
  17. UINT
  18. CountInstancesOfSubStringW (
  19. IN PCWSTR SourceString,
  20. IN PCWSTR SearchString,
  21. IN UINT SearchChars
  22. )
  23. {
  24. UINT Count;
  25. UINT SourceChars;
  26. PCWSTR End;
  27. Count = 0;
  28. SourceChars = lstrlenW (SourceString);
  29. End = SourceString + SourceChars - SearchChars;
  30. if (!SearchChars) {
  31. return 0;
  32. }
  33. while (SourceString <= End) {
  34. if (!_wcsnicmp (SourceString, SearchString, SearchChars)) {
  35. Count++;
  36. SourceString += SearchChars;
  37. } else {
  38. SourceString++;
  39. }
  40. }
  41. return Count;
  42. }
  43. PWSTR
  44. StringSearchAndReplaceW (
  45. IN PCWSTR SourceString,
  46. IN PCWSTR SearchString,
  47. IN PCWSTR ReplaceString,
  48. IN DWORD* pcbNewString
  49. )
  50. {
  51. PWSTR NewString;
  52. PBYTE p;
  53. PBYTE Dest;
  54. UINT Count;
  55. UINT Size;
  56. UINT SearchBytes;
  57. UINT ReplaceBytes;
  58. UINT SearchChars;
  59. //
  60. // Count occurances within the string
  61. //
  62. if (pcbNewString) {
  63. *pcbNewString = 0;
  64. }
  65. SearchBytes = ByteCountW (SearchString);
  66. SearchChars = SearchBytes / sizeof (WCHAR);
  67. ReplaceBytes = ByteCountW (ReplaceString);
  68. Count = CountInstancesOfSubStringW (
  69. SourceString,
  70. SearchString,
  71. SearchChars
  72. );
  73. if (!Count) {
  74. return NULL;
  75. }
  76. Size = SizeOfStringW (SourceString) -
  77. Count * SearchBytes +
  78. Count * ReplaceBytes;
  79. NewString = (PWSTR) LocalAlloc(LPTR, Size);
  80. if (!NewString) {
  81. return NULL;
  82. }
  83. if (pcbNewString) {
  84. *pcbNewString = Size;
  85. }
  86. p = (PBYTE) SourceString;
  87. Dest = (PBYTE) NewString;
  88. while (*((PWSTR) p)) {
  89. if (!_wcsnicmp ((PWSTR) p, SearchString, SearchChars)) {
  90. CopyMemory (Dest, ReplaceString, ReplaceBytes);
  91. Dest += ReplaceBytes;
  92. p += SearchBytes;
  93. } else {
  94. *((PWSTR) Dest) = *((PWSTR) p);
  95. p += sizeof (WCHAR);
  96. Dest += sizeof (WCHAR);
  97. }
  98. }
  99. *((PWSTR) Dest) = 0;
  100. return NewString;
  101. }
  102. VOID
  103. RegistrySearchAndReplaceW (
  104. IN HKEY hRoot,
  105. IN PCWSTR szKey,
  106. IN PCWSTR Search,
  107. IN PCWSTR Replace)
  108. {
  109. HKEY hKey = NULL;
  110. HKEY hSubKey = NULL;
  111. DWORD dwType;
  112. DWORD cchMaxSubKeyName, cchNewMaxSubKeyName;
  113. DWORD cchMaxValueName, cchNewMaxValueName, cchLocalValueName;
  114. DWORD cbMaxValue, cbNewMaxValue, cbLocalValue, cbNewLocalValue;
  115. PWSTR szValueName = NULL, szNewValueName = NULL;
  116. PWSTR szSubKeyName = NULL, szNewSubKeyName = NULL;
  117. PBYTE pbValue = NULL, pbNewValue = NULL;
  118. LONG lResult;
  119. DWORD dwIndex;
  120. UNICODE_STRING Unicode_String;
  121. lResult = RegOpenKey(hRoot, szKey, &hKey);
  122. if (ERROR_SUCCESS != lResult) {
  123. DEBUGMSG ((DM_VERBOSE, "Fail to open key %s. Error %d", szKey, lResult));
  124. return;
  125. }
  126. lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
  127. &cchMaxSubKeyName, NULL, NULL,
  128. &cchMaxValueName, &cbMaxValue,
  129. NULL, NULL);
  130. if (ERROR_SUCCESS != lResult) {
  131. DEBUGMSG ((DM_VERBOSE, "Fail to query info for key %s. Error %d", szKey, lResult));
  132. goto Exit;
  133. }
  134. cchMaxSubKeyName++; // Include the terminating NULL
  135. cchMaxValueName++; // Include the terminating NULL
  136. //
  137. // Now starts enumerating the value and replace value names &
  138. // string data with "Replace" string in place of "Search" string
  139. //
  140. // Allocate enough memory
  141. szValueName = (LPWSTR) LocalAlloc(LPTR, cchMaxValueName * sizeof(WCHAR));
  142. if (!szValueName) {
  143. goto Exit;
  144. }
  145. pbValue = (LPBYTE) LocalAlloc(LPTR, cbMaxValue);
  146. if (!pbValue) {
  147. goto Exit;
  148. }
  149. dwIndex = 0;
  150. cchLocalValueName = cchMaxValueName;
  151. cbLocalValue = cbMaxValue;
  152. while (RegEnumValue(hKey, dwIndex++, szValueName,
  153. &cchLocalValueName, NULL,
  154. &dwType, pbValue, &cbLocalValue) == ERROR_SUCCESS) {
  155. if (dwType == REG_SZ || dwType == REG_MULTI_SZ || dwType == REG_EXPAND_SZ) {
  156. // Construct the new data value only if it's a string
  157. pbNewValue = (LPBYTE) StringSearchAndReplaceW((PCWSTR)pbValue, Search, Replace, &cbNewLocalValue);
  158. }
  159. // Now construct the new value name by replacing
  160. szNewValueName = StringSearchAndReplaceW(szValueName, Search, Replace, NULL);
  161. // If the value name or data has changed then write a new value
  162. if (szNewValueName || pbNewValue) {
  163. lResult = RegSetValueEx(hKey,
  164. szNewValueName ? szNewValueName : szValueName,
  165. 0,
  166. dwType,
  167. pbNewValue ? pbNewValue : pbValue,
  168. pbNewValue ? cbNewLocalValue : cbLocalValue);
  169. }
  170. if (pbNewValue) {
  171. LocalFree(pbNewValue);
  172. pbNewValue = NULL;
  173. }
  174. if (szNewValueName) {
  175. LocalFree(szNewValueName);
  176. szNewValueName = NULL;
  177. if (RegDeleteValue(hKey, szValueName) == ERROR_SUCCESS) {
  178. //
  179. // Start from begining, as enumeration index no longer valid
  180. // with insertion/deletion of value under the key
  181. //
  182. dwIndex = 0;
  183. lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
  184. NULL, NULL, NULL, &cchNewMaxValueName,
  185. &cbNewMaxValue, NULL, NULL);
  186. if (ERROR_SUCCESS != lResult) {
  187. DEBUGMSG ((DM_VERBOSE, "Fail to query info for key %s. Error %d", szKey, lResult));
  188. goto Exit;
  189. }
  190. cchNewMaxValueName++; // Include the terminating NULL
  191. if (cchNewMaxValueName > cchMaxValueName) {
  192. LocalFree(szValueName);
  193. szValueName = NULL;
  194. cchMaxValueName = cchNewMaxValueName;
  195. szValueName = (LPWSTR) LocalAlloc(LPTR, cchMaxValueName * sizeof(WCHAR));
  196. if (!szValueName) {
  197. goto Exit;
  198. }
  199. }
  200. if (cbNewMaxValue > cbMaxValue) {
  201. LocalFree(pbValue);
  202. pbValue = NULL;
  203. cbMaxValue = cbNewMaxValue;
  204. pbValue = (LPBYTE) LocalAlloc(LPTR, cbMaxValue);
  205. if (!pbValue) {
  206. goto Exit;
  207. }
  208. }
  209. }
  210. }
  211. cchLocalValueName = cchMaxValueName;
  212. cbLocalValue = cbMaxValue;
  213. }
  214. LocalFree(szValueName);
  215. szValueName = NULL;
  216. LocalFree(pbValue);
  217. pbValue = NULL;
  218. //
  219. // Now enumerate all the sub keys and replace the name as
  220. // required in a recursive fashion
  221. //
  222. szSubKeyName = (LPWSTR) LocalAlloc(LPTR, cchMaxSubKeyName * sizeof(WCHAR));
  223. if (!szSubKeyName) {
  224. goto Exit;
  225. }
  226. dwIndex = 0;
  227. while (RegEnumKey(hKey, dwIndex++,
  228. szSubKeyName, cchMaxSubKeyName) == ERROR_SUCCESS) {
  229. // recursively replace in the sub key tree
  230. RegistrySearchAndReplaceW(hKey, szSubKeyName, Search, Replace);
  231. szNewSubKeyName = StringSearchAndReplaceW(szSubKeyName, Search, Replace, NULL);
  232. if (szNewSubKeyName) {
  233. if (RegOpenKey(hKey, szSubKeyName, &hSubKey) == ERROR_SUCCESS) {
  234. Unicode_String.Length = ByteCountW(szNewSubKeyName);
  235. Unicode_String.MaximumLength = Unicode_String.Length + sizeof(WCHAR);
  236. Unicode_String.Buffer = szNewSubKeyName;
  237. lResult = NtRenameKey(hSubKey, &Unicode_String);
  238. if (lResult == ERROR_SUCCESS) {
  239. //
  240. // Start from begining, as enumeration index no longer valid
  241. // with rename of sub-keys under the key
  242. //
  243. dwIndex = 0;
  244. lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
  245. &cchNewMaxSubKeyName, NULL, NULL,
  246. NULL, NULL, NULL, NULL);
  247. if (ERROR_SUCCESS != lResult) {
  248. DEBUGMSG ((DM_VERBOSE, "Fail to query info for key %s. Error %d", szKey, lResult));
  249. goto Exit;
  250. }
  251. cchNewMaxSubKeyName++; // Include the terminating NULL
  252. if (cchNewMaxSubKeyName > cchMaxSubKeyName) {
  253. LocalFree(szSubKeyName);
  254. szSubKeyName = NULL;
  255. cchMaxSubKeyName = cchNewMaxSubKeyName;
  256. szSubKeyName = (LPWSTR) LocalAlloc(LPTR, cchMaxSubKeyName * sizeof(WCHAR));
  257. if (!szSubKeyName) {
  258. goto Exit;
  259. }
  260. }
  261. }
  262. RegCloseKey(hSubKey);
  263. }
  264. LocalFree(szNewSubKeyName);
  265. szNewSubKeyName = NULL;
  266. }
  267. }
  268. Exit:
  269. if (hKey) {
  270. RegCloseKey(hKey);
  271. }
  272. if (szValueName) {
  273. LocalFree(szValueName);
  274. }
  275. if (pbValue) {
  276. LocalFree(pbValue);
  277. }
  278. if (szSubKeyName) {
  279. LocalFree(szSubKeyName);
  280. }
  281. }