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.
22 #include "lib/registry/common/registry.h"
25 #define DBGC_CLASS DBGC_REGISTRY
27 /* List of available backends */
28 static struct reg_init_function_entry *backends = NULL;
30 static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
32 /* Register new backend */
33 NTSTATUS registry_register(void *_function)
35 struct registry_ops *functions = _function;
36 struct reg_init_function_entry *entry = backends;
38 if (!functions || !functions->name) {
39 return NT_STATUS_INVALID_PARAMETER;
42 DEBUG(5,("Attempting to register registry backend %s\n", functions->name));
44 /* Check for duplicates */
45 if (reg_find_backend_entry(functions->name)) {
46 DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name));
47 return NT_STATUS_OBJECT_NAME_COLLISION;
50 entry = malloc(sizeof(struct reg_init_function_entry));
51 entry->functions = functions;
53 DLIST_ADD(backends, entry);
54 DEBUG(5,("Successfully added registry backend '%s'\n", functions->name));
58 /* Find a backend in the list of available backends */
59 static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
61 struct reg_init_function_entry *entry;
62 static BOOL reg_first_init = True;
66 status = register_subsystem("registry", registry_register);
67 if (NT_STATUS_IS_ERR(status)) {
68 DEBUG(0, ("Error registering registry subsystem: %s\n", nt_errstr(status)));
69 /* Don't try the initialisation again */
70 reg_first_init = False;
75 reg_first_init = False;
81 if (strcmp(entry->functions->name, name)==0) return entry;
88 /* Check whether a certain backend is present */
89 BOOL reg_has_backend(const char *backend)
91 return reg_find_backend_entry(backend) != NULL?True:False;
94 /* Open a registry file/host/etc */
95 WERROR reg_open(const char *backend, const char *location, const char *credentials, REG_HANDLE **h)
97 struct reg_init_function_entry *entry;
103 entry = reg_find_backend_entry(backend);
106 DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
107 return WERR_GENERAL_FAILURE;
110 mem_ctx = talloc_init(backend);
111 ret = talloc(mem_ctx, sizeof(REG_HANDLE));
113 ret->location = location?talloc_strdup(mem_ctx, location):NULL;
114 ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL;
115 ret->functions = entry->functions;
116 ret->backend_data = NULL;
117 ret->mem_ctx = mem_ctx;
120 if(!entry->functions->open_registry) {
124 werr = entry->functions->open_registry(ret, location, credentials);
126 if(W_ERROR_IS_OK(werr))
129 talloc_destroy(mem_ctx);
133 /* Open a key by name (including the hive name!) */
134 WERROR reg_open_key_abs(REG_HANDLE *handle, const char *name, REG_KEY **result)
140 if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
141 else hivelength = strlen(name);
143 for(i = 0; W_ERROR_IS_OK(error); i++) {
144 error = reg_get_hive(handle, i, &hive);
145 if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) {
146 return reg_open_key(hive, name, result);
154 * First tries to use the open_key function from the backend
155 * then falls back to get_subkey_by_name and later get_subkey_by_index
157 WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result)
164 DEBUG(0, ("Invalid parent key specified"));
165 return WERR_INVALID_PARAM;
168 if(!parent->handle->functions->open_key &&
169 (parent->handle->functions->get_subkey_by_name ||
170 parent->handle->functions->get_subkey_by_index)) {
171 char *orig = strdup(name),
173 *curend = strchr(orig, '\\');
174 REG_KEY *curkey = parent;
176 while(curbegin && *curbegin) {
177 if(curend)*curend = '\0';
178 error = reg_key_get_subkey_by_name(curkey, curbegin, result);
179 if(!W_ERROR_IS_OK(error)) {
184 curbegin = curend + 1;
185 curend = strchr(curbegin, '\\');
193 if(!parent->handle->functions->open_key) {
194 DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
195 return WERR_NOT_SUPPORTED;
198 mem_ctx = talloc_init("mem_ctx");
200 fullname = talloc_asprintf(mem_ctx, "%s%s%s",
201 reg_key_get_path(parent),
202 strlen(reg_key_get_path(parent))?"\\":"",
205 error = parent->handle->functions->open_key(parent->handle,
206 parent->hive, fullname, result);
208 if(!W_ERROR_IS_OK(error)) {
209 talloc_destroy(mem_ctx);
213 (*result)->handle = parent->handle;
214 (*result)->path = talloc_asprintf((*result)->mem_ctx, "%s\\%s",
215 reg_key_get_path_abs(parent), (*result)->name);
216 (*result)->hive = parent->hive;
217 talloc_steal(mem_ctx, (*result)->mem_ctx, fullname);
219 talloc_destroy(mem_ctx);
224 WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val)
226 if(!key) return WERR_INVALID_PARAM;
228 if(key->handle->functions->get_value_by_index) {
229 WERROR status = key->handle->functions->get_value_by_index(key, idx, val);
230 if(!W_ERROR_IS_OK(status))
233 } else if(key->handle->functions->fetch_values) {
234 if(!key->cache_values)
235 key->handle->functions->fetch_values(key,
236 &key->cache_values_count, &key->cache_values);
238 if(idx < key->cache_values_count && idx >= 0) {
239 *val = reg_val_dup(key->cache_values[idx]);
241 return WERR_NO_MORE_ITEMS;
244 return WERR_NOT_SUPPORTED;
247 (*val)->parent = key;
248 (*val)->handle = key->handle;
252 WERROR reg_key_num_subkeys(REG_KEY *key, int *count)
254 if(!key) return WERR_INVALID_PARAM;
256 if(key->handle->functions->num_subkeys) {
257 return key->handle->functions->num_subkeys(key, count);
260 if(key->handle->functions->fetch_subkeys) {
261 if(!key->cache_subkeys)
262 key->handle->functions->fetch_subkeys(key,
263 &key->cache_subkeys_count, &key->cache_subkeys);
265 *count = key->cache_subkeys_count;
269 if(key->handle->functions->get_subkey_by_index) {
273 for(i = 0; W_ERROR_IS_OK(error = key->handle->functions->get_subkey_by_index(key, i, &dest)); i++) {
278 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_OK;
282 return WERR_NOT_SUPPORTED;
285 WERROR reg_key_num_values(REG_KEY *key, int *count)
288 if(!key) return WERR_INVALID_PARAM;
290 if(!key->handle->functions->num_values) {
291 if(!key->handle->functions->fetch_values) {
292 DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name));
293 return WERR_NOT_SUPPORTED;
296 if(!key->cache_values)
297 key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values);
299 *count = key->cache_values_count;
304 return key->handle->functions->num_values(key, count);
307 WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey)
309 if(!key) return WERR_INVALID_PARAM;
311 if(key->handle->functions->get_subkey_by_index) {
312 WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey);
313 if(!NT_STATUS_IS_OK(status)) return status;
314 } else if(key->handle->functions->fetch_subkeys) {
315 if(!key->cache_subkeys)
316 key->handle->functions->fetch_subkeys(key,
317 &key->cache_subkeys_count, &key->cache_subkeys);
319 if(idx < key->cache_subkeys_count) {
320 *subkey = reg_key_dup(key->cache_subkeys[idx]);
322 return WERR_NO_MORE_ITEMS;
325 return WERR_NOT_SUPPORTED;
328 (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s",
329 reg_key_get_path_abs(key), (*subkey)->name);
330 (*subkey)->handle = key->handle;
331 (*subkey)->hive = key->hive;
337 WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subkey)
340 WERROR error = WERR_OK;
342 if(!key) return WERR_INVALID_PARAM;
344 if(key->handle->functions->get_subkey_by_name) {
345 error = key->handle->functions->get_subkey_by_name(key,name,subkey);
346 } else if(key->handle->functions->get_subkey_by_index || key->handle->functions->fetch_subkeys) {
347 for(i = 0; W_ERROR_IS_OK(error); i++) {
348 error = reg_key_get_subkey_by_index(key, i, subkey);
349 if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) {
352 reg_key_free(*subkey);
355 return WERR_NOT_SUPPORTED;
358 if(!W_ERROR_IS_OK(error)) return error;
360 (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", reg_key_get_path_abs(key), (*subkey)->name);
361 (*subkey)->handle = key->handle;
362 (*subkey)->hive = key->hive;
367 WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val)
370 WERROR error = WERR_OK;
372 if(!key) return WERR_INVALID_PARAM;
374 if(key->handle->functions->get_value_by_name) {
375 error = key->handle->functions->get_value_by_name(key,name, val);
377 for(i = 0; W_ERROR_IS_OK(error); i++) {
378 error = reg_key_get_value_by_index(key, i, val);
379 if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) {
386 if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
389 (*val)->parent = key;
390 (*val)->handle = key->handle;
395 WERROR reg_key_del(REG_KEY *key)
398 if(!key) return WERR_INVALID_PARAM;
401 if(!key->handle->functions->del_key)
402 return WERR_NOT_SUPPORTED;
404 error = key->handle->functions->del_key(key);
405 if(!W_ERROR_IS_OK(error)) return error;
407 /* Invalidate cache */
408 key->cache_subkeys = NULL;
409 key->cache_subkeys_count = 0;
413 WERROR reg_sync(REG_KEY *h, const char *location)
415 if(!h->handle->functions->sync_key)
418 return h->handle->functions->sync_key(h, location);
421 WERROR reg_key_del_recursive(REG_KEY *key)
423 WERROR error = WERR_OK;
426 /* Delete all values for specified key */
427 for(i = 0; W_ERROR_IS_OK(error); i++) {
429 error = reg_key_get_value_by_index(key, i, &val);
430 if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
433 if(W_ERROR_IS_OK(error)) {
434 error = reg_val_del(val);
435 if(!W_ERROR_IS_OK(error)) return error;
441 /* Delete all keys below this one */
442 for(i = 0; W_ERROR_IS_OK(error); i++) {
445 error = reg_key_get_subkey_by_index(key, i, &subkey);
446 if(!W_ERROR_IS_OK(error)) return error;
448 error = reg_key_del_recursive(subkey);
449 if(!W_ERROR_IS_OK(error)) return error;
452 return reg_key_del(key);
455 WERROR reg_val_del(REG_VAL *val)
458 if (!val) return WERR_INVALID_PARAM;
460 if (!val->handle->functions->del_value) {
461 DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name));
462 return WERR_NOT_SUPPORTED;
465 error = val->handle->functions->del_value(val);
467 if(!W_ERROR_IS_OK(error)) return error;
469 val->parent->cache_values = NULL;
470 val->parent->cache_values_count = 0;
475 WERROR reg_key_add_name_recursive_abs(REG_HANDLE *handle, const char *name)
481 if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
482 else hivelength = strlen(name);
484 for(i = 0; W_ERROR_IS_OK(error); i++) {
485 error = reg_get_hive(handle, i, &hive);
486 if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) {
487 return reg_key_add_name_recursive(hive, name);
494 WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path)
496 REG_KEY *cur, *prevcur = parent;
498 /* FIXME: we should never write to a 'const char *' !!! --metze */
499 char *begin = (char *)path, *end;
502 end = strchr(begin, '\\');
505 error = reg_key_get_subkey_by_name(prevcur, begin, &cur);
507 /* Key is not there, add it */
508 if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
509 error = reg_key_add_name(prevcur, begin, 0, NULL, &cur);
510 if(!W_ERROR_IS_OK(error)) return error;
513 if(!W_ERROR_IS_OK(error)) {
526 WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, REG_KEY **newkey)
530 if (!parent) return WERR_INVALID_PARAM;
532 if (!parent->handle->functions->add_key) {
533 DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name));
534 return WERR_NOT_SUPPORTED;
537 error = parent->handle->functions->add_key(parent, name, access_mask, desc, newkey);
539 if(!W_ERROR_IS_OK(error)) return error;
541 (*newkey)->handle = parent->handle;
542 (*newkey)->backend_data = talloc_asprintf((*newkey)->mem_ctx, "%s\\%s", reg_key_get_path(parent), name);
544 parent->cache_subkeys = NULL;
545 parent->cache_subkeys_count = 0;
549 WERROR reg_val_update(REG_VAL *val, int type, void *data, int len)
553 /* A 'real' update function has preference */
554 if (val->handle->functions->update_value)
555 return val->handle->functions->update_value(val, type, data, len);
557 /* Otherwise, just remove and add again */
558 if (val->handle->functions->add_value &&
559 val->handle->functions->del_value) {
561 if(!W_ERROR_IS_OK(error = val->handle->functions->del_value(val)))
564 error = val->handle->functions->add_value(val->parent, val->name, type, data, len);
565 if(!W_ERROR_IS_OK(error)) return error;
566 memcpy(val, new, sizeof(REG_VAL));
567 val->parent->cache_values = NULL;
568 val->parent->cache_values_count = 0;
572 DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name));
573 return WERR_NOT_SUPPORTED;
576 void reg_free(REG_HANDLE *h)
578 if(!h->functions->close_registry) return;
580 h->functions->close_registry(h);
583 WERROR reg_get_hive(REG_HANDLE *h, int hivenum, REG_KEY **key)
587 if(h->functions->get_hive) {
588 ret = h->functions->get_hive(h, hivenum, key);
589 } else if(h->functions->open_key) {
590 if(hivenum == 0) ret = h->functions->open_key(h, hivenum, "", key);
591 else ret = WERR_NO_MORE_ITEMS;
593 DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key or get_hive method implemented\n", h->functions->name));
594 ret = WERR_NOT_SUPPORTED;
597 if(W_ERROR_IS_OK(ret)) {
600 (*key)->path = talloc_strdup((*key)->mem_ctx, (*key)->name);
602 (*key)->hive = hivenum;
608 WERROR reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen)
610 WERROR ret = WERR_OK;
611 if(!key->handle->functions->add_value)
612 return WERR_NOT_SUPPORTED;
614 ret = key->handle->functions->add_value(key, name, type, value, vallen);
616 if(!W_ERROR_IS_OK(ret)) return ret;
618 /* Invalidate the cache */
619 key->cache_values = NULL;
620 key->cache_values_count = 0;
624 WERROR reg_save(REG_HANDLE *h, const char *location)
627 return WERR_NOT_SUPPORTED;
630 WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent)
637 error = reg_get_hive(key->handle, key->hive, &root);
638 if(!W_ERROR_IS_OK(error)) return error;
640 parent_name = strdup(reg_key_get_path(key));
641 last = strrchr(parent_name, '\\');
644 SAFE_FREE(parent_name);
649 error = reg_open_key(root, parent_name, parent);
650 SAFE_FREE(parent_name);