r4204: Arguments to reg_del_key more like the RPC for more efficient usage
authorJelmer Vernooij <jelmer@samba.org>
Tue, 14 Dec 2004 20:49:18 +0000 (20:49 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:07:26 +0000 (13:07 -0500)
Fix small bug in regpatch
Fix segfault in regshell cmdline completion
Implement set_value and del_value in ldb backend

source/include/registry.h
source/lib/registry/common/reg_interface.c
source/lib/registry/common/reg_util.c
source/lib/registry/reg_backend_dir.c
source/lib/registry/reg_backend_ldb.c
source/lib/registry/reg_backend_rpc.c
source/lib/registry/tools/regpatch.c
source/lib/registry/tools/regshell.c
source/rpc_server/winreg/rpc_winreg.c

index 5865636836d6a15f556906020ef04330a58b3a41..e2f8bc087a3fc220b01a5485428b7784147f4003 100644 (file)
@@ -131,11 +131,11 @@ struct hive_operations {
 
        /* Key management */
        WERROR (*add_key)(TALLOC_CTX *, struct registry_key *, const char *name, uint32_t access_mask, SEC_DESC *, struct registry_key **);
-       WERROR (*del_key)(struct registry_key *);
+       WERROR (*del_key)(struct registry_key *, const char *name);
        WERROR (*flush_key) (struct registry_key *);
 
        /* Value management */
-       WERROR (*set_value)(struct registry_key *, const char *name, int type, void *data, int len); 
+       WERROR (*set_value)(struct registry_key *, const char *name, uint32 type, void *data, int len); 
        WERROR (*del_value)(struct registry_key *, const char *valname);
 };
 
index 79bb0b765cbf6cfced5a55ee4648d3a41f2fff5e..c729945a262cec1478ec4ae5ce871f40d9e64ce3 100644 (file)
@@ -192,28 +192,6 @@ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *lo
        return WERR_OK;
 }
 
-/* Open a key by name (including the predefined key name!) */
-WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result)
-{
-       struct registry_key *predef;
-       WERROR error;
-       int predeflength;
-       char *predefname;
-
-       if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name;
-       else predeflength = strlen(name);
-
-       predefname = strndup(name, predeflength);
-       error = reg_get_predefined_key_by_name(handle, predefname, &predef);
-       SAFE_FREE(predefname);
-
-       if(!W_ERROR_IS_OK(error)) {
-               return error;
-       }
-
-       return reg_open_key(mem_ctx, predef, name, result);
-}
-
 /* Open a key 
  * First tries to use the open_key function from the backend
  * then falls back to get_subkey_by_name and later get_subkey_by_index 
@@ -409,123 +387,21 @@ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key,
        return WERR_OK;
 }
 
-WERROR reg_key_del(struct registry_key *key)
+WERROR reg_key_del(struct registry_key *parent, const char *name)
 {
        WERROR error;
-       if(!key) return WERR_INVALID_PARAM;
+       if(!parent) return WERR_INVALID_PARAM;
        
        
-       if(!key->hive->functions->del_key)
+       if(!parent->hive->functions->del_key)
                return WERR_NOT_SUPPORTED;
        
-       error = key->hive->functions->del_key(key);
+       error = parent->hive->functions->del_key(parent, name);
        if(!W_ERROR_IS_OK(error)) return error;
 
        return WERR_OK;
 }
 
-WERROR reg_key_del_recursive(struct registry_key *key)
-{
-       WERROR error = WERR_OK;
-       int i;
-
-       TALLOC_CTX *mem_ctx = talloc_init("del_recursive");
-       
-       /* Delete all values for specified key */
-       for(i = 0; W_ERROR_IS_OK(error); i++) {
-               struct registry_value *val;
-               error = reg_key_get_value_by_index(mem_ctx, key, i, &val);
-               if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) 
-               {
-                       talloc_destroy(mem_ctx);                        
-                       return error;
-               }
-
-               if(W_ERROR_IS_OK(error)) {
-                       error = reg_del_value(key, val->name);
-                       if(!W_ERROR_IS_OK(error)) {
-                               talloc_destroy(mem_ctx);
-                               return error;
-                       }
-               }
-       }
-
-       error = WERR_OK;
-
-       /* Delete all keys below this one */
-       for(i = 0; W_ERROR_IS_OK(error); i++) {
-               struct registry_key *subkey;
-
-               error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
-               if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; }
-
-               error = reg_key_del_recursive(subkey);
-               if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; }
-       }
-
-       talloc_destroy(mem_ctx);
-       return reg_key_del(key);
-}
-
-WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name)
-{
-       struct registry_key *hive;
-       WERROR error;
-       int hivelength;
-       char *hivename;
-
-       if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
-       else hivelength = strlen(name);
-
-       hivename = strndup(name, hivelength);
-       error = reg_get_predefined_key_by_name(handle, hivename, &hive);
-       SAFE_FREE(hivename);
-
-       if(!W_ERROR_IS_OK(error)) return error;
-
-       return reg_key_add_name_recursive(hive, name);
-}
-
-WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path)
-{
-       struct registry_key *cur, *prevcur = parent;
-       WERROR error = WERR_OK;
-       char *dups, *begin, *end;
-       TALLOC_CTX *mem_ctx = talloc_init("add_recursive");
-
-       begin = dups = strdup(path);
-
-       while(1) { 
-               end = strchr(begin, '\\');
-               if(end) *end = '\0';
-               
-               error = reg_key_get_subkey_by_name(mem_ctx, prevcur, begin, &cur);
-
-               /* Key is not there, add it */
-               if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
-                       error = reg_key_add_name(mem_ctx, prevcur, begin, 0, NULL, &cur);
-                       if(!W_ERROR_IS_OK(error)) break;
-               }
-
-               if(!W_ERROR_IS_OK(error)) {
-                       if(end) *end = '\\';
-                       break;
-               }
-               
-               if(!end) { 
-                       error = WERR_OK; 
-                       break; 
-               }
-
-               *end = '\\';
-               begin = end+1;
-               prevcur = cur;
-       }
-       SAFE_FREE(dups);
-       talloc_destroy(mem_ctx);
-       return error;
-}
-
 WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **newkey)
 {
        WERROR error;
@@ -547,7 +423,7 @@ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const
        return WERR_OK;
 }
 
-WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len)
+WERROR reg_val_set(struct registry_key *key, const char *value, uint32 type, void *data, int len)
 {
        /* A 'real' set function has preference */
        if (key->hive->functions->set_value) 
@@ -577,27 +453,6 @@ WERROR reg_save (struct registry_context *ctx, const char *location)
        return WERR_NOT_SUPPORTED;
 }
 
-WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent)
-{
-       char *parent_name;
-       char *last;
-       struct registry_key *root = NULL;
-       WERROR error;
-
-       parent_name = strdup(key->path);
-       last = strrchr(parent_name, '\\');
-
-       if(!last) {
-               SAFE_FREE(parent_name);
-               return WERR_FOOBAR;
-       }
-       *last = '\0';
-
-       error = reg_open_key(mem_ctx, root, parent_name, parent);
-       SAFE_FREE(parent_name);
-       return error;
-}
-
 WERROR reg_key_flush(struct registry_key *key)
 {
        if (!key) {
index 052ccc347be46a576cff3470d1c8b1b07d2702e2..1d1f7703245d38fcd4ec8530cc3b9f96b5351bb2 100644 (file)
@@ -150,3 +150,90 @@ char *reg_path_unix2win(char *path)
        }
        return path;
 }
+
+/* Open a key by name (including the predefined key name!) */
+WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result)
+{
+       struct registry_key *predef;
+       WERROR error;
+       int predeflength;
+       char *predefname;
+
+       if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name;
+       else predeflength = strlen(name);
+
+       predefname = strndup(name, predeflength);
+       error = reg_get_predefined_key_by_name(handle, predefname, &predef);
+       SAFE_FREE(predefname);
+
+       if(!W_ERROR_IS_OK(error)) {
+               return error;
+       }
+
+       if (strchr(name, '\\')) {
+               return reg_open_key(mem_ctx, predef, strchr(name, '\\')+1, result);
+       } else {
+               *result = predef;
+               return WERR_OK;
+       }
+}
+
+static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, struct registry_key **parent, const char **name)
+{
+       char *parent_name;
+       WERROR error;
+       
+       if (strchr(path, '\\') == NULL) {
+               return WERR_FOOBAR;
+       }
+       
+       parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-1-path);
+
+       error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent);
+       if (!W_ERROR_IS_OK(error)) {
+               return error;
+       }
+       
+       *name = talloc_strdup(mem_ctx, strchr(path, '\\')+1);
+
+       return WERR_OK;
+}
+
+WERROR reg_key_del_abs(struct registry_context *ctx, const char *path)
+{
+       struct registry_key *parent;
+       const char *n;
+       TALLOC_CTX *mem_ctx = talloc_init("reg_key_del_abs");
+       WERROR error;
+       
+       if (!strchr(path, '\\')) {
+               return WERR_FOOBAR;
+       }
+       
+       error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
+       if (W_ERROR_IS_OK(error)) {
+               error = reg_key_del(parent, n);
+       }
+
+       talloc_destroy(mem_ctx);
+
+       return error;
+}
+
+WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32 access_mask, SEC_DESC *sec_desc, struct registry_key **result)
+{
+       struct registry_key *parent;
+       const char *n;
+       WERROR error;
+       
+       if (!strchr(path, '\\')) {
+               return WERR_FOOBAR;
+       }
+       
+       error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
+       if (W_ERROR_IS_OK(error)) {
+               error = reg_key_add_name(mem_ctx, parent, n, access_mask, sec_desc, result);
+       }
+
+       return error;
+}
index 89f92805854210f91a5560b1e0bcf2ac82101196..41a0da58c017bcc836548cd36075b70ce926f143 100644 (file)
@@ -34,9 +34,16 @@ static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent,
        return WERR_INVALID_PARAM;
 }
 
