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.

452 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. tree.c
  5. Abstract:
  6. Implements routines that do operations on entire trees
  7. Author:
  8. Jim Schmidt (jimschm) 08-Mar-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. //
  14. // Includes
  15. //
  16. // None
  17. #define DBG_TREE "Tree"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. // None
  26. //
  27. // Macros
  28. //
  29. // None
  30. //
  31. // Types
  32. //
  33. // None
  34. //
  35. // Globals
  36. //
  37. // None
  38. //
  39. // Macro expansion list
  40. //
  41. // None
  42. //
  43. // Private function prototypes
  44. //
  45. // None
  46. //
  47. // Macro expansion definition
  48. //
  49. // None
  50. //
  51. // Code
  52. //
  53. BOOL
  54. RgRemoveAllValuesInKeyA (
  55. IN PCSTR KeyToRemove
  56. )
  57. {
  58. REGTREE_ENUMA e;
  59. PCSTR pattern;
  60. BOOL result = TRUE;
  61. HKEY deleteHandle;
  62. REGSAM prevMode;
  63. LONG rc;
  64. pattern = ObsBuildEncodedObjectStringExA (KeyToRemove, "*", FALSE);
  65. if (EnumFirstRegObjectInTreeExA (
  66. &e,
  67. pattern,
  68. FALSE, // no key names
  69. TRUE, // ignored in this case
  70. TRUE, // values first
  71. TRUE, // depth first
  72. REGENUM_ALL_SUBLEVELS,
  73. TRUE, // use exclusions
  74. FALSE, // ReadValueData
  75. NULL
  76. )) {
  77. do {
  78. MYASSERT (!(e.Attributes & REG_ATTRIBUTE_KEY));
  79. prevMode = SetRegOpenAccessMode (KEY_ALL_ACCESS);
  80. deleteHandle = OpenRegKeyStrA (e.Location);
  81. if (deleteHandle) {
  82. rc = RegDeleteValueA (deleteHandle, e.Name);
  83. CloseRegKey (deleteHandle);
  84. SetRegOpenAccessMode (prevMode);
  85. if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND) {
  86. SetLastError (rc);
  87. AbortRegObjectInTreeEnumA (&e);
  88. ObsFreeA (pattern);
  89. return FALSE;
  90. }
  91. } else {
  92. SetRegOpenAccessMode (prevMode);
  93. AbortRegObjectInTreeEnumA (&e);
  94. ObsFreeA (pattern);
  95. return FALSE;
  96. }
  97. } while (EnumNextRegObjectInTreeA (&e));
  98. }
  99. ObsFreeA (pattern);
  100. return result;
  101. }
  102. BOOL
  103. RgRemoveAllValuesInKeyW (
  104. IN PCWSTR KeyToRemove
  105. )
  106. {
  107. REGTREE_ENUMW e;
  108. PCWSTR pattern;
  109. BOOL result = TRUE;
  110. HKEY deleteHandle;
  111. REGSAM prevMode;
  112. LONG rc;
  113. pattern = ObsBuildEncodedObjectStringExW (KeyToRemove, L"*", FALSE);
  114. if (EnumFirstRegObjectInTreeExW (
  115. &e,
  116. pattern,
  117. FALSE, // no key names
  118. TRUE, // ignored in this case
  119. TRUE, // values first
  120. TRUE, // depth first
  121. REGENUM_ALL_SUBLEVELS,
  122. TRUE, // use exclusions
  123. FALSE, // ReadValueData
  124. NULL
  125. )) {
  126. do {
  127. MYASSERT (!(e.Attributes & REG_ATTRIBUTE_KEY));
  128. prevMode = SetRegOpenAccessMode (KEY_ALL_ACCESS);
  129. deleteHandle = OpenRegKeyStrW (e.Location);
  130. if (deleteHandle) {
  131. rc = RegDeleteValueW (deleteHandle, e.Name);
  132. CloseRegKey (deleteHandle);
  133. SetRegOpenAccessMode (prevMode);
  134. if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND) {
  135. SetLastError (rc);
  136. AbortRegObjectInTreeEnumW (&e);
  137. ObsFreeW (pattern);
  138. return FALSE;
  139. }
  140. } else {
  141. SetRegOpenAccessMode (prevMode);
  142. AbortRegObjectInTreeEnumW (&e);
  143. ObsFreeW (pattern);
  144. return FALSE;
  145. }
  146. } while (EnumNextRegObjectInTreeW (&e));
  147. }
  148. ObsFreeW (pattern);
  149. return result;
  150. }
  151. BOOL
  152. pDeleteKeyStrA (
  153. IN OUT PSTR *DeleteKey
  154. )
  155. {
  156. PSTR p;
  157. HKEY key;
  158. LONG rc;
  159. if (*DeleteKey == NULL) {
  160. return TRUE;
  161. }
  162. p = (PSTR) FindLastWackA (*DeleteKey);
  163. if (p) {
  164. *p = 0;
  165. p++;
  166. key = OpenRegKeyStrA (*DeleteKey);
  167. if (key) {
  168. rc = RegDeleteKeyA (key, p);
  169. CloseRegKey (key);
  170. } else {
  171. rc = GetLastError();
  172. }
  173. if (rc == ERROR_FILE_NOT_FOUND) {
  174. rc = ERROR_SUCCESS;
  175. }
  176. } else {
  177. rc = ERROR_SUCCESS;
  178. }
  179. FreeTextA (*DeleteKey);
  180. *DeleteKey = NULL;
  181. SetLastError (rc);
  182. return rc == ERROR_SUCCESS;
  183. }
  184. BOOL
  185. pDeleteKeyStrW (
  186. IN OUT PWSTR *DeleteKey
  187. )
  188. {
  189. PWSTR p;
  190. HKEY key;
  191. LONG rc;
  192. if (*DeleteKey == NULL) {
  193. return TRUE;
  194. }
  195. p = (PWSTR) FindLastWackW (*DeleteKey);
  196. if (p) {
  197. *p = 0;
  198. p++;
  199. key = OpenRegKeyStrW (*DeleteKey);
  200. if (key) {
  201. rc = RegDeleteKeyW (key, p);
  202. CloseRegKey (key);
  203. } else {
  204. rc = GetLastError();
  205. }
  206. if (rc == ERROR_FILE_NOT_FOUND) {
  207. rc = ERROR_SUCCESS;
  208. }
  209. } else {
  210. rc = ERROR_SUCCESS;
  211. }
  212. FreeTextW (*DeleteKey);
  213. *DeleteKey = NULL;
  214. SetLastError (rc);
  215. return rc == ERROR_SUCCESS;
  216. }
  217. BOOL
  218. RgRemoveKeyA (
  219. IN PCSTR KeyToRemove
  220. )
  221. {
  222. REGTREE_ENUMA e;
  223. PCSTR pattern;
  224. BOOL result = TRUE;
  225. PSTR deleteKey = NULL;
  226. PSTR encodedKey;
  227. encodedKey = AllocTextA (ByteCountA (KeyToRemove) * 2 + 2 * sizeof (CHAR));
  228. ObsEncodeStringA (encodedKey, KeyToRemove);
  229. StringCatA (encodedKey, "\\*");
  230. pattern = ObsBuildEncodedObjectStringExA (encodedKey, NULL, FALSE);
  231. FreeTextA (encodedKey);
  232. if (EnumFirstRegObjectInTreeExA (
  233. &e,
  234. pattern,
  235. TRUE, // key names
  236. FALSE, // containers last
  237. TRUE, // values first
  238. TRUE, // depth first
  239. REGENUM_ALL_SUBLEVELS,
  240. TRUE, // use exclusions
  241. FALSE, // ReadValueData
  242. NULL
  243. )) {
  244. do {
  245. if (!pDeleteKeyStrA (&deleteKey)) {
  246. result = FALSE;
  247. break;
  248. }
  249. MYASSERT (e.Attributes & REG_ATTRIBUTE_KEY);
  250. if (!RgRemoveAllValuesInKeyA (e.NativeFullName)) {
  251. result = FALSE;
  252. break;
  253. }
  254. //
  255. // The reg enum wrappers hold on to a key handle, which prevents
  256. // us from deleting the key now. We need to hold on to the key
  257. // name, then continue on to the next item. At that time, we can
  258. // delete the key.
  259. //
  260. deleteKey = DuplicateTextA (e.NativeFullName);
  261. } while (EnumNextRegObjectInTreeA (&e));
  262. }
  263. ObsFreeA (pattern);
  264. if (result) {
  265. result = pDeleteKeyStrA (&deleteKey);
  266. result = result && RgRemoveAllValuesInKeyA (KeyToRemove);
  267. if (result) {
  268. deleteKey = DuplicateTextA (KeyToRemove);
  269. result = pDeleteKeyStrA (&deleteKey);
  270. }
  271. } else {
  272. AbortRegObjectInTreeEnumA (&e);
  273. if (deleteKey) {
  274. FreeTextA (deleteKey);
  275. INVALID_POINTER (deleteKey);
  276. }
  277. }
  278. return result;
  279. }
  280. BOOL
  281. RgRemoveKeyW (
  282. IN PCWSTR KeyToRemove
  283. )
  284. {
  285. REGTREE_ENUMW e;
  286. PCWSTR pattern;
  287. BOOL result = TRUE;
  288. PWSTR deleteKey = NULL;
  289. PWSTR encodedKey;
  290. encodedKey = AllocTextW (ByteCountW (KeyToRemove) * 2 + 2 * sizeof (WCHAR));
  291. ObsEncodeStringW (encodedKey, KeyToRemove);
  292. StringCatW (encodedKey, L"\\*");
  293. pattern = ObsBuildEncodedObjectStringExW (encodedKey, NULL, FALSE);
  294. FreeTextW (encodedKey);
  295. if (EnumFirstRegObjectInTreeExW (
  296. &e,
  297. pattern,
  298. TRUE, // key names
  299. FALSE, // containers last
  300. TRUE, // values first
  301. TRUE, // depth first
  302. REGENUM_ALL_SUBLEVELS,
  303. TRUE, // use exclusions
  304. FALSE, // ReadValueData
  305. NULL
  306. )) {
  307. do {
  308. if (!pDeleteKeyStrW (&deleteKey)) {
  309. result = FALSE;
  310. break;
  311. }
  312. MYASSERT (e.Attributes & REG_ATTRIBUTE_KEY);
  313. if (!RgRemoveAllValuesInKeyW (e.NativeFullName)) {
  314. result = FALSE;
  315. break;
  316. }
  317. //
  318. // The reg enum wrappers hold on to a key handle, which prevents
  319. // us from deleting the key now. We need to hold on to the key
  320. // name, then continue on to the next item. At that time, we can
  321. // delete the key.
  322. //
  323. deleteKey = DuplicateTextW (e.NativeFullName);
  324. } while (EnumNextRegObjectInTreeW (&e));
  325. }
  326. ObsFreeW (pattern);
  327. if (result) {
  328. result = pDeleteKeyStrW (&deleteKey);
  329. result = result && RgRemoveAllValuesInKeyW (KeyToRemove);
  330. if (result) {
  331. deleteKey = DuplicateTextW (KeyToRemove);
  332. result = pDeleteKeyStrW (&deleteKey);
  333. }
  334. } else {
  335. AbortRegObjectInTreeEnumW (&e);
  336. if (deleteKey) {
  337. FreeTextW (deleteKey);
  338. INVALID_POINTER (deleteKey);
  339. }
  340. }
  341. return result;
  342. }