summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2004-12-14 20:49:18 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:07:26 -0500
commit1a340869c43f9ce741e8a4bd28ea01ec63301df5 (patch)
treecd005ea4f160b42c8c38b7a9112b87c93ee0ced3
parent75f02f9d4daf4a16b408ce145f841f11d4b0ca67 (diff)
downloadsamba-1a340869c43f9ce741e8a4bd28ea01ec63301df5.tar.gz
samba-1a340869c43f9ce741e8a4bd28ea01ec63301df5.tar.bz2
samba-1a340869c43f9ce741e8a4bd28ea01ec63301df5.zip
r4204: Arguments to reg_del_key more like the RPC for more efficient usage
Fix small bug in regpatch Fix segfault in regshell cmdline completion Implement set_value and del_value in ldb backend (This used to be commit 8e2aa58abeafa78afe7dafb9723f5f365e756527)
-rw-r--r--source4/include/registry.h4
-rw-r--r--source4/lib/registry/common/reg_interface.c155
-rw-r--r--source4/lib/registry/common/reg_util.c87
-rw-r--r--source4/lib/registry/reg_backend_dir.c11
-rw-r--r--source4/lib/registry/reg_backend_ldb.c62
-rw-r--r--source4/lib/registry/reg_backend_rpc.c18
-rw-r--r--source4/lib/registry/tools/regpatch.c16
-rw-r--r--source4/lib/registry/tools/regshell.c15
-rw-r--r--source4/rpc_server/winreg/rpc_winreg.c5
9 files changed, 175 insertions, 198 deletions
diff --git a/source4/include/registry.h b/source4/include/registry.h
index 5865636836..e2f8bc087a 100644
--- a/source4/include/registry.h
+++ b/source4/include/registry.h
@@ -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);
};
diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c
index 79bb0b765c..c729945a26 100644
--- a/source4/lib/registry/common/reg_interface.c
+++ b/source4/lib/registry/common/reg_interface.c
@@ -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) {
diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c
index 052ccc347b..1d1f770324 100644
--- a/source4/lib/registry/common/reg_util.c
+++ b/source4/lib/registry/common/reg_util.c
@@ -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;
+}
diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c
index 89f9280585..41a0da58c0 100644
--- a/source4/lib/registry/reg_backend_dir.c
+++ b/source4/lib/registry/reg_backend_dir.c
@@ -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)
diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c
index ec8a6d9de3..7a63f4a530 100644
--- a/source4/lib/registry/reg_backend_ldb.c
+++ b/source4/lib/registry/reg_backend_ldb.c
@@ -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)
diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c
index b14b67d609..224a061762 100644
--- a/source4/lib/registry/reg_backend_rpc.c
+++ b/source4/lib/registry/reg_backend_rpc.c
@@ -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);
diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c
index 18589a9285..600c1f60e7 100644
--- a/source4/lib/registry/tools/regpatch.c
+++ b/source4/lib/registry/tools/regpatch.c
@@ -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;
diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c
index 0a09708869..6de8b25c9c 100644
--- a/source4/lib/registry/tools/regshell.c
+++ b/source4/lib/registry/tools/regshell.c
@@ -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;
diff --git a/source4/rpc_server/winreg/rpc_winreg.c b/source4/rpc_server/winreg/rpc_winreg.c
index e8d4056b2a..b34ccfa4b9 100644
--- a/source4/rpc_server/winreg/rpc_winreg.c
+++ b/source4/rpc_server/winreg/rpc_winreg.c
@@ -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;