-static WERROR reg_dir_del_key(struct registry_key *k)
+static WERROR reg_dir_del_key(struct registry_key *k, const char *name)
 {
-       return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE;
+       char *child = talloc_asprintf(NULL, "%s/%s", (char *)k->backend_data, name);
+       WERROR ret;
+
+       if (rmdir(child) == 0) ret = WERR_OK; else ret = WERR_GENERAL_FAILURE;
+
+       talloc_destroy(child);
+
+       return ret;
 }
 
 static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, struct registry_key **subkey)
index ec8a6d9de3ae7ba0fb541eeb655252042c724c08..7a63f4a5304b3f80835a0344f2d815d7e952a9e6 100644 (file)
@@ -235,12 +235,15 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con
        return WERR_OK;
 }
 
-static WERROR ldb_del_key (struct registry_key *key)
+static WERROR ldb_del_key (struct registry_key *key, const char *child)
 {
        int ret;
        struct ldb_key_data *kd = key->backend_data;
+       char *childdn = talloc_asprintf(NULL, "key=%s,%s", child, kd->dn);
 
-       ret = ldb_delete(key->hive->backend_data, kd->dn);
+       ret = ldb_delete(key->hive->backend_data, childdn);
+
+       talloc_destroy(childdn);
 
        if (ret < 0) {
                DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data)));
@@ -250,6 +253,59 @@ static WERROR ldb_del_key (struct registry_key *key)
        return WERR_OK;
 }
 
+static WERROR ldb_del_value (struct registry_key *key, const char *child)
+{
+       int ret;
+       struct ldb_key_data *kd = key->backend_data;
+       char *childdn = talloc_asprintf(NULL, "value=%s,%s", child, kd->dn);
+
+       ret = ldb_delete(key->hive->backend_data, childdn);
+
+       talloc_destroy(childdn);
+
+       if (ret < 0) {
+               DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(key->hive->backend_data)));
+               return WERR_FOOBAR;
+       }
+
+       return WERR_OK;
+}
+
+static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32 type, void *data, int len)
+{
+       struct ldb_context *ctx = parent->hive->backend_data;
+       struct ldb_message msg;
+       struct ldb_val val;
+       int ret;
+       char *type_s;
+       TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
+
+       ZERO_STRUCT(msg);
+
+       msg.dn = reg_path_to_ldb(mem_ctx, parent->path, talloc_asprintf(mem_ctx, "value=%s,", name));
+
+       ldb_msg_add_string(ctx, &msg, "value", talloc_strdup(mem_ctx, name));
+       val.length = len;
+       val.data = data;
+       ldb_msg_add_value(ctx, &msg, "data", &val);
+
+       type_s = talloc_asprintf(mem_ctx, "%u", type);
+       ldb_msg_add_string(ctx, &msg, "type", type_s); 
+
+       ret = ldb_add(ctx, &msg);
+       if (ret < 0) {
+               ret = ldb_modify(ctx, &msg);
+               if (ret < 0) {
+                       DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data)));
+                       talloc_destroy(mem_ctx);
+                       return WERR_FOOBAR;
+               }
+       }
+       
+       talloc_destroy(mem_ctx);
+       return WERR_OK;
+}
+
 static struct hive_operations reg_backend_ldb = {
        .name = "ldb",
        .add_key = ldb_add_key,
@@ -258,6 +314,8 @@ static struct hive_operations reg_backend_ldb = {
        .open_key = ldb_open_key,
        .get_value_by_index = ldb_get_value_by_id,
        .get_subkey_by_index = ldb_get_subkey_by_id,
+       .set_value = ldb_set_value,
+       .del_value = ldb_del_value,
 };
 
 NTSTATUS registry_ldb_init(void)
index b14b67d609cef90474b83a7ca399a9a98993540f..224a061762dd57e93910db88dc28a4017cb87db2 100644 (file)
@@ -315,27 +315,17 @@ static WERROR rpc_query_key(struct registry_key *k)
        return r.out.result;
 }
 
