s3:registry: add db_context argument to regdb_delete_subkeylist()
[ira/wip.git] / source3 / registry / reg_backend_db.c
index 8d483063c46c36fcaf6abf71301045deddc5b3ac..69676b19e60e8ada1c046b35b9715802f6f4a8e4 100644 (file)
@@ -239,7 +239,7 @@ WERROR init_registry_data(void)
 {
        WERROR werr;
        TALLOC_CTX *frame = talloc_stackframe();
-       REGVAL_CTR *values;
+       struct regval_ctr *values;
        int i;
        UNISTR2 data;
 
@@ -254,7 +254,7 @@ WERROR init_registry_data(void)
        }
 
        for (i=0; builtin_registry_values[i].path != NULL; i++) {
-               values = TALLOC_ZERO_P(frame, REGVAL_CTR);
+               values = TALLOC_ZERO_P(frame, struct regval_ctr);
                if (values == NULL) {
                        werr = WERR_NOMEM;
                        goto done;
@@ -307,7 +307,7 @@ do_init:
 
        for (i=0; builtin_registry_values[i].path != NULL; i++) {
 
-               values = TALLOC_ZERO_P(frame, REGVAL_CTR);
+               values = TALLOC_ZERO_P(frame, struct regval_ctr);
                if (values == NULL) {
                        werr = WERR_NOMEM;
                        goto fail;
@@ -511,7 +511,8 @@ int regdb_get_seqnum(void)
 }
 
 
-static WERROR regdb_delete_key_with_prefix(const char *keyname,
+static WERROR regdb_delete_key_with_prefix(struct db_context *db,
+                                          const char *keyname,
                                           const char *prefix)
 {
        char *path;
@@ -537,7 +538,7 @@ static WERROR regdb_delete_key_with_prefix(const char *keyname,
                goto done;
        }
 
-       werr = ntstatus_to_werror(dbwrap_delete_bystring(regdb, path));
+       werr = ntstatus_to_werror(dbwrap_delete_bystring(db, path));
 
        /* treat "not" found" as ok */
        if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) {
@@ -550,19 +551,48 @@ done:
 }
 
 
-static WERROR regdb_delete_values(const char *keyname)
+static WERROR regdb_delete_values(struct db_context *db, const char *keyname)
 {
-       return regdb_delete_key_with_prefix(keyname, REG_VALUE_PREFIX);
+       return regdb_delete_key_with_prefix(db, keyname, REG_VALUE_PREFIX);
 }
 
-static WERROR regdb_delete_secdesc(const char *keyname)
+static WERROR regdb_delete_secdesc(struct db_context *db, const char *keyname)
 {
-       return regdb_delete_key_with_prefix(keyname, REG_SECDESC_PREFIX);
+       return regdb_delete_key_with_prefix(db, keyname, REG_SECDESC_PREFIX);
 }
 
-static WERROR regdb_delete_subkeylist(const char *keyname)
+static WERROR regdb_delete_subkeylist(struct db_context *db, const char *keyname)
 {
-       return regdb_delete_key_with_prefix(keyname, NULL);
+       return regdb_delete_key_with_prefix(db, keyname, NULL);
+}
+
+static WERROR regdb_delete_key_lists(const char *keyname)
+{
+       WERROR werr;
+
+       werr = regdb_delete_values(regdb, keyname);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
+                         REG_VALUE_PREFIX, keyname, win_errstr(werr)));
+               goto done;
+       }
+
+       werr = regdb_delete_secdesc(regdb, keyname);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
+                         REG_SECDESC_PREFIX, keyname, win_errstr(werr)));
+               goto done;
+       }
+
+       werr = regdb_delete_subkeylist(regdb, keyname);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " Deleting %s failed: %s\n",
+                         keyname, win_errstr(werr)));
+               goto done;
+       }
+
+done:
+       return werr;
 }
 
 /***********************************************************************
@@ -779,37 +809,9 @@ bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
                if (!path) {
                        goto cancel;
                }
-               path = normalize_reg_path(ctx, path);
-               if (!path) {
-                       goto cancel;
-               }
 
-               /* (a) Delete the value list for this key */
-
-               werr = regdb_delete_values(path);
-               if (!W_ERROR_IS_OK(werr)) {
-                       DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
-                                 REG_VALUE_PREFIX, path, win_errstr(werr)));
-                       goto cancel;
-               }
-
-               /* (b) Delete the secdesc for this key */
-
-               werr = regdb_delete_secdesc(path);
-               if (!W_ERROR_IS_OK(werr)) {
-                       DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
-                                 REG_SECDESC_PREFIX, path, win_errstr(werr)));
-                       goto cancel;
-               }
-
-               /* (c) Delete the list of subkeys of this key */
-
-               werr = regdb_delete_subkeylist(path);
-               if (!W_ERROR_IS_OK(werr)) {
-                       DEBUG(1, (__location__ " Deleting %s failed: %s\n",
-                                 path, win_errstr(werr)));
-                       goto cancel;
-               }
+               werr = regdb_delete_key_lists(path);
+               W_ERROR_NOT_OK_GOTO(werr, cancel);
 
                TALLOC_FREE(path);
        }
