summaryrefslogtreecommitdiff
path: root/source3/registry/reg_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/registry/reg_api.c')
-rw-r--r--source3/registry/reg_api.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/source3/registry/reg_api.c b/source3/registry/reg_api.c
index 4fbf54e753..e2bb56deea 100644
--- a/source3/registry/reg_api.c
+++ b/source3/registry/reg_api.c
@@ -677,3 +677,59 @@ WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
*pkey = key;
return WERR_OK;
}
+
+
+/*
+ * Utility function to delete a registry key with all its subkeys.
+ * Note that reg_deletekey returns ACCESS_DENIED when called on a
+ * key that has subkeys.
+ */
+WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
+ struct registry_key *parent,
+ const char *path)
+{
+ TALLOC_CTX *mem_ctx = NULL;
+ WERROR werr = WERR_OK;
+ struct registry_key *key;
+ uint32 idx = 0;
+ char *subkey_name = NULL;
+
+ mem_ctx = talloc_new(ctx);
+ if (mem_ctx == NULL) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ /* recurse through subkeys first */
+ werr = reg_openkey(mem_ctx, parent, path, REG_KEY_WRITE, &key);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ /* NOTE: we *must not* increment idx in this loop since
+ * the list of subkeys shrinks with each loop body.
+ * so this way, we repeatedly delete the *first* entry
+ * of a shrinking list. */
+ for (idx = 0;
+ W_ERROR_IS_OK(werr = reg_enumkey(mem_ctx, key, idx,
+ &subkey_name, NULL));
+ )
+ {
+ werr = reg_deletekey_recursive(mem_ctx, key, subkey_name);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ }
+ if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
+ DEBUG(1, ("reg_deletekey_recursive: Error enumerating "
+ "subkeys: %s\n", dos_errstr(werr)));
+ goto done;
+ }
+
+ /* now delete the actual key */
+ werr = reg_deletekey(parent, path);
+
+done:
+ TALLOC_FREE(mem_ctx);
+ return werr;
+}