-static WERROR rpc_del_key(struct registry_key *k)
+static WERROR rpc_del_key(struct registry_key *parent, const char *name)
 {
        NTSTATUS status;
-       struct rpc_key_data *mykeydata = k->backend_data;
+       struct rpc_key_data *mykeydata = parent->backend_data;
        struct winreg_DeleteKey r;
-       struct registry_key *parent;
-       WERROR error;
        TALLOC_CTX *mem_ctx = talloc_init("del_key");
        
-       error = reg_key_get_parent(mem_ctx, k, &parent);
-       if(!W_ERROR_IS_OK(error)) { 
-               talloc_destroy(mem_ctx); 
-               return error; 
-       }
-
-       mykeydata = parent->backend_data;
-
     r.in.handle = &mykeydata->pol;
-    init_winreg_String(&r.in.key, k->name);
+    init_winreg_String(&r.in.key, name);
  
-    status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r);
+    status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
 
        talloc_destroy(mem_ctx);
 
index 18589a9285e78a93bbc15b63012f9b67a01de233..600c1f60e7c2fc72e556d338de40733f278d29de 100644 (file)
@@ -686,13 +686,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd
 
                  /* If we found it, apply the other bits, else create such a key */
                  if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
-                         if(W_ERROR_IS_OK(reg_key_add_name_recursive_abs(r, cmd->key))) {
-                                 error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp);
-                                 if(!W_ERROR_IS_OK(error)) {
-                                       DEBUG(0, ("Error finding new key '%s' after it has been added\n", cmd->key));
-                                       continue;
-                                 }
-                         } else {
+                         if(!W_ERROR_IS_OK(reg_key_add_abs(mem_ctx, r, cmd->key, 0, NULL, &tmp))) {
                                        DEBUG(0, ("Error adding new key '%s'\n", cmd->key));
                                        continue;
                          }
@@ -730,13 +724,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd
                   * Find the key if it exists, and delete it ...
                   */
 
-                 error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp);
-                 if(!W_ERROR_IS_OK(error)) {
-                         DEBUG(0, ("Unable to open key '%s'\n", cmd->key));
-                         continue;
-                 }
-                 
-                 error = reg_key_del_recursive(tmp);
+                 error = reg_key_del_abs(r, cmd->key); 
                  if(!W_ERROR_IS_OK(error)) {
                          DEBUG(0, ("Unable to delete key '%s'\n", cmd->key));
                          continue;
index 0a097088699f87ec8728394a8c641470d112bdf1..6de8b25c9cf66e43454a7f4b0fe157706b66f5e1 100644 (file)
@@ -120,18 +120,12 @@ static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key *
 
 static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
 { 
-       struct registry_key *key;
        if(argc < 2) {
                fprintf(stderr, "Usage: rmkey <name>\n");
                return NULL;
        }
 
-       if(!W_ERROR_IS_OK(reg_open_key(mem_ctx, cur, argv[1], &key))) {
-               fprintf(stderr, "No such subkey '%s'\n", argv[1]);
-               return NULL;
-       }
-
-       if(!W_ERROR_IS_OK(reg_key_del(key))) {
+       if(!W_ERROR_IS_OK(reg_key_del(cur, argv[1]))) {
                fprintf(stderr, "Error deleting '%s'\n", argv[1]);
        } else {
                fprintf(stderr, "Successfully deleted '%s'\n", argv[1]);
@@ -259,9 +253,10 @@ static char **reg_complete_command(const char *text, int end)
        return matches;
 
 cleanup:
-       while (i >= 0) {
-               free(matches[i]);
-               i--;
+       count--;
+       while (count >= 0) {
+               free(matches[count]);
+               count--;
        }
        free(matches);
        return NULL;
index e8d4056b2a211f573ba7d577bf94fe170a6caec2..b34ccfa4b9e572a93f47eefa6473c6a8064339bd 100644 (file)
@@ -126,16 +126,13 @@ static WERROR winreg_DeleteKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
                       struct winreg_DeleteKey *r)
 {
        struct dcesrv_handle *h;
-       struct registry_key *key;
        WERROR result;
 
        h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, HTYPE_REGKEY);
        DCESRV_CHECK_HANDLE(h);
 
-       result = reg_open_key(mem_ctx, (struct registry_key *)h->data, r->in.key.name, &key);
-
        if (W_ERROR_IS_OK(result)) {
-               return reg_key_del(key);
+               return reg_key_del((struct registry_key *)h->data, r->in.key.name);
        }
 
        return result;