summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/lib/registry/local.c93
1 files changed, 53 insertions, 40 deletions
diff --git a/source4/lib/registry/local.c b/source4/lib/registry/local.c
index be48729f79..3078518539 100644
--- a/source4/lib/registry/local.c
+++ b/source4/lib/registry/local.c
@@ -166,58 +166,71 @@ static WERROR local_enum_key(TALLOC_CTX *mem_ctx,
}
static WERROR local_create_key(TALLOC_CTX *mem_ctx,
- struct registry_key *parent_key,
- const char *name,
+ struct registry_key *parent,
+ const char *path,
const char *key_class,
struct security_descriptor *security,
- struct registry_key **key)
+ struct registry_key **result)
{
- struct local_key *local_parent;
- struct hive_key *hivekey;
- const char **elements;
- unsigned int i;
- const char *last_part;
- char *trunc_name;
-
- last_part = strrchr(name, '\\');
- if (last_part == NULL) {
- last_part = name;
- local_parent = (struct local_key *)parent_key;
- } else {
- trunc_name = talloc_strndup(mem_ctx, name, last_part - name);
- W_ERROR_HAVE_NO_MEMORY(trunc_name);
- W_ERROR_NOT_OK_RETURN(reg_open_key(mem_ctx, parent_key,
- trunc_name,
- (struct registry_key **)&local_parent));
- talloc_free(trunc_name);
- last_part++;
- }
+ char *orig, *curbegin, *curend;
+ struct local_key *local_parent = talloc_get_type(parent,
+ struct local_key);
+ struct hive_key *curkey = local_parent->hive_key;
+ WERROR error;
+ const char **elements = NULL;
+ int el;
- W_ERROR_NOT_OK_RETURN(hive_key_add_name(mem_ctx, local_parent->hive_key,
- last_part, key_class, security,
- &hivekey));
+ orig = talloc_strdup(mem_ctx, path);
+ W_ERROR_HAVE_NO_MEMORY(orig);
+ curbegin = orig;
+ curend = strchr(orig, '\\');
if (local_parent->path.elements != NULL) {
- elements = talloc_array(hivekey, const char *,
- str_list_length(local_parent->path.elements)+2);
+ elements = talloc_array(mem_ctx, const char *,
+ str_list_length(local_parent->path.elements) + 1);
W_ERROR_HAVE_NO_MEMORY(elements);
- for (i = 0; local_parent->path.elements[i] != NULL; i++) {
- elements[i] = talloc_reference(elements,
- local_parent->path.elements[i]);
+ for (el = 0; local_parent->path.elements[el] != NULL; el++) {
+ elements[el] = talloc_reference(elements,
+ local_parent->path.elements[el]);
}
+ elements[el] = NULL;
} else {
- elements = talloc_array(hivekey, const char *, 2);
- W_ERROR_HAVE_NO_MEMORY(elements);
- i = 0;
+ elements = NULL;
+ el = 0;
}
- elements[i] = talloc_strdup(elements, name);
- W_ERROR_HAVE_NO_MEMORY(elements[i]);
- elements[i+1] = NULL;
+ while (curbegin != NULL && *curbegin) {
+ if (curend != NULL)
+ *curend = '\0';
+ elements = talloc_realloc(mem_ctx, elements, const char *, el+2);
+ W_ERROR_HAVE_NO_MEMORY(elements);
+ elements[el] = talloc_strdup(elements, curbegin);
+ W_ERROR_HAVE_NO_MEMORY(elements[el]);
+ el++;
+ elements[el] = NULL;
+ error = hive_get_key_by_name(mem_ctx, curkey,
+ curbegin, &curkey);
+ if (W_ERROR_EQUAL(error, WERR_BADFILE)) {
+ error = hive_key_add_name(mem_ctx, curkey, curbegin,
+ key_class, security,
+ &curkey);
+ }
+ if (!W_ERROR_IS_OK(error)) {
+ DEBUG(2, ("Open/Creation of key %s failed: %s\n",
+ curbegin, win_errstr(error)));
+ talloc_free(orig);
+ return error;
+ }
+ if (curend == NULL)
+ break;
+ curbegin = curend + 1;
+ curend = strchr(curbegin, '\\');
+ }
+ talloc_free(orig);
- *key = reg_import_hive_key(local_parent->global.context, hivekey,
- local_parent->path.predefined_key,
- elements);
+ *result = reg_import_hive_key(local_parent->global.context, curkey,
+ local_parent->path.predefined_key,
+ talloc_steal(curkey, elements));
return WERR_OK;
}