From 369a5d64e462e084e6c5fe4984d56da18b2c92d9 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 22 Sep 2004 12:32:31 +0000 Subject: r2518: Some long overdue changes: - Samba4-style code in lib/registry (struct registry_key instead of REG_KEY, etc) - Use hives (like Windows has drives) instead of one root key (like a Unix FS) - usability fixes in the GTK utilities (autodetect the username, enable/disable options, etc) - fix gwsam compile - several bugfixes in the registry rpc code - do charset conversion in nt4 registry backend (This used to be commit 2762ed3b9bf1d67dd54d63e02cddbfd71ea89892) --- source4/lib/registry/common/reg_interface.c | 493 +++++++++++++--------------- source4/lib/registry/common/reg_objects.c | 213 ------------ source4/lib/registry/common/reg_util.c | 64 ++-- source4/lib/registry/common/registry.h | 142 -------- 4 files changed, 244 insertions(+), 668 deletions(-) delete mode 100644 source4/lib/registry/common/reg_objects.c delete mode 100644 source4/lib/registry/common/registry.h (limited to 'source4/lib/registry/common') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index f0a6807558..ec6188be71 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -19,7 +19,6 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY @@ -29,10 +28,12 @@ static struct reg_init_function_entry *backends = NULL; static struct reg_init_function_entry *reg_find_backend_entry(const char *name); +#define reg_make_path(mem_ctx, parent, name) (((parent)->hive->root == (parent))?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)) + /* Register new backend */ NTSTATUS registry_register(const void *_function) { - const struct registry_ops *functions = _function; + const struct registry_operations *functions = _function; struct reg_init_function_entry *entry = backends; if (!functions || !functions->name) { @@ -91,90 +92,157 @@ BOOL reg_has_backend(const char *backend) return reg_find_backend_entry(backend) != NULL?True:False; } -/* Open a registry file/host/etc */ -WERROR reg_open(const char *backend, const char *location, const char *credentials, REG_HANDLE **h) +WERROR reg_create(struct registry_context **_ret) +{ + TALLOC_CTX *mem_ctx; + struct registry_context *ret; + mem_ctx = talloc_init("registry handle"); + ret = talloc(mem_ctx, sizeof(struct registry_context)); + ret->mem_ctx = mem_ctx; + ZERO_STRUCTP(ret); + *_ret = ret; + return WERR_OK; +} + +WERROR reg_list_available_hives(TALLOC_CTX *mem_ctx, const char *backend, const char *location, const char *credentials, char ***hives) { struct reg_init_function_entry *entry; + + entry = reg_find_backend_entry(backend); + + if (!entry) { + DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); + return WERR_GENERAL_FAILURE; + } + + if(!entry->functions->list_available_hives) { + return WERR_NOT_SUPPORTED; + } + + return entry->functions->list_available_hives(mem_ctx, location, credentials, hives); +} + +WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials) +{ + WERROR error = reg_create(ret); + char **hives; + int i; + TALLOC_CTX *mem_ctx = talloc_init("reg_open"); + + if(!W_ERROR_IS_OK(error)) return error; + + error = reg_list_available_hives(mem_ctx, backend, location, credentials, &hives); + + if(W_ERROR_EQUAL(error, WERR_NOT_SUPPORTED)) { + return reg_import_hive(*ret, backend, location, credentials, NULL); + } + + if(!W_ERROR_IS_OK(error)) return error; + + for(i = 0; hives[i]; i++) + { + error = reg_import_hive(*ret, backend, location, credentials, hives[i]); + if(!W_ERROR_IS_OK(error)) return error; + (*ret)->hives[i]->name = talloc_strdup((*ret)->mem_ctx, hives[i]); + } + + return WERR_OK; +} + +/* Open a registry file/host/etc */ +WERROR reg_import_hive(struct registry_context *h, const char *backend, const char *location, const char *credentials, const char *hivename) +{ + struct registry_hive *ret; TALLOC_CTX *mem_ctx; - REG_HANDLE *ret; + struct reg_init_function_entry *entry; WERROR werr; - + entry = reg_find_backend_entry(backend); if (!entry) { DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); return WERR_GENERAL_FAILURE; } + + if(!entry->functions->open_hive) { + return WERR_NOT_SUPPORTED; + } - mem_ctx = talloc_init(backend); - ret = talloc(mem_ctx, sizeof(REG_HANDLE)); - ZERO_STRUCTP(ret); + + mem_ctx = h->mem_ctx; + ret = talloc_p(mem_ctx, struct registry_hive); ret->location = location?talloc_strdup(mem_ctx, location):NULL; + ret->backend_hivename = hivename?talloc_strdup(mem_ctx, hivename):NULL; ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL; ret->functions = entry->functions; ret->backend_data = NULL; - ret->mem_ctx = mem_ctx; - *h = ret; + ret->reg_ctx = h; - if(!entry->functions->open_registry) { - return WERR_OK; - } + werr = entry->functions->open_hive(mem_ctx, ret, &ret->root); + + if(!W_ERROR_IS_OK(werr)) return werr; - werr = entry->functions->open_registry(ret, location, credentials); + if(!ret->root) return WERR_GENERAL_FAILURE; - if(W_ERROR_IS_OK(werr)) - return WERR_OK; + ret->root->hive = ret; + ret->root->name = NULL; + ret->root->path = ""; - talloc_destroy(mem_ctx); - return werr; + /* Add hive to context */ + h->num_hives++; + h->hives = talloc_realloc_p(h->hives, struct registry_hive *, h->num_hives); + h->hives[h->num_hives-1] = ret; + + return WERR_OK; } /* Open a key by name (including the hive name!) */ -WERROR reg_open_key_abs(REG_HANDLE *handle, const char *name, REG_KEY **result) +WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result) { - REG_KEY *hive; + struct registry_key *hive; WERROR error; - int i, hivelength; + int hivelength; + char *hivename; if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; else hivelength = strlen(name); - for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_get_hive(handle, i, &hive); - if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) { - return reg_open_key(hive, name, result); - } + hivename = strndup(name, hivelength); + error = reg_get_hive(handle, hivename, &hive); + SAFE_FREE(hivename); + + if(!W_ERROR_IS_OK(error)) { + return error; } - return error; + return reg_open_key(mem_ctx, hive, 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 */ -WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) +WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result) { char *fullname; WERROR error; - TALLOC_CTX *mem_ctx; if(!parent) { DEBUG(0, ("Invalid parent key specified")); return WERR_INVALID_PARAM; } - if(!parent->handle->functions->open_key && - (parent->handle->functions->get_subkey_by_name || - parent->handle->functions->get_subkey_by_index)) { + if(!parent->hive->functions->open_key && + (parent->hive->functions->get_subkey_by_name || + parent->hive->functions->get_subkey_by_index)) { char *orig = strdup(name), *curbegin = orig, *curend = strchr(orig, '\\'); - REG_KEY *curkey = parent; + struct registry_key *curkey = parent; while(curbegin && *curbegin) { if(curend)*curend = '\0'; - error = reg_key_get_subkey_by_name(curkey, curbegin, result); + error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey); if(!W_ERROR_IS_OK(error)) { SAFE_FREE(orig); return error; @@ -184,94 +252,63 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) curend = strchr(curbegin, '\\'); } SAFE_FREE(orig); - + *result = curkey; + return WERR_OK; } - if(!parent->handle->functions->open_key) { + if(!parent->hive->functions->open_key) { DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); return WERR_NOT_SUPPORTED; } - mem_ctx = talloc_init("mem_ctx"); + fullname = reg_make_path(mem_ctx, parent, name); - fullname = talloc_asprintf(mem_ctx, "%s%s%s", - reg_key_get_path(parent), - strlen(reg_key_get_path(parent))?"\\":"", - name); + error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result); - error = parent->handle->functions->open_key(parent->handle, - parent->hive, fullname, result); - - if(!W_ERROR_IS_OK(error)) { - talloc_destroy(mem_ctx); - return error; - } + if(!W_ERROR_IS_OK(error)) return error; - (*result)->handle = parent->handle; - (*result)->path = talloc_asprintf((*result)->mem_ctx, "%s\\%s", - reg_key_get_path_abs(parent), (*result)->name); (*result)->hive = parent->hive; - talloc_steal((*result)->mem_ctx, fullname); - - talloc_destroy(mem_ctx); + (*result)->path = fullname; + (*result)->hive = parent->hive; return WERR_OK; } -WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val) +WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_value **val) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_value_by_index) { - WERROR status = key->handle->functions->get_value_by_index(key, idx, val); + if(key->hive->functions->get_value_by_index) { + WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val); if(!W_ERROR_IS_OK(status)) return status; - - } else if(key->handle->functions->fetch_values) { - if(!key->cache_values) - key->handle->functions->fetch_values(key, - &key->cache_values_count, &key->cache_values); - - if(idx < key->cache_values_count && idx >= 0) { - *val = reg_val_dup(key->cache_values[idx]); - } else { - return WERR_NO_MORE_ITEMS; - } } else { return WERR_NOT_SUPPORTED; } (*val)->parent = key; - (*val)->handle = key->handle; + (*val)->hive = key->hive; return WERR_OK; } -WERROR reg_key_num_subkeys(REG_KEY *key, int *count) +WERROR reg_key_num_subkeys(struct registry_key *key, int *count) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->num_subkeys) { - return key->handle->functions->num_subkeys(key, count); + if(key->hive->functions->num_subkeys) { + return key->hive->functions->num_subkeys(key, count); } - if(key->handle->functions->fetch_subkeys) { - if(!key->cache_subkeys) - key->handle->functions->fetch_subkeys(key, - &key->cache_subkeys_count, &key->cache_subkeys); - - *count = key->cache_subkeys_count; - return WERR_OK; - } - - if(key->handle->functions->get_subkey_by_index) { + if(key->hive->functions->get_subkey_by_index) { int i; WERROR error; - REG_KEY *dest; - for(i = 0; W_ERROR_IS_OK(error = key->handle->functions->get_subkey_by_index(key, i, &dest)); i++) { - reg_key_free(dest); - } + struct registry_key *dest; + TALLOC_CTX *mem_ctx = talloc_init("num_subkeys"); + + for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_subkey_by_index(mem_ctx, key, i, &dest)); i++); + talloc_destroy(mem_ctx); *count = i; if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_OK; @@ -281,74 +318,49 @@ WERROR reg_key_num_subkeys(REG_KEY *key, int *count) return WERR_NOT_SUPPORTED; } -WERROR reg_key_num_values(REG_KEY *key, int *count) +WERROR reg_key_num_values(struct registry_key *key, int *count) { if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->num_values) { - if(!key->handle->functions->fetch_values) { - DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name)); - return WERR_NOT_SUPPORTED; - } - - if(!key->cache_values) - key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); - - *count = key->cache_values_count; - return WERR_OK; - } - - - return key->handle->functions->num_values(key, count); + return key->hive->functions->num_values(key, count); } -WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) +WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_subkey_by_index) { - WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey); + if(key->hive->functions->get_subkey_by_index) { + WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey); if(!NT_STATUS_IS_OK(status)) return status; - } else if(key->handle->functions->fetch_subkeys) { - if(!key->cache_subkeys) - key->handle->functions->fetch_subkeys(key, - &key->cache_subkeys_count, &key->cache_subkeys); - - if(idx < key->cache_subkeys_count) { - *subkey = reg_key_dup(key->cache_subkeys[idx]); - } else { - return WERR_NO_MORE_ITEMS; - } } else { return WERR_NOT_SUPPORTED; } - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", - reg_key_get_path_abs(key), (*subkey)->name); - (*subkey)->handle = key->handle; - (*subkey)->hive = key->hive; - + if(key->hive->root == key) + (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name); + else + (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name); + (*subkey)->hive = key->hive; return WERR_OK;; } -WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subkey) +WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_key **subkey) { int i; WERROR error = WERR_OK; if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_subkey_by_name) { - error = key->handle->functions->get_subkey_by_name(key,name,subkey); - } else if(key->handle->functions->get_subkey_by_index || key->handle->functions->fetch_subkeys) { + if(key->hive->functions->get_subkey_by_name) { + error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey); + } else if(key->hive->functions->get_subkey_by_index) { for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_key_get_subkey_by_index(key, i, subkey); + error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey); if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) { return error; } - reg_key_free(*subkey); } } else { return WERR_NOT_SUPPORTED; @@ -356,29 +368,27 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk if(!W_ERROR_IS_OK(error)) return error; - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", reg_key_get_path_abs(key), (*subkey)->name); - (*subkey)->handle = key->handle; + (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name); (*subkey)->hive = key->hive; return WERR_OK; } -WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val) +WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_value **val) { int i; WERROR error = WERR_OK; if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_value_by_name) { - error = key->handle->functions->get_value_by_name(key,name, val); + if(key->hive->functions->get_value_by_name) { + error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val); } else { for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_key_get_value_by_index(key, i, val); + error = reg_key_get_value_by_index(mem_ctx, key, i, val); if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) { break; } - reg_val_free(*val); } } @@ -386,52 +396,49 @@ WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val) return error; (*val)->parent = key; - (*val)->handle = key->handle; + (*val)->hive = key->hive; return WERR_OK; } -WERROR reg_key_del(REG_KEY *key) +WERROR reg_key_del(struct registry_key *key) { WERROR error; if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->del_key) + if(!key->hive->functions->del_key) return WERR_NOT_SUPPORTED; - error = key->handle->functions->del_key(key); + error = key->hive->functions->del_key(key); if(!W_ERROR_IS_OK(error)) return error; - /* Invalidate cache */ - key->cache_subkeys = NULL; - key->cache_subkeys_count = 0; return WERR_OK; } -WERROR reg_sync(REG_KEY *h, const char *location) -{ - if(!h->handle->functions->sync_key) - return WERR_OK; - - return h->handle->functions->sync_key(h, location); -} - -WERROR reg_key_del_recursive(REG_KEY *key) +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++) { - REG_VAL *val; - error = reg_key_get_value_by_index(key, i, &val); + 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_val_del(val); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_del_value(val); + if(!W_ERROR_IS_OK(error)) { + talloc_destroy(mem_ctx); + return error; + } } } @@ -439,204 +446,150 @@ WERROR reg_key_del_recursive(REG_KEY *key) /* Delete all keys below this one */ for(i = 0; W_ERROR_IS_OK(error); i++) { - REG_KEY *subkey; + struct registry_key *subkey; - error = reg_key_get_subkey_by_index(key, i, &subkey); - if(!W_ERROR_IS_OK(error)) return error; + 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)) return error; + if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } } + talloc_destroy(mem_ctx); return reg_key_del(key); } -WERROR reg_val_del(REG_VAL *val) -{ - WERROR error; - if (!val) return WERR_INVALID_PARAM; - - if (!val->handle->functions->del_value) { - DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name)); - return WERR_NOT_SUPPORTED; - } - - error = val->handle->functions->del_value(val); - - if(!W_ERROR_IS_OK(error)) return error; - - val->parent->cache_values = NULL; - val->parent->cache_values_count = 0; - - return WERR_OK; -} - -WERROR reg_key_add_name_recursive_abs(REG_HANDLE *handle, const char *name) +WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name) { - REG_KEY *hive; + struct registry_key *hive; WERROR error; - int i, hivelength; + int hivelength; + char *hivename; if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; else hivelength = strlen(name); - for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_get_hive(handle, i, &hive); - if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) { - return reg_key_add_name_recursive(hive, name); - } - } + hivename = strndup(name, hivelength); + error = reg_get_hive(handle, hivename, &hive); + SAFE_FREE(hivename); - return error; + if(!W_ERROR_IS_OK(error)) return error; + + return reg_key_add_name_recursive(hive, name); } -WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path) +WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path) { - REG_KEY *cur, *prevcur = parent; - WERROR error; - /* FIXME: we should never write to a 'const char *' !!! --metze */ - char *begin = (char *)path, *end; + struct registry_key *cur, *prevcur = parent; + WERROR error = WERR_OK; + char *dup, *begin, *end; + TALLOC_CTX *mem_ctx = talloc_init("add_recursive"); + + begin = dup = strdup(path); while(1) { end = strchr(begin, '\\'); if(end) *end = '\0'; - error = reg_key_get_subkey_by_name(prevcur, begin, &cur); + 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(prevcur, begin, 0, NULL, &cur); - if(!W_ERROR_IS_OK(error)) return error; + 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 = '\\'; - return error; + break; } - if(!end) break; + if(!end) { + error = WERR_OK; + break; + } + *end = '\\'; begin = end+1; prevcur = cur; } - return WERR_OK; + SAFE_FREE(dup); + talloc_destroy(mem_ctx); + return error; } -WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, REG_KEY **newkey) +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; if (!parent) return WERR_INVALID_PARAM; - if (!parent->handle->functions->add_key) { - DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name)); + if (!parent->hive->functions->add_key) { + DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name)); return WERR_NOT_SUPPORTED; } - error = parent->handle->functions->add_key(parent, name, access_mask, desc, newkey); + error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey); if(!W_ERROR_IS_OK(error)) return error; - (*newkey)->handle = parent->handle; - (*newkey)->backend_data = talloc_asprintf((*newkey)->mem_ctx, "%s\\%s", reg_key_get_path(parent), name); + (*newkey)->hive = parent->hive; + (*newkey)->backend_data = talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name); - parent->cache_subkeys = NULL; - parent->cache_subkeys_count = 0; return WERR_OK; } -WERROR reg_val_update(REG_VAL *val, int type, void *data, int len) +WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len) { - WERROR error; - - /* A 'real' update function has preference */ - if (val->handle->functions->update_value) - return val->handle->functions->update_value(val, type, data, len); - - /* Otherwise, just remove and add again */ - if (val->handle->functions->add_value && - val->handle->functions->del_value) { - REG_VAL *new; - if(!W_ERROR_IS_OK(error = val->handle->functions->del_value(val))) - return error; - - error = val->handle->functions->add_value(val->parent, val->name, type, data, len); - if(!W_ERROR_IS_OK(error)) return error; - memcpy(val, new, sizeof(REG_VAL)); - val->parent->cache_values = NULL; - val->parent->cache_values_count = 0; - return WERR_OK; - } - - DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name)); - return WERR_NOT_SUPPORTED; -} - -void reg_free(REG_HANDLE *h) -{ - if(!h->functions->close_registry) return; + /* A 'real' set function has preference */ + if (key->hive->functions->set_value) + return key->hive->functions->set_value(key, value, type, data, len); - h->functions->close_registry(h); + DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name)); + return WERR_NOT_SUPPORTED; } -WERROR reg_get_hive(REG_HANDLE *h, int hivenum, REG_KEY **key) +WERROR reg_get_hive(struct registry_context *h, const char *name, struct registry_key **key) { - WERROR ret; - - if(h->functions->get_hive) { - ret = h->functions->get_hive(h, hivenum, key); - } else if(h->functions->open_key) { - if(hivenum == 0) ret = h->functions->open_key(h, hivenum, "", key); - else ret = WERR_NO_MORE_ITEMS; - } else { - DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key or get_hive method implemented\n", h->functions->name)); - ret = WERR_NOT_SUPPORTED; - } - - if(W_ERROR_IS_OK(ret)) { - (*key)->handle = h; - if(!(*key)->path) { - (*key)->path = talloc_strdup((*key)->mem_ctx, (*key)->name); + int i; + for(i = 0; i < h->num_hives; i++) + { + if(!strcmp(h->hives[i]->name, name)) { + *key = h->hives[i]->root; + return WERR_OK; } - (*key)->hive = hivenum; } - return ret; + return WERR_NO_MORE_ITEMS; } -WERROR reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen) +WERROR reg_del_value(struct registry_value *val) { WERROR ret = WERR_OK; - if(!key->handle->functions->add_value) + if(!val->hive->functions->del_value) return WERR_NOT_SUPPORTED; - ret = key->handle->functions->add_value(key, name, type, value, vallen); + ret = val->hive->functions->del_value(val); if(!W_ERROR_IS_OK(ret)) return ret; - /* Invalidate the cache */ - key->cache_values = NULL; - key->cache_values_count = 0; return ret; } -WERROR reg_save(REG_HANDLE *h, const char *location) +WERROR reg_save(struct registry_context *h, const char *location) { /* FIXME */ return WERR_NOT_SUPPORTED; } -WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent) +WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent) { char *parent_name; char *last; - REG_KEY *root; + struct registry_key *root; WERROR error; - error = reg_get_hive(key->handle, key->hive, &root); - if(!W_ERROR_IS_OK(error)) return error; - - parent_name = strdup(reg_key_get_path(key)); + parent_name = strdup(key->path); last = strrchr(parent_name, '\\'); if(!last) { @@ -645,7 +598,7 @@ WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent) } *last = '\0'; - error = reg_open_key(root, parent_name, parent); + error = reg_open_key(mem_ctx, root, parent_name, parent); SAFE_FREE(parent_name); return error; } diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c deleted file mode 100644 index d911b4650b..0000000000 --- a/source4/lib/registry/common/reg_objects.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Gerald Carter 2002. - * Copyright (C) Jelmer Vernooij 2003-2004. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Implementation of registry frontend view functions. */ - -#include "includes.h" -#include "lib/registry/common/registry.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_SRV - -/*********************************************************************** - allocate memory for and duplicate a REG_VAL. - This is malloc'd memory so the caller should free it when done - **********************************************************************/ - -REG_VAL* reg_val_dup( REG_VAL *val ) -{ - val->ref++; - return val; -} - -/********************************************************************** - free the memory allocated to a REG_VAL - *********************************************************************/ - -void reg_val_free( REG_VAL *val ) -{ - if ( !val ) - return; - - val->ref--; - if(val->ref) return; - - if(val->handle->functions->free_val_backend_data) - val->handle->functions->free_val_backend_data(val); - - talloc_destroy( val->mem_ctx ); - - return; -} - -/********************************************************************** - *********************************************************************/ - -uint8_t * reg_val_data_blk( REG_VAL *val ) -{ - return val->data_blk; -} - -/********************************************************************** - *********************************************************************/ - -int reg_val_size( REG_VAL *val ) -{ - return val->data_len; -} - -/********************************************************************** - *********************************************************************/ - -char *reg_val_name( REG_VAL *val ) -{ - return val->name; -} - -/********************************************************************** - *********************************************************************/ - -uint32_t reg_val_type( REG_VAL *val ) -{ - return val->data_type; -} - -/********************************************************************** - *********************************************************************/ - -REG_HANDLE *reg_key_handle (REG_KEY *key) -{ - return key->handle; -} - -char *reg_key_name( REG_KEY *key ) -{ - return key->name; -} - -char *reg_key_class( REG_KEY *key ) -{ - return key->class_name; -} - -NTTIME reg_key_last_modified( REG_KEY *key ) -{ - return key->last_mod; -} - -REG_KEY *reg_key_dup(REG_KEY *key) -{ - key->ref++; - return key; -} - -void reg_key_free(REG_KEY *key) -{ - if(!key) - return; - - key->ref--; - if(key->ref) return; - - if(key->handle->functions->free_key_backend_data) - key->handle->functions->free_key_backend_data(key); - - if(key->cache_values) { - int i; - for(i = 0; i < key->cache_values_count; i++) { - reg_val_free(key->cache_values[i]); - } - } - - if(key->cache_subkeys) { - int i; - for(i = 0; i < key->cache_subkeys_count; i++) { - reg_key_free(key->cache_subkeys[i]); - } - } - - talloc_destroy(key->mem_ctx); -} - -char *reg_val_get_path(REG_VAL *v) -{ - /* FIXME */ - return NULL; -} - -const char *reg_key_get_path(REG_KEY *k) -{ - SMB_REG_ASSERT(k); - return strchr(k->path, '\\')?strchr(k->path, '\\')+1:""; -} - -const char *reg_key_get_path_abs(REG_KEY *k) -{ - SMB_REG_ASSERT(k); - return k->path; -} - -/* For use by the backends _ONLY_ */ -REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) -{ - REG_KEY *r; - TALLOC_CTX *mem_ctx = talloc_init(path); - r = talloc(mem_ctx, sizeof(REG_KEY)); - ZERO_STRUCTP(r); - r->handle = h; - r->mem_ctx = mem_ctx; - r->path = talloc_strdup(mem_ctx, path); - r->name = talloc_strdup(mem_ctx, strrchr(path, '\\')?strrchr(path,'\\')+1:path); - r->backend_data = data; - r->ref = 1; - return r; -} - -REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data) -{ - REG_KEY *r; - const char *parent_path = k?reg_key_get_path(k):""; - TALLOC_CTX *mem_ctx = talloc_init(name); - r = talloc(mem_ctx, sizeof(REG_KEY)); - ZERO_STRUCTP(r); - r->handle = k->handle; - r->hive = k->hive; - r->name = talloc_strdup(mem_ctx, name); - - r->path = talloc_asprintf(mem_ctx, "%s%s%s", parent_path, *parent_path && parent_path[strlen(parent_path)-1] != '\\'?"\\":"", name); - r->backend_data = data; - r->mem_ctx = mem_ctx; - r->ref = 1; - return r; -} - -REG_VAL *reg_val_new(REG_KEY *parent, void *data) -{ - REG_VAL *r; - TALLOC_CTX *mem_ctx = talloc_init("value"); - r = talloc(mem_ctx, sizeof(REG_VAL)); - ZERO_STRUCTP(r); - r->mem_ctx = mem_ctx; - r->handle = parent->handle; - r->backend_data = data; - r->ref = 1; - return r; -} diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index db5e97bf7f..21c925deab 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -34,90 +34,68 @@ const char *str_regtype(int type) return "Unknown"; } -char *reg_val_data_string(REG_VAL *v) +char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) { char *asciip; char *ret = NULL; int i; - if(reg_val_size(v) == 0) return strdup(""); + if(v->data_len == 0) return talloc_strdup(mem_ctx, ""); - switch (reg_val_type(v)) { + switch (v->data_type) { case REG_SZ: - /* FIXME: Convert to ascii */ - return strndup(reg_val_data_blk(v), reg_val_size(v)); + return talloc_strndup(mem_ctx, v->data_blk, v->data_len); case REG_EXPAND_SZ: - return strndup(reg_val_data_blk(v), reg_val_size(v)); + return talloc_strndup(mem_ctx, v->data_blk, v->data_len); case REG_BINARY: - ret = malloc(reg_val_size(v) * 3 + 2); + ret = talloc(mem_ctx, v->data_len * 3 + 2); asciip = ret; - for (i=0; i 0) + for (i=0; idata_len; i++) { + int str_rem = v->data_len * 3 - (asciip - ret); + asciip += snprintf(asciip, str_rem, "%02x", *(uint8_t *)(v->data_blk+i)); + if (i < v->data_len && str_rem > 0) *asciip = ' '; asciip++; } *asciip = '\0'; return ret; - break; case REG_DWORD: - if (*(int *)reg_val_data_blk(v) == 0) - ret = strdup("0"); - else - asprintf(&ret, "0x%x", *(int *)reg_val_data_blk(v)); - break; + if (*(int *)v->data_blk == 0) + return talloc_strdup(mem_ctx, "0"); + + return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data_blk); case REG_MULTI_SZ: /* FIXME */ break; default: - return 0; break; } return ret; } -char *reg_val_description(REG_VAL *val) +char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) { - char *ret, *ds = reg_val_data_string(val); - asprintf(&ret, "%s = %s : %s", reg_val_name(val)?reg_val_name(val):"", str_regtype(reg_val_type(val)), ds); - free(ds); - return ret; + return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val)); } -BOOL reg_val_set_string(REG_VAL *val, char *str) +BOOL reg_val_set_string(struct registry_value *val, char *str) { /* FIXME */ return False; } -WERROR reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname, REG_VAL **val) +WERROR reg_key_get_subkey_val(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *subname, const char *valname, struct registry_value **val) { - REG_KEY *k; - WERROR error = reg_key_get_subkey_by_name(key, subname, &k); - if(!W_ERROR_IS_OK(error)) return error; - - return reg_key_get_value_by_name(k, valname, val); -} - -WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32_t type, uint8_t *data, int real_len) -{ - REG_KEY *k; - REG_VAL *v; - WERROR error; - - error = reg_key_get_subkey_by_name(key, subname, &k); - if(!W_ERROR_IS_OK(error)) return error; - - error = reg_key_get_value_by_name(k, valname, &v); + struct registry_key *k; + WERROR error = reg_key_get_subkey_by_name(mem_ctx, key, subname, &k); if(!W_ERROR_IS_OK(error)) return error; - return reg_val_update(v, type, data, real_len); + return reg_key_get_value_by_name(mem_ctx, k, valname, val); } /*********************************************************************** diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h deleted file mode 100644 index 89d0ac6b14..0000000000 --- a/source4/lib/registry/common/registry.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Registry interface - This file contains the _internal_ structs for the registry - subsystem. Backends and the subsystem itself are the only - files that need to include this file. - Copyright (C) Gerald Carter 2002. - Copyright (C) Jelmer Vernooij 2003-2004. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _REGISTRY_REGISTRY_H /* _REGISTRY_REGISTRY_H */ -#define _REGISTRY_REGISTRY_H - -#define REGISTRY_INTERFACE_VERSION 1 - -/* structure to store the registry handles */ -struct reg_key_s { - char *name; /* Name of the key */ - char *path; /* Full path to the key */ - char *class_name; /* Name of key class */ - NTTIME last_mod; /* Time last modified */ - SEC_DESC *security; - REG_HANDLE *handle; - void *backend_data; - REG_VAL **cache_values; - int cache_values_count; - REG_KEY **cache_subkeys; - int cache_subkeys_count; - int hive; - TALLOC_CTX *mem_ctx; - int ref; -}; - -struct reg_val_s { - char *name; - int has_name; - int data_type; - int data_len; - void *data_blk; /* Might want a separate block */ - REG_HANDLE *handle; - REG_KEY *parent; - void *backend_data; - TALLOC_CTX *mem_ctx; - int ref; -}; - -/* FIXME */ -typedef void (*key_notification_function) (void); -typedef void (*value_notification_function) (void); - -/* - * Container for function pointers to enumeration routines - * for virtual registry view - * - * Backends can provide : - * - just one hive (example: nt4, w95) - * - several hives (example: rpc) - * - */ - -struct registry_ops { - const char *name; - WERROR (*open_registry) (REG_HANDLE *, const char *location, const char *credentials); - WERROR (*sync_key)(REG_KEY *, const char *location); - WERROR (*close_registry) (REG_HANDLE *); - - /* Implement this one */ - WERROR (*get_hive) (REG_HANDLE *, int , REG_KEY **); - - /* Or this one */ - WERROR (*open_key) (REG_HANDLE *, int hive, const char *name, REG_KEY **); - - /* Either implement these */ - WERROR (*num_subkeys) (REG_KEY *, int *count); - WERROR (*num_values) (REG_KEY *, int *count); - WERROR (*get_subkey_by_index) (REG_KEY *, int idx, REG_KEY **); - /* Can not contain more then one level */ - WERROR (*get_subkey_by_name) (REG_KEY *, const char *name, REG_KEY **); - WERROR (*get_value_by_index) (REG_KEY *, int idx, REG_VAL **); - /* Can not contain more then one level */ - WERROR (*get_value_by_name) (REG_KEY *, const char *name, REG_VAL **); - - /* Or these */ - WERROR (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***); - WERROR (*fetch_values) (REG_KEY *, int *count, REG_VAL ***); - - /* Security control */ - WERROR (*key_get_sec_desc) (REG_KEY *, SEC_DESC **); - WERROR (*key_set_sec_desc) (REG_KEY *, SEC_DESC *); - - /* Notification */ - WERROR (*request_key_change_notify) (REG_KEY *, key_notification_function); - WERROR (*request_value_change_notify) (REG_VAL *, value_notification_function); - - /* Key management */ - WERROR (*add_key)(REG_KEY *, const char *name, uint32_t access_mask, SEC_DESC *, REG_KEY **); - WERROR (*del_key)(REG_KEY *); - - /* Value management */ - WERROR (*add_value)(REG_KEY *, const char *name, int type, void *data, int len); - WERROR (*del_value)(REG_VAL *); - - /* If update is not available, value will first be deleted and then added - * again */ - WERROR (*update_value)(REG_VAL *, int type, void *data, int len); - - void (*free_key_backend_data) (REG_KEY *); - void (*free_val_backend_data) (REG_VAL *); -}; - -struct reg_handle_s { - const struct registry_ops *functions; - char *location; - char *credentials; - void *backend_data; - TALLOC_CTX *mem_ctx; -}; - -struct reg_init_function_entry { - /* Function to create a member of the pdb_methods list */ - const struct registry_ops *functions; - struct reg_init_function_entry *prev, *next; -}; - -/* Used internally */ -#define SMB_REG_ASSERT(a) { if(!(a)) { DEBUG(0,("%s failed! (%s:%d)", #a, __FILE__, __LINE__)); }} - -#endif /* _REGISTRY_H */ -- cgit