@@ -956,6 +958,73 @@ done:
        return werr;
 }
 
+static WERROR regdb_delete_subkey(const char *key, const char *subkey)
+{
+       WERROR werr, werr2;
+       struct regsubkey_ctr *subkeys;
+       char *path;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
+               werr = WERR_NOT_FOUND;
+               goto done;
+       }
+
+       path = talloc_asprintf(mem_ctx, "%s/%s", key, subkey);
+       if (path == NULL) {
+               werr = WERR_NOMEM;
+               goto done;
+       }
+
+       if (!regdb_key_exists(path)) {
+               werr = WERR_OK;
+               goto done;
+       }
+
+       werr = regdb_transaction_start();
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       werr = regdb_delete_key_lists(path);
+       W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+       werr = regsubkey_ctr_init(mem_ctx, &subkeys);
+       W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+       if (regdb_fetch_keys(key, subkeys) < 0) {
+               werr = WERR_REG_IO_FAILURE;
+               goto cancel;
+       }
+
+       werr = regsubkey_ctr_delkey(subkeys, subkey);
+       W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+       if (!regdb_store_keys_internal(key, subkeys)) {
+               DEBUG(0, (__location__ " failed to store new subkey_list for "
+                        "parent key %s\n", key));
+               werr = WERR_REG_IO_FAILURE;
+               goto cancel;
+       }
+
+       werr = regdb_transaction_commit();
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, (__location__ " failed to commit transaction: %s\n",
+                        win_errstr(werr)));
+       }
+
+       goto done;
+
+cancel:
+       werr2 = regdb_transaction_cancel();
+       if (!W_ERROR_IS_OK(werr2)) {
+               DEBUG(0, (__location__ " failed to cancel transaction: %s\n",
+                        win_errstr(werr2)));
+       }
+
+done:
+       talloc_free(mem_ctx);
+       return werr;
+}
+
 static TDB_DATA regdb_fetch_key_internal(TALLOC_CTX *mem_ctx, const char *key)
 {
        char *path = NULL;
@@ -1330,7 +1399,7 @@ done:
  Unpack a list of registry values frem the TDB
  ***************************************************************************/
 
-static int regdb_unpack_values(REGVAL_CTR *values, uint8 *buf, int buflen)
+static int regdb_unpack_values(struct regval_ctr *values, uint8 *buf, int buflen)
 {
        int             len = 0;
        uint32          type;
@@ -1375,11 +1444,11 @@ static int regdb_unpack_values(REGVAL_CTR *values, uint8 *buf, int buflen)
  Pack all values in all printer keys
  ***************************************************************************/
 
-static int regdb_pack_values(REGVAL_CTR *values, uint8 *buf, int buflen)
+static int regdb_pack_values(struct regval_ctr *values, uint8 *buf, int buflen)
 {
        int             len = 0;
        int             i;
-       REGISTRY_VALUE  *val;
+       struct regval_blob      *val;
        int             num_values;
 
        if ( !values )
@@ -1410,7 +1479,7 @@ static int regdb_pack_values(REGVAL_CTR *values, uint8 *buf, int buflen)
  released by the caller.
  ***********************************************************************/
 
-int regdb_fetch_values( const char* key, REGVAL_CTR *values )
+int regdb_fetch_values(const char* key, struct regval_ctr *values)
 {
        char *keystr = NULL;
        TALLOC_CTX *ctx = talloc_stackframe();
@@ -1445,7 +1514,7 @@ done:
        return ret;
 }
 
-bool regdb_store_values( const char *key, REGVAL_CTR *values )
+bool regdb_store_values(const char *key, struct regval_ctr *values)
 {
        TDB_DATA old_data, data;
        char *keystr = NULL;
@@ -1590,7 +1659,7 @@ bool regdb_subkeys_need_update(struct regsubkey_ctr *subkeys)
        return (regdb_get_seqnum() != regsubkey_ctr_get_seqnum(subkeys));
 }
 
-bool regdb_values_need_update(REGVAL_CTR *values)
+bool regdb_values_need_update(struct regval_ctr *values)
 {
        return (regdb_get_seqnum() != values->seqnum);
 }
@@ -1599,12 +1668,13 @@ bool regdb_values_need_update(REGVAL_CTR *values)
  * Table of function pointers for default access
  */
  
-REGISTRY_OPS regdb_ops = {
+struct registry_ops regdb_ops = {
        .fetch_subkeys = regdb_fetch_keys,
        .fetch_values = regdb_fetch_values,
        .store_subkeys = regdb_store_keys,
        .store_values = regdb_store_values,
        .create_subkey = regdb_create_subkey,
+       .delete_subkey = regdb_delete_subkey,
        .get_secdesc = regdb_get_secdesc,
        .set_secdesc = regdb_set_secdesc,
        .subkeys_need_update = regdb_subkeys_need_update,