s3:registry: add db_context argument to regdb_delete_key_lists()
[ira/wip.git] / source3 / registry / reg_backend_db.c
index 689bd1038e3ea0d4a0c731932af7e08baae826fd..700db0140f794e28482568a2c1f7bb37269f3ca1 100644 (file)
@@ -103,7 +103,7 @@ static WERROR init_registry_key_internal(const char *add_path)
        char *remaining = NULL;
        char *keyname;
        char *subkeyname;
-       REGSUBKEY_CTR *subkeys;
+       struct regsubkey_ctr *subkeys;
        const char *p, *p2;
 
        DEBUG(6, ("init_registry_key: Adding [%s]\n", add_path));
@@ -167,9 +167,9 @@ static WERROR init_registry_key_internal(const char *add_path)
                 * since we are about to update the record.
                 * We just want any subkeys already present */
 
-               if (!(subkeys = TALLOC_ZERO_P(frame, REGSUBKEY_CTR))) {
+               werr = regsubkey_ctr_init(frame, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
                        DEBUG(0,("talloc() failure!\n"));
-                       werr = WERR_NOMEM;
                        goto fail;
                }
 
@@ -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;
@@ -482,6 +482,24 @@ int regdb_close( void )
        return 0;
 }
 
+WERROR regdb_transaction_start(void)
+{
+       return (regdb->transaction_start(regdb) == 0) ?
+               WERR_OK : WERR_REG_IO_FAILURE;
+}
+
+WERROR regdb_transaction_commit(void)
+{
+       return (regdb->transaction_commit(regdb) == 0) ?
+               WERR_OK : WERR_REG_IO_FAILURE;
+}
+
+WERROR regdb_transaction_cancel(void)
+{
+       return (regdb->transaction_cancel(regdb) == 0) ?
+               WERR_OK : WERR_REG_IO_FAILURE;
+}
+
 /***********************************************************************
  return the tdb sequence number of the registry tdb.
  this is an indicator for the content of the registry
@@ -492,13 +510,98 @@ int regdb_get_seqnum(void)
        return regdb->get_seqnum(regdb);
 }
 
+
+static WERROR regdb_delete_key_with_prefix(struct db_context *db,
+                                          const char *keyname,
+                                          const char *prefix)
+{
+       char *path;
+       WERROR werr = WERR_NOMEM;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (keyname == NULL) {
+               werr = WERR_INVALID_PARAM;
+               goto done;
+       }
+
+       if (prefix == NULL) {
+               path = discard_const_p(char, keyname);
+       } else {
+               path = talloc_asprintf(mem_ctx, "%s/%s", prefix, keyname);
+               if (path == NULL) {
+                       goto done;
+               }
+       }
+
+       path = normalize_reg_path(mem_ctx, path);
+       if (path == NULL) {
+               goto done;
+       }
+
+       werr = ntstatus_to_werror(dbwrap_delete_bystring(db, path));
+
+       /* treat "not" found" as ok */
+       if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) {
+               werr = WERR_OK;
+       }
+
+done:
+       talloc_free(mem_ctx);
+       return werr;
+}
+
+
+static WERROR regdb_delete_values(struct db_context *db, const char *keyname)
+{
+       return regdb_delete_key_with_prefix(db, keyname, REG_VALUE_PREFIX);
+}
+
+static WERROR regdb_delete_secdesc(struct db_context *db, const char *keyname)
+{
+       return regdb_delete_key_with_prefix(db, keyname, REG_SECDESC_PREFIX);
+}
+
+static WERROR regdb_delete_subkeylist(struct db_context *db, const char *keyname)
+{
+       return regdb_delete_key_with_prefix(db, keyname, NULL);
+}
+
+static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname)
+{
+       WERROR werr;
+
+       werr = regdb_delete_values(db, 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(db, 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(db, keyname);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " Deleting %s failed: %s\n",
+                         keyname, win_errstr(werr)));
+               goto done;
+       }
+
+done:
+       return werr;
+}
+
 /***********************************************************************
  Add subkey strings to the registry tdb under a defined key
  fmt is the same format as tdb_pack except this function only supports
  fstrings
  ***********************************************************************/
 
