2 Unix SMB/CIFS implementation.
3 Transparent registry backend handling
4 Copyright (C) Jelmer Vernooij 2003-2004.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define DBGC_CLASS DBGC_REGISTRY
26 /* List of available backends */
27 static struct reg_init_function_entry *backends = NULL;
29 static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
31 #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))
33 /* Register new backend */
34 NTSTATUS registry_register(const void *_function)
36 const struct registry_operations *functions = _function;
37 struct reg_init_function_entry *entry = backends;
39 if (!functions || !functions->name) {
40 DEBUG(0, ("Invalid arguments while registering registry backend\n"));
41 return NT_STATUS_INVALID_PARAMETER;
44 DEBUG(5,("Attempting to register registry backend %s\n", functions->name));
46 /* Check for duplicates */
47 if (reg_find_backend_entry(functions->name)) {
48 DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name));
49 return NT_STATUS_OBJECT_NAME_COLLISION;
52 entry = malloc(sizeof(struct reg_init_function_entry));
53 entry->functions = functions;
55 DLIST_ADD(backends, entry);
56 DEBUG(5,("Successfully added registry backend '%s'\n", functions->name));
60 static BOOL registry_init(void)
62 static BOOL initialised;
69 status = register_subsystem("registry", registry_register);
70 if (NT_STATUS_IS_ERR(status)) {
71 DEBUG(0, ("Error registering registry subsystem: %s\n", nt_errstr(status)));
80 /* Find a backend in the list of available backends */
81 static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
83 struct reg_init_function_entry *entry;
85 if(registry_init() == False) return NULL;
90 if (strcmp(entry->functions->name, name) == 0) return entry;
97 /* Check whether a certain backend is present */
98 BOOL reg_has_backend(const char *backend)
100 return reg_find_backend_entry(backend) != NULL?True:False;
103 WERROR reg_create(struct registry_context **_ret)
106 struct registry_context *ret;
107 mem_ctx = talloc_init("registry handle");
108 ret = talloc(mem_ctx, sizeof(struct registry_context));
109 ret->mem_ctx = mem_ctx;
115 WERROR reg_list_available_hives(TALLOC_CTX *mem_ctx, const char *backend, const char *location, const char *credentials, char ***hives)
117 struct reg_init_function_entry *entry;
119 entry = reg_find_backend_entry(backend);
122 DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
123 return WERR_GENERAL_FAILURE;
126 if(!entry->functions->list_available_hives) {
127 return WERR_NOT_SUPPORTED;
130 return entry->functions->list_available_hives(mem_ctx, location, credentials, hives);
133 WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials)
135 WERROR error = reg_create(ret);
138 TALLOC_CTX *mem_ctx = talloc_init("reg_open");
140 if(!W_ERROR_IS_OK(error)) return error;
142 error = reg_list_available_hives(mem_ctx, backend, location, credentials, &hives);
144 if(W_ERROR_EQUAL(error, WERR_NOT_SUPPORTED)) {
145 return reg_import_hive(*ret, backend, location, credentials, NULL);
148 if(!W_ERROR_IS_OK(error)) return error;
150 for(i = 0; hives[i]; i++)
152 error = reg_import_hive(*ret, backend, location, credentials, hives[i]);
153 if(!W_ERROR_IS_OK(error)) return error;
154 (*ret)->hives[i]->name = talloc_strdup((*ret)->mem_ctx, hives[i]);
160 WERROR reg_close (struct registry_context *ctx)
163 for (i = 0; i < ctx->num_hives; i++) {
164 if (ctx->hives[i]->functions->close_hive) {
165 ctx->hives[i]->functions->close_hive(ctx->hives[i]);
173 /* Open a registry file/host/etc */
174 WERROR reg_import_hive(struct registry_context *h, const char *backend, const char *location, const char *credentials, const char *hivename)
176 struct registry_hive *ret;
178 struct reg_init_function_entry *entry;
181 entry = reg_find_backend_entry(backend);
184 DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
185 return WERR_GENERAL_FAILURE;
188 if(!entry->functions->open_hive) {
189 return WERR_NOT_SUPPORTED;
193 mem_ctx = h->mem_ctx;
194 ret = talloc_p(mem_ctx, struct registry_hive);
195 ret->location = location?talloc_strdup(mem_ctx, location):NULL;
196 ret->backend_hivename = hivename?talloc_strdup(mem_ctx, hivename):NULL;
197 ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL;
198 ret->functions = entry->functions;
199 ret->backend_data = NULL;
203 werr = entry->functions->open_hive(mem_ctx, ret, &ret->root);
205 if(!W_ERROR_IS_OK(werr)) return werr;
208 DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
209 return WERR_GENERAL_FAILURE;
212 ret->root->hive = ret;
213 ret->root->name = NULL;
214 ret->root->path = talloc_strdup(mem_ctx, "");
216 /* Add hive to context */
218 h->hives = talloc_realloc_p(h, h->hives, struct registry_hive *, h->num_hives);
219 h->hives[h->num_hives-1] = ret;
224 /* Open a key by name (including the hive name!) */
225 WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result)
227 struct registry_key *hive;
232 if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
233 else hivelength = strlen(name);
235 hivename = strndup(name, hivelength);
236 error = reg_get_hive(handle, hivename, &hive);
239 if(!W_ERROR_IS_OK(error)) {
243 return reg_open_key(mem_ctx, hive, name, result);
247 * First tries to use the open_key function from the backend
248 * then falls back to get_subkey_by_name and later get_subkey_by_index
250 WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result)
256 DEBUG(0, ("Invalid parent key specified"));
257 return WERR_INVALID_PARAM;
260 if(!parent->hive->functions->open_key &&
261 (parent->hive->functions->get_subkey_by_name ||
262 parent->hive->functions->get_subkey_by_index)) {
263 char *orig = strdup(name),
265 *curend = strchr(orig, '\\');
266 struct registry_key *curkey = parent;
268 while(curbegin && *curbegin) {
269 if(curend)*curend = '\0';
270 error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey);
271 if(!W_ERROR_IS_OK(error)) {
276 curbegin = curend + 1;
277 curend = strchr(curbegin, '\\');
286 if(!parent->hive->functions->open_key) {
287 DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
288 return WERR_NOT_SUPPORTED;
291 fullname = reg_make_path(mem_ctx, parent, name);
293 error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result);
295 if(!W_ERROR_IS_OK(error)) return error;
297 (*result)->hive = parent->hive;
298 (*result)->path = fullname;
299 (*result)->hive = parent->hive;
304 WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_value **val)
306 if(!key) return WERR_INVALID_PARAM;
308 if(key->hive->functions->get_value_by_index) {
309 WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val);
310 if(!W_ERROR_IS_OK(status))
313 return WERR_NOT_SUPPORTED;
316 (*val)->parent = key;
317 (*val)->hive = key->hive;
321 WERROR reg_key_num_subkeys(struct registry_key *key, int *count)
323 if(!key) return WERR_INVALID_PARAM;
325 if(key->hive->functions->num_subkeys) {
326 return key->hive->functions->num_subkeys(key, count);
329 if(key->hive->functions->get_subkey_by_index) {
332 struct registry_key *dest;
333 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
335 for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_subkey_by_index(mem_ctx, key, i, &dest)); i++);
336 talloc_destroy(mem_ctx);
339 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_OK;
343 return WERR_NOT_SUPPORTED;
346 WERROR reg_key_num_values(struct registry_key *key, int *count)
349 if(!key) return WERR_INVALID_PARAM;
351 return key->hive->functions->num_values(key, count);
354 WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey)
356 if(!key) return WERR_INVALID_PARAM;
358 if(key->hive->functions->get_subkey_by_index) {
359 WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey);
360 if(!NT_STATUS_IS_OK(status)) return status;
362 return WERR_NOT_SUPPORTED;
365 if(key->hive->root == key)
366 (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name);
368 (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
370 (*subkey)->hive = key->hive;
374 WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_key **subkey)
377 WERROR error = WERR_OK;
379 if(!key) return WERR_INVALID_PARAM;
381 if(key->hive->functions->get_subkey_by_name) {
382 error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey);
383 } else if(key->hive->functions->open_key) {
384 error = key->hive->functions->open_key(mem_ctx, key->hive, talloc_asprintf(mem_ctx, "%s\\%s", key->path, name), subkey);
385 } else if(key->hive->functions->get_subkey_by_index) {
386 for(i = 0; W_ERROR_IS_OK(error); i++) {
387 error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey);
388 if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) {
393 return WERR_NOT_SUPPORTED;
396 if(!W_ERROR_IS_OK(error)) return error;
398 (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
399 (*subkey)->hive = key->hive;
404 WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_value **val)
407 WERROR error = WERR_OK;
409 if(!key) return WERR_INVALID_PARAM;
411 if(key->hive->functions->get_value_by_name) {
412 error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val);
414 for(i = 0; W_ERROR_IS_OK(error); i++) {
415 error = reg_key_get_value_by_index(mem_ctx, key, i, val);
416 if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) {
422 if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
425 (*val)->parent = key;
426 (*val)->hive = key->hive;
431 WERROR reg_key_del(struct registry_key *key)
434 if(!key) return WERR_INVALID_PARAM;
437 if(!key->hive->functions->del_key)
438 return WERR_NOT_SUPPORTED;
440 error = key->hive->functions->del_key(key);
441 if(!W_ERROR_IS_OK(error)) return error;
446 WERROR reg_key_del_recursive(struct registry_key *key)
448 WERROR error = WERR_OK;
451 TALLOC_CTX *mem_ctx = talloc_init("del_recursive");
453 /* Delete all values for specified key */
454 for(i = 0; W_ERROR_IS_OK(error); i++) {
455 struct registry_value *val;
456 error = reg_key_get_value_by_index(mem_ctx, key, i, &val);
457 if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
459 talloc_destroy(mem_ctx);
463 if(W_ERROR_IS_OK(error)) {
464 error = reg_del_value(val);
465 if(!W_ERROR_IS_OK(error)) {
466 talloc_destroy(mem_ctx);
474 /* Delete all keys below this one */
475 for(i = 0; W_ERROR_IS_OK(error); i++) {
476 struct registry_key *subkey;
478 error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
479 if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; }
481 error = reg_key_del_recursive(subkey);
482 if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; }
485 talloc_destroy(mem_ctx);
486 return reg_key_del(key);
489 WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name)
491 struct registry_key *hive;
496 if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
497 else hivelength = strlen(name);
499 hivename = strndup(name, hivelength);
500 error = reg_get_hive(handle, hivename, &hive);
503 if(!W_ERROR_IS_OK(error)) return error;
505 return reg_key_add_name_recursive(hive, name);
508 WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path)
510 struct registry_key *cur, *prevcur = parent;
511 WERROR error = WERR_OK;
512 char *dups, *begin, *end;
513 TALLOC_CTX *mem_ctx = talloc_init("add_recursive");
515 begin = dups = strdup(path);
518 end = strchr(begin, '\\');
521 error = reg_key_get_subkey_by_name(mem_ctx, prevcur, begin, &cur);
523 /* Key is not there, add it */
524 if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
525 error = reg_key_add_name(mem_ctx, prevcur, begin, 0, NULL, &cur);
526 if(!W_ERROR_IS_OK(error)) break;
529 if(!W_ERROR_IS_OK(error)) {
544 talloc_destroy(mem_ctx);
548 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)
552 if (!parent) return WERR_INVALID_PARAM;
554 if (!parent->hive->functions->add_key) {
555 DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name));
556 return WERR_NOT_SUPPORTED;
559 error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey);
561 if(!W_ERROR_IS_OK(error)) return error;
563 (*newkey)->hive = parent->hive;
564 (*newkey)->backend_data = talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name);
569 WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len)
571 /* A 'real' set function has preference */
572 if (key->hive->functions->set_value)
573 return key->hive->functions->set_value(key, value, type, data, len);
575 DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name));
576 return WERR_NOT_SUPPORTED;
579 WERROR reg_get_hive(struct registry_context *h, const char *name, struct registry_key **key)
582 for(i = 0; i < h->num_hives; i++)
584 if(!strcmp(h->hives[i]->name, name)) {
585 *key = h->hives[i]->root;
590 return WERR_NO_MORE_ITEMS;
593 WERROR reg_del_value(struct registry_value *val)
595 WERROR ret = WERR_OK;
596 if(!val->hive->functions->del_value)
597 return WERR_NOT_SUPPORTED;
599 ret = val->hive->functions->del_value(val);
601 if(!W_ERROR_IS_OK(ret)) return ret;
606 WERROR reg_save (struct registry_context *ctx, const char *location)
608 return WERR_NOT_SUPPORTED;
611 WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent)
615 struct registry_key *root;
618 parent_name = strdup(key->path);
619 last = strrchr(parent_name, '\\');
622 SAFE_FREE(parent_name);
627 error = reg_open_key(mem_ctx, root, parent_name, parent);
628 SAFE_FREE(parent_name);
632 WERROR reg_key_flush(struct registry_key *key)
635 return WERR_INVALID_PARAM;
638 if (key->hive->functions->flush_key) {
639 return key->hive->functions->flush_key(key);
642 /* No need for flushing, apparently */