registry: Implement recursive deletes for regf-backed registry.
authorAndrew Kroeger <andrew@sprocks.gotdns.com>
Sat, 16 Feb 2008 21:19:00 +0000 (15:19 -0600)
committerAndrew Kroeger <andrew@sprocks.gotdns.com>
Wed, 27 Feb 2008 01:27:14 +0000 (19:27 -0600)
When deleting a registry key that contains subkeys or values, Windows performs a
recursive deletion that removes any subkeys or values.  This update makes
deletes for an regf-backed registry consistent with Windows.

The regf-backed registry does not have transactional integrity when performing
multiple operations.  Therefore, if an error occurs during the recursive
deletion, the regf-backed registry may be left in an inconsistent state.
(This used to be commit b0321bad290d1a9399b4aba140a622e3af6d7575)

source4/lib/registry/regf.c

index 15b60745f05612dea2b5d9ebdd06b6d161743d03..6a35799a7e12200f4d761ca105e4308cde1c45ef 100644 (file)
@@ -1618,10 +1618,55 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name)
                return WERR_BADFILE;
        }
 
                return WERR_BADFILE;
        }
 
-       if (key->nk->subkeys_offset != -1 ||
-               key->nk->values_offset != -1) {
-               DEBUG(0, ("Key '%s' is not empty.\n", name));
-               return WERR_FILE_EXISTS;
+       if (key->nk->subkeys_offset != -1) {
+               char *sk_name;
+               struct hive_key *sk = (struct hive_key *)key;
+               int i = key->nk->num_subkeys;
+               while (i--) {
+                       /* Get subkey information. */
+                       error = regf_get_subkey_by_index(parent_nk, sk, 0,
+                                                        (const char **)&sk_name,
+                                                        NULL, NULL);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't retrieve subkey by index.\n"));
+                               return error;
+                       }
+
+                       /* Delete subkey. */
+                       error = regf_del_key(sk, sk_name);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't delete key '%s'.\n", sk_name));
+                               return error;
+                       }
+
+                       talloc_free(sk_name);
+               }
+       }
+
+       if (key->nk->values_offset != -1) {
+               char *val_name;
+               struct hive_key *sk = (struct hive_key *)key;
+               DATA_BLOB data;
+               int i = key->nk->num_values;
+               while (i--) {
+                       /* Get value information. */
+                       error = regf_get_value(parent_nk, sk, 0,
+                                              (const char **)&val_name,
+                                              NULL, &data);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't retrieve value by index.\n"));
+                               return error;
+                       }
+
+                       /* Delete value. */
+                       error = regf_del_value(sk, val_name);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't delete value '%s'.\n", val_name));
+                               return error;
+                       }
+
+                       talloc_free(val_name);
+               }
        }
 
        /* Delete it from the subkey list. */
        }
 
        /* Delete it from the subkey list. */