-static bool regdb_store_keys_internal(const char *key, REGSUBKEY_CTR *ctr)
+static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr)
 {
        TDB_DATA dbuf;
        uint8 *buffer = NULL;
@@ -599,14 +702,14 @@ done:
  do not currently exist
  ***********************************************************************/
 
-bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
+bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
 {
-       int num_subkeys, i;
+       int num_subkeys, old_num_subkeys, i;
        char *path = NULL;
-       REGSUBKEY_CTR *subkeys = NULL, *old_subkeys = NULL;
+       struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL;
        char *oldkeyname = NULL;
        TALLOC_CTX *ctx = talloc_stackframe();
-       NTSTATUS status;
+       WERROR werr;
 
        if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
                goto fail;
@@ -617,23 +720,28 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
         * changed
         */
 
-       if (!(old_subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR))) {
+       werr = regsubkey_ctr_init(ctx, &old_subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
                DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
                return false;
        }
 
        regdb_fetch_keys(key, old_subkeys);
 
-       if ((ctr->num_subkeys && old_subkeys->num_subkeys) &&
-           (ctr->num_subkeys == old_subkeys->num_subkeys)) {
-
-               for (i = 0; i<ctr->num_subkeys; i++) {
-                       if (strcmp(ctr->subkeys[i],
-                                  old_subkeys->subkeys[i]) != 0) {
+       num_subkeys = regsubkey_ctr_numkeys(ctr);
+       old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
+       if ((num_subkeys && old_num_subkeys) &&
+           (num_subkeys == old_num_subkeys)) {
+
+               for (i = 0; i < num_subkeys; i++) {
+                       if (strcmp(regsubkey_ctr_specific_key(ctr, i),
+                                  regsubkey_ctr_specific_key(old_subkeys, i))
+                           != 0)
+                       {
                                break;
                        }
                }
-               if (i == ctr->num_subkeys) {
+               if (i == num_subkeys) {
                        /*
                         * Nothing changed, no point to even start a tdb
                         * transaction
@@ -654,7 +762,8 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
         * Re-fetch the old keys inside the transaction
         */
 
-       if (!(old_subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR))) {
+       werr = regsubkey_ctr_init(ctx, &old_subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
                DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
                goto cancel;
        }
@@ -696,66 +805,14 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
                        continue;
                }
 
-               /* (a) Delete the value list for this key */
-
-               path = talloc_asprintf(ctx, "%s/%s/%s",
-                               REG_VALUE_PREFIX,
-                               key,
-                               oldkeyname );
-               if (!path) {
-                       goto cancel;
-               }
-               path = normalize_reg_path(ctx, path);
-               if (!path) {
-                       goto cancel;
-               }
-               /* Ignore errors here, we might have no values around */
-               dbwrap_delete_bystring(regdb, path);
-               TALLOC_FREE(path);
-
-               /* (b) Delete the secdesc for this key */
-
-               path = talloc_asprintf(ctx, "%s/%s/%s",
-                               REG_SECDESC_PREFIX,
-                               key,
-                               oldkeyname );
-               if (!path) {
-                       goto cancel;
-               }
-               path = normalize_reg_path(ctx, path);
+               path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname);
                if (!path) {
                        goto cancel;
                }
-               status = dbwrap_delete_bystring(regdb, path);
-               /* Don't fail if there are no values around. */
-               if (!NT_STATUS_IS_OK(status) &&
-                   !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND))
-               {
-                       DEBUG(1, ("Deleting %s failed: %s\n", path,
-                                 nt_errstr(status)));
-                       goto cancel;
-               }
-               TALLOC_FREE(path);
 
-               /* (c) Delete the list of subkeys of this key */
+               werr = regdb_delete_key_lists(regdb, path);
+               W_ERROR_NOT_OK_GOTO(werr, cancel);
 
-               path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname);
-               if (!path) {
-                       goto cancel;
-               }
-               path = normalize_reg_path(ctx, path);
-               if (!path) {
-                       goto cancel;
-               }
-               status = dbwrap_delete_bystring(regdb, path);
-               /* Don't fail if the subkey record was not found. */
-               if (!NT_STATUS_IS_OK(status) &&
-                   !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND))
-               {
-                       DEBUG(1, ("Deleting %s failed: %s\n", path,
-                                 nt_errstr(status)));
-                       goto cancel;
-               }
                TALLOC_FREE(path);
        }
 
@@ -774,7 +831,8 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
        num_subkeys = regsubkey_ctr_numkeys(ctr);
 
        if (num_subkeys == 0) {
-               if (!(subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR)) ) {
+               werr = regsubkey_ctr_init(ctx, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
                        DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
                        goto cancel;
                }
@@ -795,7 +853,8 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
                if (!path) {
                        goto cancel;
                }
-               if (!(subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR)) ) {
+               werr = regsubkey_ctr_init(ctx, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
                        DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
                        goto cancel;
                }
@@ -832,6 +891,139 @@ fail:
        return false;
 }
 
+static WERROR regdb_create_subkey(const char *key, const char *subkey)
+{
+       WERROR werr;
+       struct regsubkey_ctr *subkeys;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
+               werr = WERR_NOT_FOUND;
+               goto done;
+       }
+
+       werr = regsubkey_ctr_init(mem_ctx, &subkeys);
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       if (regdb_fetch_keys(key, subkeys) < 0) {
+               werr = WERR_REG_IO_FAILURE;
+               goto done;
+       }
+
+       if (regsubkey_ctr_key_exists(subkeys, subkey)) {
+               werr = WERR_OK;
+               goto done;
+       }
+
+       talloc_free(subkeys);
+
+       werr = regdb_transaction_start();
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       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_addkey(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:
+       werr = regdb_transaction_cancel();
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, (__location__ " failed to cancel transaction: %s\n",
+                        win_errstr(werr)));
+       }
+
+done:
+       talloc_free(mem_ctx);
+       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(regdb, 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)
 {
@@ -912,13 +1104,15 @@ static int cmp_keynames(const void *p1, const void *p2)
 static bool create_sorted_subkeys(const char *key, const char *sorted_keyname)
 {
        char **sorted_subkeys;
-       REGSUBKEY_CTR *ctr;
+       struct regsubkey_ctr *ctr;
        bool result = false;
        NTSTATUS status;
        char *buf;
        char *p;
        int i, res;
        size_t len;
+       int num_subkeys;
+       WERROR werr;
 
        if (regdb->transaction_start(regdb) != 0) {
                DEBUG(0, ("create_sorted_subkeys: transaction_start "
@@ -926,8 +1120,8 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname)
                return false;
        }
 
-       ctr = talloc(talloc_tos(), REGSUBKEY_CTR);
-       if (ctr == NULL) {
+       werr = regsubkey_ctr_init(talloc_tos(), &ctr);
+       if (!W_ERROR_IS_OK(werr)) {
                goto fail;
        }
 
@@ -936,33 +1130,34 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname)
                goto fail;
        }
 
-       sorted_subkeys = talloc_array(ctr, char *, ctr->num_subkeys);
+       num_subkeys = regsubkey_ctr_numkeys(ctr);
+       sorted_subkeys = talloc_array(ctr, char *, num_subkeys);
        if (sorted_subkeys == NULL) {
                goto fail;
        }
 
-       len = 4 + 4*ctr->num_subkeys;
+       len = 4 + 4*num_subkeys;
 
-       for (i = 0; i<ctr->num_subkeys; i++) {
+       for (i = 0; i < num_subkeys; i++) {
                sorted_subkeys[i] = talloc_strdup_upper(sorted_subkeys,
-                                                       ctr->subkeys[i]);
+                                       regsubkey_ctr_specific_key(ctr, i));
                if (sorted_subkeys[i] == NULL) {
                        goto fail;
                }
                len += strlen(sorted_subkeys[i])+1;
        }
 
-       qsort(sorted_subkeys, ctr->num_subkeys, sizeof(char *), cmp_keynames);
+       qsort(sorted_subkeys, num_subkeys, sizeof(char *), cmp_keynames);
 
        buf = talloc_array(ctr, char, len);
        if (buf == NULL) {
                goto fail;
        }
-       p = buf + 4 + 4*ctr->num_subkeys;
+       p = buf + 4 + 4*num_subkeys;
 
-       SIVAL(buf, 0, ctr->num_subkeys);
+       SIVAL(buf, 0, num_subkeys);
 
-       for (i=0; i<ctr->num_subkeys; i++) {
+       for (i=0; i < num_subkeys; i++) {
                ptrdiff_t offset = p - buf;
                SIVAL(buf, 4 + 4*i, offset);
                strlcpy(p, sorted_subkeys[i], len-offset);
@@ -1146,8 +1341,9 @@ done:
  released by the caller.
  ***********************************************************************/
 
-int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr)
+int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr)
 {
+       WERROR werr;
        uint32 num_items;
        uint8 *buf;
        uint32 buflen, len;
@@ -1163,7 +1359,10 @@ int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr)
                goto done;
        }
 
-       ctr->seqnum = regdb_get_seqnum();
+       werr = regsubkey_ctr_set_seqnum(ctr, regdb_get_seqnum());
+       if (!W_ERROR_IS_OK(werr)) {
+               goto done;
+       }
 
        value = regdb_fetch_key_internal(frame, key);
 
@@ -1178,35 +1377,12 @@ int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr)
        buflen = value.dsize;
        len = tdb_unpack( buf, buflen, "d", &num_items);
 
-       /*
-        * The following code breaks the abstraction that reg_objects.c sets
-        * up with regsubkey_ctr_addkey(). But if we use that with the current
-        * data structure of ctr->subkeys being an unsorted array, we end up
-        * with an O(n^2) algorithm for retrieving keys from the tdb
-        * file. This is pretty pointless, as we have to trust the data
-        * structure on disk not to have duplicates anyway. The alternative to
-        * breaking this abstraction would be to set up a more sophisticated
-        * data structure in REGSUBKEY_CTR.
-        *
-        * This makes "net conf list" for a registry with >1000 shares
-        * actually usable :-)
-        */
-
-       ctr->subkeys = talloc_array(ctr, char *, num_items);
-       if (ctr->subkeys == NULL) {
-               DEBUG(5, ("regdb_fetch_keys: could not allocate subkeys\n"));
-               goto done;
-       }
-       ctr->num_subkeys = num_items;
-
        for (i=0; i<num_items; i++) {
                len += tdb_unpack(buf+len, buflen-len, "f", subkeyname);
-               ctr->subkeys[i] = talloc_strdup(ctr->subkeys, subkeyname);
-               if (ctr->subkeys[i] == NULL) {
-                       DEBUG(5, ("regdb_fetch_keys: could not allocate "
-                                 "subkeyname\n"));
-                       TALLOC_FREE(ctr->subkeys);
-                       ctr->num_subkeys = 0;
+               werr = regsubkey_ctr_addkey(ctr, subkeyname);
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey "
+                                 "failed: %s\n", win_errstr(werr)));
                        goto done;
                }
        }
