s3:registry: wrap deletekey_recursive in one big transaction.
[jra/samba/.git] / source3 / registry / reg_api.c
index 25cf101aaf5ff1e83580d6df545caaecc3e6d497..4dde493a491401733d6d570d6c4face7823c3a3c 100644 (file)
@@ -183,9 +183,9 @@ static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
        
        /* Look up the table of registry I/O operations */
 
-       if ( !(key->hook = reghook_cache_find( key->name )) ) {
-               DEBUG(0,("reg_open_onelevel: Failed to assign "
-                        "REGISTRY_HOOK to [%s]\n", key->name ));
+       if ( !(key->ops = reghook_cache_find( key->name )) ) {
+               DEBUG(0,("reg_open_onelevel: Failed to assign "
+                        "REGISTRY_OPS to [%s]\n", key->name ));
                result = WERR_BADFILE;
                goto done;
        }
@@ -436,7 +436,7 @@ WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
                return err;
        }
 
-       *secdescsize = ndr_size_security_descriptor(secdesc, 0);
+       *secdescsize = ndr_size_security_descriptor(secdesc, NULL, 0);
        TALLOC_FREE(mem_ctx);
 
        *last_changed_time = 0;
@@ -653,6 +653,19 @@ WERROR reg_setvalue(struct registry_key *key, const char *name,
        return WERR_OK;
 }
 
+static WERROR reg_value_exists(struct registry_key *key, const char *name)
+{
+       int i;
+
+       for (i=0; i<key->values->num_values; i++) {
+               if (strequal(key->values->values[i]->valuename, name)) {
+                       return WERR_OK;
+               }
+       }
+
+       return WERR_BADFILE;
+}
+
 WERROR reg_deletevalue(struct registry_key *key, const char *name)
 {
        WERROR err;
@@ -665,6 +678,11 @@ WERROR reg_deletevalue(struct registry_key *key, const char *name)
                return err;
        }
 
+       err = reg_value_exists(key, name);
+       if (!W_ERROR_IS_OK(err)) {
+               return err;
+       }
+
        regval_ctr_delvalue(key->values, name);
 
        if (!store_reg_values(key->key, key->values)) {
@@ -715,9 +733,9 @@ static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
 
        /* initialize the REGISTRY_KEY structure */
 
-       registry_key.hook = reghook_cache_find(topkeypath);
-       if (!registry_key.hook) {
-               DEBUG(0, ("reg_load_tree: Failed to assigned a REGISTRY_HOOK "
+       registry_key.ops = reghook_cache_find(topkeypath);
+       if (!registry_key.ops) {
+               DEBUG(0, ("reg_load_tree: Failed to assign  REGISTRY_OPS "
                          "to [%s]\n", topkeypath));
                return WERR_BADFILE;
        }
@@ -753,7 +771,11 @@ static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
 
        key->subkey_index = 0;
        while ((subkey = regfio_fetch_subkey( regfile, key ))) {
-               regsubkey_ctr_addkey(subkeys, subkey->keyname);
+               result = regsubkey_ctr_addkey(subkeys, subkey->keyname);
+               if (!W_ERROR_IS_OK(result)) {
+                       TALLOC_FREE(subkeys);
+                       return result;
+               }
        }
 
        /* write this key and values out */
@@ -880,8 +902,8 @@ static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
                return WERR_NOMEM;
        }
 
-       registry_key.hook = reghook_cache_find(registry_key.name);
-       if (registry_key.hook == NULL) {
+       registry_key.ops = reghook_cache_find(registry_key.name);
+       if (registry_key.ops == NULL) {
                return WERR_BADFILE;
        }
 
@@ -939,54 +961,6 @@ done:
        return result;
 }
 
-static const struct generic_mapping reg_generic_map =
-       { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
-
-static WERROR make_default_reg_sd(TALLOC_CTX *ctx, SEC_DESC **psd)
-{
-       DOM_SID adm_sid, owner_sid;
-       SEC_ACE ace[2];         /* at most 2 entries */
-       SEC_ACCESS mask;
-       SEC_ACL *psa = NULL;
-       size_t sd_size;
-
-       /* set the owner to BUILTIN\Administrator */
-
-       sid_copy(&owner_sid, &global_sid_Builtin);
-       sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
-       
-
-       /* basic access for Everyone */
-
-       init_sec_access(&mask, reg_generic_map.generic_execute
-                              | reg_generic_map.generic_read);
-       init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
-                    mask, 0);
-
-       /* add Full Access 'BUILTIN\Administrators' */
-
-       init_sec_access(&mask, reg_generic_map.generic_all);
-       sid_copy(&adm_sid, &global_sid_Builtin);
-       sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-       init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
-       /* create the security descriptor */
-
-       psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace);
-       if (psa == NULL) {
-               return WERR_NOMEM;
-       }
-
-       *psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
-                            SEC_DESC_SELF_RELATIVE, &owner_sid, NULL,
-                            NULL, psa, &sd_size);
-       if (*psd == NULL) {
-               return WERR_NOMEM;
-       }
-
-       return WERR_OK;
-}
-
 static WERROR backup_registry_key(REGISTRY_KEY *krecord, const char *fname)
 {
        REGF_FILE *regfile;
@@ -1143,7 +1117,7 @@ static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
        if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
                DEBUG(1, ("reg_deletekey_recursive_internal: "
                          "Error enumerating subkeys: %s\n",
-                         dos_errstr(werr)));
+                         win_errstr(werr)));
                goto done;
        }
 
@@ -1159,18 +1133,54 @@ done:
        return werr;
 }
 
+static WERROR reg_deletekey_recursive_trans(TALLOC_CTX *ctx,
+                                           struct registry_key *parent,
+                                           const char *path,
+                                           bool del_key)
+{
+       WERROR werr;
+
+       werr = regdb_transaction_start();
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, ("reg_deletekey_recursive_trans: "
+                         "error starting transaction: %s\n",
+                         win_errstr(werr)));
+               return werr;
+       }
+
+       werr = reg_deletekey_recursive_internal(ctx, parent, path, del_key);
+
+       if (!W_ERROR_IS_OK(werr)) {
+               werr = regdb_transaction_cancel();
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG(0, ("reg_deletekey_recursive_trans: "
+                                 "error cancelling transaction: %s\n",
+                                 win_errstr(werr)));
+               }
+       } else {
+               werr = regdb_transaction_commit();
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG(0, ("reg_deletekey_recursive_trans: "
+                                 "error committing transaction: %s\n",
+                                 win_errstr(werr)));
+               }
+       }
+
+       return werr;
+}
+
 WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
                               struct registry_key *parent,
                               const char *path)
 {
-       return reg_deletekey_recursive_internal(ctx, parent, path, true);
+       return reg_deletekey_recursive_trans(ctx, parent, path, true);
 }
 
 WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
                                   struct registry_key *parent,
                                   const char *path)
 {
-       return reg_deletekey_recursive_internal(ctx, parent, path, false);
+       return reg_deletekey_recursive_trans(ctx, parent, path, false);
 }
 
 #if 0