@@ -1223,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;
@@ -1268,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 )
@@ -1303,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();
@@ -1338,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;
@@ -1444,7 +1620,6 @@ static WERROR regdb_set_secdesc(const char *key,
 {
        TALLOC_CTX *mem_ctx = talloc_stackframe();
        char *tdbkey;
-       NTSTATUS status;
        WERROR err = WERR_NOMEM;
        TDB_DATA tdbdata;
 
@@ -1461,39 +1636,30 @@ static WERROR regdb_set_secdesc(const char *key,
 
        if (secdesc == NULL) {
                /* assuming a delete */
-               status = dbwrap_trans_delete_bystring(regdb, tdbkey);
-               if (NT_STATUS_IS_OK(status)) {
-                       err = WERR_OK;
-               } else {
-                       err = ntstatus_to_werror(status);
-               }
+               err = ntstatus_to_werror(dbwrap_trans_delete_bystring(regdb,
+                                                                     tdbkey));
                goto done;
        }
 
        err = ntstatus_to_werror(marshall_sec_desc(mem_ctx, secdesc,
                                                   &tdbdata.dptr,
                                                   &tdbdata.dsize));
-       if (!W_ERROR_IS_OK(err)) {
-               goto done;
-       }
+       W_ERROR_NOT_OK_GOTO_DONE(err);
 
-       status = dbwrap_trans_store_bystring(regdb, tdbkey, tdbdata, 0);
-       if (!NT_STATUS_IS_OK(status)) {
-               err = ntstatus_to_werror(status);
-               goto done;
-       }
+       err = ntstatus_to_werror(dbwrap_trans_store_bystring(regdb, tdbkey,
+                                                            tdbdata, 0));
 
  done:
        TALLOC_FREE(mem_ctx);
        return err;
 }
 
-bool regdb_subkeys_need_update(REGSUBKEY_CTR *subkeys)
+bool regdb_subkeys_need_update(struct regsubkey_ctr *subkeys)
 {
-       return (regdb_get_seqnum() != subkeys->seqnum);
+       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);
 }
@@ -1502,11 +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,