s3-registry: add reg_querymultiplevalues() to reg_api.
[Samba.git] / source3 / registry / reg_api.c
blob1954fb50419b65b25cfdc90e18d02a7d11506510
1 /*
2 * Unix SMB/CIFS implementation.
3 * Virtual Windows Registry Layer
4 * Copyright (C) Volker Lendecke 2006
5 * Copyright (C) Michael Adam 2007-2008
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 /* Attempt to wrap the existing API in a more winreg.idl-like way */
24 * Here is a list of winreg.idl functions and corresponding implementations
25 * provided here:
27 * 0x00 winreg_OpenHKCR
28 * 0x01 winreg_OpenHKCU
29 * 0x02 winreg_OpenHKLM
30 * 0x03 winreg_OpenHKPD
31 * 0x04 winreg_OpenHKU
32 * 0x05 winreg_CloseKey
33 * 0x06 winreg_CreateKey reg_createkey
34 * 0x07 winreg_DeleteKey reg_deletekey
35 * 0x08 winreg_DeleteValue reg_deletevalue
36 * 0x09 winreg_EnumKey reg_enumkey
37 * 0x0a winreg_EnumValue reg_enumvalue
38 * 0x0b winreg_FlushKey
39 * 0x0c winreg_GetKeySecurity reg_getkeysecurity
40 * 0x0d winreg_LoadKey
41 * 0x0e winreg_NotifyChangeKeyValue
42 * 0x0f winreg_OpenKey reg_openkey
43 * 0x10 winreg_QueryInfoKey reg_queryinfokey
44 * 0x11 winreg_QueryValue reg_queryvalue
45 * 0x12 winreg_ReplaceKey
46 * 0x13 winreg_RestoreKey reg_restorekey
47 * 0x14 winreg_SaveKey reg_savekey
48 * 0x15 winreg_SetKeySecurity reg_setkeysecurity
49 * 0x16 winreg_SetValue reg_setvalue
50 * 0x17 winreg_UnLoadKey
51 * 0x18 winreg_InitiateSystemShutdown
52 * 0x19 winreg_AbortSystemShutdown
53 * 0x1a winreg_GetVersion reg_getversion
54 * 0x1b winreg_OpenHKCC
55 * 0x1c winreg_OpenHKDD
56 * 0x1d winreg_QueryMultipleValues
57 * 0x1e winreg_InitiateSystemShutdownEx
58 * 0x1f winreg_SaveKeyEx
59 * 0x20 winreg_OpenHKPT
60 * 0x21 winreg_OpenHKPN
61 * 0x22 winreg_QueryMultipleValues2
65 #include "includes.h"
66 #include "registry.h"
67 #include "reg_cachehook.h"
68 #include "regfio.h"
69 #include "reg_util_internal.h"
70 #include "reg_backend_db.h"
71 #include "reg_dispatcher.h"
72 #include "reg_util_marshalling.h"
73 #include "reg_objects.h"
74 #include "../librpc/gen_ndr/ndr_security.h"
76 #undef DBGC_CLASS
77 #define DBGC_CLASS DBGC_REGISTRY
80 /**********************************************************************
81 * Helper functions
82 **********************************************************************/
84 static WERROR fill_value_cache(struct registry_key *key)
86 WERROR werr;
88 if (key->values != NULL) {
89 if (!reg_values_need_update(key->key, key->values)) {
90 return WERR_OK;
94 werr = regval_ctr_init(key, &(key->values));
95 W_ERROR_NOT_OK_RETURN(werr);
97 if (fetch_reg_values(key->key, key->values) == -1) {
98 TALLOC_FREE(key->values);
99 return WERR_BADFILE;
102 return WERR_OK;
105 static WERROR fill_subkey_cache(struct registry_key *key)
107 WERROR werr;
109 if (key->subkeys != NULL) {
110 if (!reg_subkeys_need_update(key->key, key->subkeys)) {
111 return WERR_OK;
115 werr = regsubkey_ctr_init(key, &(key->subkeys));
116 W_ERROR_NOT_OK_RETURN(werr);
118 if (fetch_reg_keys(key->key, key->subkeys) == -1) {
119 TALLOC_FREE(key->subkeys);
120 return WERR_NO_MORE_ITEMS;
123 return WERR_OK;
126 static int regkey_destructor(struct registry_key_handle *key)
128 return regdb_close();
131 static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
132 struct registry_key *parent,
133 const char *name,
134 const struct nt_user_token *token,
135 uint32 access_desired,
136 struct registry_key **pregkey)
138 WERROR result = WERR_OK;
139 struct registry_key *regkey;
140 struct registry_key_handle *key;
141 struct regsubkey_ctr *subkeys = NULL;
143 DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
145 SMB_ASSERT(strchr(name, '\\') == NULL);
147 if (!(regkey = TALLOC_ZERO_P(mem_ctx, struct registry_key)) ||
148 !(regkey->token = dup_nt_token(regkey, token)) ||
149 !(regkey->key = TALLOC_ZERO_P(regkey, struct registry_key_handle)))
151 result = WERR_NOMEM;
152 goto done;
155 if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
156 goto done;
159 key = regkey->key;
160 talloc_set_destructor(key, regkey_destructor);
162 /* initialization */
164 key->type = REG_KEY_GENERIC;
166 if (name[0] == '\0') {
168 * Open a copy of the parent key
170 if (!parent) {
171 result = WERR_BADFILE;
172 goto done;
174 key->name = talloc_strdup(key, parent->key->name);
176 else {
178 * Normal subkey open
180 key->name = talloc_asprintf(key, "%s%s%s",
181 parent ? parent->key->name : "",
182 parent ? "\\": "",
183 name);
186 if (key->name == NULL) {
187 result = WERR_NOMEM;
188 goto done;
191 /* Tag this as a Performance Counter Key */
193 if( StrnCaseCmp(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
194 key->type = REG_KEY_HKPD;
196 /* Look up the table of registry I/O operations */
198 if ( !(key->ops = reghook_cache_find( key->name )) ) {
199 DEBUG(0,("reg_open_onelevel: Failed to assign "
200 "registry_ops to [%s]\n", key->name ));
201 result = WERR_BADFILE;
202 goto done;
205 /* check if the path really exists; failed is indicated by -1 */
206 /* if the subkey count failed, bail out */
208 result = regsubkey_ctr_init(key, &subkeys);
209 if (!W_ERROR_IS_OK(result)) {
210 goto done;
213 if ( fetch_reg_keys( key, subkeys ) == -1 ) {
214 result = WERR_BADFILE;
215 goto done;
218 TALLOC_FREE( subkeys );
220 if ( !regkey_access_check( key, access_desired, &key->access_granted,
221 token ) ) {
222 result = WERR_ACCESS_DENIED;
223 goto done;
226 *pregkey = regkey;
227 result = WERR_OK;
229 done:
230 if ( !W_ERROR_IS_OK(result) ) {
231 TALLOC_FREE(regkey);
234 return result;
237 WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive,
238 uint32 desired_access,
239 const struct nt_user_token *token,
240 struct registry_key **pkey)
242 SMB_ASSERT(hive != NULL);
243 SMB_ASSERT(hive[0] != '\0');
244 SMB_ASSERT(strchr(hive, '\\') == NULL);
246 return regkey_open_onelevel(mem_ctx, NULL, hive, token, desired_access,
247 pkey);
251 /**********************************************************************
252 * The API functions
253 **********************************************************************/
255 WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
256 const char *name, uint32 desired_access,
257 struct registry_key **pkey)
259 struct registry_key *direct_parent = parent;
260 WERROR err;
261 char *p, *path, *to_free;
262 size_t len;
264 if (!(path = SMB_STRDUP(name))) {
265 return WERR_NOMEM;
267 to_free = path;
269 len = strlen(path);
271 if ((len > 0) && (path[len-1] == '\\')) {
272 path[len-1] = '\0';
275 while ((p = strchr(path, '\\')) != NULL) {
276 char *name_component;
277 struct registry_key *tmp;
279 if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
280 err = WERR_NOMEM;
281 goto error;
284 err = regkey_open_onelevel(mem_ctx, direct_parent,
285 name_component, parent->token,
286 KEY_ENUMERATE_SUB_KEYS, &tmp);
287 SAFE_FREE(name_component);
289 if (!W_ERROR_IS_OK(err)) {
290 goto error;
292 if (direct_parent != parent) {
293 TALLOC_FREE(direct_parent);
296 direct_parent = tmp;
297 path = p+1;
300 err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
301 desired_access, pkey);
302 error:
303 if (direct_parent != parent) {
304 TALLOC_FREE(direct_parent);
306 SAFE_FREE(to_free);
307 return err;
310 WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
311 uint32 idx, char **name, NTTIME *last_write_time)
313 WERROR err;
315 if (!(key->key->access_granted & KEY_ENUMERATE_SUB_KEYS)) {
316 return WERR_ACCESS_DENIED;
319 if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
320 return err;
323 if (idx >= regsubkey_ctr_numkeys(key->subkeys)) {
324 return WERR_NO_MORE_ITEMS;
327 if (!(*name = talloc_strdup(mem_ctx,
328 regsubkey_ctr_specific_key(key->subkeys, idx))))
330 return WERR_NOMEM;
333 if (last_write_time) {
334 *last_write_time = 0;
337 return WERR_OK;
340 WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
341 uint32 idx, char **pname, struct registry_value **pval)
343 struct registry_value *val;
344 struct regval_blob *blob;
345 WERROR err;
347 if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
348 return WERR_ACCESS_DENIED;
351 if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
352 return err;
355 if (idx >= regval_ctr_numvals(key->values)) {
356 return WERR_NO_MORE_ITEMS;
359 blob = regval_ctr_specific_value(key->values, idx);
360 err = registry_pull_value(mem_ctx, &val,
361 regval_type(blob),
362 regval_data_p(blob),
363 regval_size(blob),
364 regval_size(blob));
365 if (!W_ERROR_IS_OK(err)) {
366 return err;
369 if (pname
370 && !(*pname = talloc_strdup(
371 mem_ctx, regval_name(blob)))) {
372 SAFE_FREE(val);
373 return WERR_NOMEM;
376 *pval = val;
377 return WERR_OK;
380 WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
381 const char *name, struct registry_value **pval)
383 WERROR err;
384 uint32 i;
386 if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
387 return WERR_ACCESS_DENIED;
390 if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
391 return err;
394 for (i=0; i < regval_ctr_numvals(key->values); i++) {
395 struct regval_blob *blob;
396 blob = regval_ctr_specific_value(key->values, i);
397 if (strequal(regval_name(blob), name)) {
398 return reg_enumvalue(mem_ctx, key, i, NULL, pval);
402 return WERR_BADFILE;
405 WERROR reg_querymultiplevalues(TALLOC_CTX *mem_ctx,
406 struct registry_key *key,
407 uint32_t num_names,
408 const char **names,
409 uint32_t *pnum_vals,
410 struct registry_value **pvals)
412 WERROR err;
413 uint32_t i, n, found = 0;
414 struct registry_value *vals;
416 if (num_names == 0) {
417 return WERR_OK;
420 if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
421 return WERR_ACCESS_DENIED;
424 if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
425 return err;
428 vals = talloc_zero_array(mem_ctx, struct registry_value, num_names);
429 if (vals == NULL) {
430 return WERR_NOMEM;
433 for (n=0; n < num_names; n++) {
434 for (i=0; i < regval_ctr_numvals(key->values); i++) {
435 struct regval_blob *blob;
436 blob = regval_ctr_specific_value(key->values, i);
437 if (strequal(regval_name(blob), names[n])) {
438 struct registry_value *v;
439 err = reg_enumvalue(mem_ctx, key, i, NULL, &v);
440 if (!W_ERROR_IS_OK(err)) {
441 return err;
443 vals[n] = *v;
444 found++;
449 *pvals = vals;
450 *pnum_vals = found;
452 return WERR_OK;
455 WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
456 uint32_t *max_subkeylen, uint32_t *max_subkeysize,
457 uint32_t *num_values, uint32_t *max_valnamelen,
458 uint32_t *max_valbufsize, uint32_t *secdescsize,
459 NTTIME *last_changed_time)
461 uint32 i, max_size;
462 size_t max_len;
463 TALLOC_CTX *mem_ctx;
464 WERROR err;
465 struct security_descriptor *secdesc;
467 if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
468 return WERR_ACCESS_DENIED;
471 if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
472 !W_ERROR_IS_OK(fill_value_cache(key))) {
473 return WERR_BADFILE;
476 max_len = 0;
477 for (i=0; i< regsubkey_ctr_numkeys(key->subkeys); i++) {
478 max_len = MAX(max_len,
479 strlen(regsubkey_ctr_specific_key(key->subkeys, i)));
482 *num_subkeys = regsubkey_ctr_numkeys(key->subkeys);
483 *max_subkeylen = max_len;
484 *max_subkeysize = 0; /* Class length? */
486 max_len = 0;
487 max_size = 0;
488 for (i=0; i < regval_ctr_numvals(key->values); i++) {
489 struct regval_blob *blob;
490 blob = regval_ctr_specific_value(key->values, i);
491 max_len = MAX(max_len, strlen(regval_name(blob)));
492 max_size = MAX(max_size, regval_size(blob));
495 *num_values = regval_ctr_numvals(key->values);
496 *max_valnamelen = max_len;
497 *max_valbufsize = max_size;
499 if (!(mem_ctx = talloc_new(key))) {
500 return WERR_NOMEM;
503 err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
504 if (!W_ERROR_IS_OK(err)) {
505 TALLOC_FREE(mem_ctx);
506 return err;
509 *secdescsize = ndr_size_security_descriptor(secdesc, 0);
510 TALLOC_FREE(mem_ctx);
512 *last_changed_time = 0;
514 return WERR_OK;
517 WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
518 const char *subkeypath, uint32 desired_access,
519 struct registry_key **pkey,
520 enum winreg_CreateAction *paction)
522 struct registry_key *key = parent;
523 struct registry_key *create_parent;
524 TALLOC_CTX *mem_ctx;
525 char *path, *end;
526 WERROR err;
528 if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
530 if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
531 err = WERR_NOMEM;
532 goto done;
535 while ((end = strchr(path, '\\')) != NULL) {
536 struct registry_key *tmp;
537 enum winreg_CreateAction action;
539 *end = '\0';
541 err = reg_createkey(mem_ctx, key, path,
542 KEY_ENUMERATE_SUB_KEYS, &tmp, &action);
543 if (!W_ERROR_IS_OK(err)) {
544 goto done;
547 if (key != parent) {
548 TALLOC_FREE(key);
551 key = tmp;
552 path = end+1;
556 * At this point, "path" contains the one-element subkey of "key". We
557 * can try to open it.
560 err = reg_openkey(ctx, key, path, desired_access, pkey);
561 if (W_ERROR_IS_OK(err)) {
562 if (paction != NULL) {
563 *paction = REG_OPENED_EXISTING_KEY;
565 goto done;
568 if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
570 * Something but "notfound" has happened, so bail out
572 goto done;
576 * We have to make a copy of the current key, as we opened it only
577 * with ENUM_SUBKEY access.
580 err = reg_openkey(mem_ctx, key, "", KEY_CREATE_SUB_KEY,
581 &create_parent);
582 if (!W_ERROR_IS_OK(err)) {
583 goto done;
587 * Actually create the subkey
590 err = fill_subkey_cache(create_parent);
591 if (!W_ERROR_IS_OK(err)) goto done;
593 err = create_reg_subkey(key->key, path);
594 W_ERROR_NOT_OK_GOTO_DONE(err);
597 * Now open the newly created key
600 err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
601 if (W_ERROR_IS_OK(err) && (paction != NULL)) {
602 *paction = REG_CREATED_NEW_KEY;
605 done:
606 TALLOC_FREE(mem_ctx);
607 return err;
610 WERROR reg_deletekey(struct registry_key *parent, const char *path)
612 WERROR err;
613 char *name, *end;
614 struct registry_key *tmp_key, *key;
615 TALLOC_CTX *mem_ctx = talloc_stackframe();
617 name = talloc_strdup(mem_ctx, path);
618 if (name == NULL) {
619 err = WERR_NOMEM;
620 goto done;
623 /* check if the key has subkeys */
624 err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
625 W_ERROR_NOT_OK_GOTO_DONE(err);
627 err = fill_subkey_cache(key);
628 W_ERROR_NOT_OK_GOTO_DONE(err);
630 if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
631 err = WERR_ACCESS_DENIED;
632 goto done;
635 /* no subkeys - proceed with delete */
636 end = strrchr(name, '\\');
637 if (end != NULL) {
638 *end = '\0';
640 err = reg_openkey(mem_ctx, parent, name,
641 KEY_CREATE_SUB_KEY, &tmp_key);
642 W_ERROR_NOT_OK_GOTO_DONE(err);
644 parent = tmp_key;
645 name = end+1;
648 if (name[0] == '\0') {
649 err = WERR_INVALID_PARAM;
650 goto done;
653 err = delete_reg_subkey(parent->key, name);
655 done:
656 TALLOC_FREE(mem_ctx);
657 return err;
660 WERROR reg_setvalue(struct registry_key *key, const char *name,
661 const struct registry_value *val)
663 WERROR err;
664 DATA_BLOB value_data;
665 int res;
667 if (!(key->key->access_granted & KEY_SET_VALUE)) {
668 return WERR_ACCESS_DENIED;
671 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
672 return err;
675 err = registry_push_value(key, val, &value_data);
676 if (!W_ERROR_IS_OK(err)) {
677 return err;
680 res = regval_ctr_addvalue(key->values, name, val->type,
681 value_data.data, value_data.length);
682 TALLOC_FREE(value_data.data);
684 if (res == 0) {
685 TALLOC_FREE(key->values);
686 return WERR_NOMEM;
689 if (!store_reg_values(key->key, key->values)) {
690 TALLOC_FREE(key->values);
691 return WERR_REG_IO_FAILURE;
694 return WERR_OK;
697 static WERROR reg_value_exists(struct registry_key *key, const char *name)
699 struct regval_blob *blob;
701 blob = regval_ctr_getvalue(key->values, name);
703 if (blob == NULL) {
704 return WERR_BADFILE;
705 } else {
706 return WERR_OK;
710 WERROR reg_deletevalue(struct registry_key *key, const char *name)
712 WERROR err;
714 if (!(key->key->access_granted & KEY_SET_VALUE)) {
715 return WERR_ACCESS_DENIED;
718 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
719 return err;
722 err = reg_value_exists(key, name);
723 if (!W_ERROR_IS_OK(err)) {
724 return err;
727 regval_ctr_delvalue(key->values, name);
729 if (!store_reg_values(key->key, key->values)) {
730 TALLOC_FREE(key->values);
731 return WERR_REG_IO_FAILURE;
734 return WERR_OK;
737 WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key,
738 struct security_descriptor **psecdesc)
740 return regkey_get_secdesc(mem_ctx, key->key, psecdesc);
743 WERROR reg_setkeysecurity(struct registry_key *key,
744 struct security_descriptor *psecdesc)
746 return regkey_set_secdesc(key->key, psecdesc);
749 WERROR reg_getversion(uint32_t *version)
751 if (version == NULL) {
752 return WERR_INVALID_PARAM;
755 *version = 0x00000005; /* Windows 2000 registry API version */
756 return WERR_OK;
759 /*******************************************************************
760 Note: topkeypat is the *full* path that this *key will be
761 loaded into (including the name of the key)
762 ********************************************************************/
764 static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
765 REGF_NK_REC *key)
767 REGF_NK_REC *subkey;
768 struct registry_key_handle registry_key;
769 struct regval_ctr *values;
770 struct regsubkey_ctr *subkeys;
771 int i;
772 char *path = NULL;
773 WERROR result = WERR_OK;
775 /* initialize the struct registry_key_handle structure */
777 registry_key.ops = reghook_cache_find(topkeypath);
778 if (!registry_key.ops) {
779 DEBUG(0, ("reg_load_tree: Failed to assign registry_ops "
780 "to [%s]\n", topkeypath));
781 return WERR_BADFILE;
784 registry_key.name = talloc_strdup(regfile->mem_ctx, topkeypath);
785 if (!registry_key.name) {
786 DEBUG(0, ("reg_load_tree: Talloc failed for reg_key.name!\n"));
787 return WERR_NOMEM;
790 /* now start parsing the values and subkeys */
792 result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
793 W_ERROR_NOT_OK_RETURN(result);
795 result = regval_ctr_init(subkeys, &values);
796 W_ERROR_NOT_OK_RETURN(result);
798 /* copy values into the struct regval_ctr */
800 for (i=0; i<key->num_values; i++) {
801 regval_ctr_addvalue(values, key->values[i].valuename,
802 key->values[i].type,
803 key->values[i].data,
804 (key->values[i].data_size & ~VK_DATA_IN_OFFSET));
807 /* copy subkeys into the struct regsubkey_ctr */
809 key->subkey_index = 0;
810 while ((subkey = regfio_fetch_subkey( regfile, key ))) {
811 result = regsubkey_ctr_addkey(subkeys, subkey->keyname);
812 if (!W_ERROR_IS_OK(result)) {
813 TALLOC_FREE(subkeys);
814 return result;
818 /* write this key and values out */
820 if (!store_reg_values(&registry_key, values)
821 || !store_reg_keys(&registry_key, subkeys))
823 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
824 result = WERR_REG_IO_FAILURE;
827 TALLOC_FREE(subkeys);
829 if (!W_ERROR_IS_OK(result)) {
830 return result;
833 /* now continue to load each subkey registry tree */
835 key->subkey_index = 0;
836 while ((subkey = regfio_fetch_subkey(regfile, key))) {
837 path = talloc_asprintf(regfile->mem_ctx,
838 "%s\\%s",
839 topkeypath,
840 subkey->keyname);
841 if (path == NULL) {
842 return WERR_NOMEM;
844 result = reg_load_tree(regfile, path, subkey);
845 if (!W_ERROR_IS_OK(result)) {
846 break;
850 return result;
853 /*******************************************************************
854 ********************************************************************/
856 static WERROR restore_registry_key(struct registry_key_handle *krecord,
857 const char *fname)
859 REGF_FILE *regfile;
860 REGF_NK_REC *rootkey;
861 WERROR result;
863 /* open the registry file....fail if the file already exists */
865 regfile = regfio_open(fname, (O_RDONLY), 0);
866 if (regfile == NULL) {
867 DEBUG(0, ("restore_registry_key: failed to open \"%s\" (%s)\n",
868 fname, strerror(errno)));
869 return ntstatus_to_werror(map_nt_error_from_unix(errno));
872 /* get the rootkey from the regf file and then load the tree
873 via recursive calls */
875 if (!(rootkey = regfio_rootkey(regfile))) {
876 regfio_close(regfile);
877 return WERR_REG_FILE_INVALID;
880 result = reg_load_tree(regfile, krecord->name, rootkey);
882 /* cleanup */
884 regfio_close(regfile);
886 return result;
889 WERROR reg_restorekey(struct registry_key *key, const char *fname)
891 return restore_registry_key(key->key, fname);
894 /********************************************************************
895 ********************************************************************/
897 static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
898 REGF_NK_REC *parent)
900 REGF_NK_REC *key;
901 struct regval_ctr *values;
902 struct regsubkey_ctr *subkeys;
903 int i, num_subkeys;
904 char *key_tmp = NULL;
905 char *keyname, *parentpath;
906 char *subkeypath = NULL;
907 char *subkeyname;
908 struct registry_key_handle registry_key;
909 WERROR result = WERR_OK;
910 struct security_descriptor *sec_desc = NULL;
912 if (!regfile) {
913 return WERR_GENERAL_FAILURE;
916 if (!keypath) {
917 return WERR_OBJECT_PATH_INVALID;
920 /* split up the registry key path */
922 key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
923 if (!key_tmp) {
924 return WERR_NOMEM;
926 if (!reg_split_key(key_tmp, &parentpath, &keyname)) {
927 return WERR_OBJECT_PATH_INVALID;
930 if (!keyname) {
931 keyname = parentpath;
934 /* we need a registry_key_handle object here to enumerate subkeys and values */
936 ZERO_STRUCT(registry_key);
938 registry_key.name = talloc_strdup(regfile->mem_ctx, keypath);
939 if (registry_key.name == NULL) {
940 return WERR_NOMEM;
943 registry_key.ops = reghook_cache_find(registry_key.name);
944 if (registry_key.ops == NULL) {
945 return WERR_BADFILE;
948 /* lookup the values and subkeys */
950 result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
951 W_ERROR_NOT_OK_RETURN(result);
953 result = regval_ctr_init(subkeys, &values);
954 W_ERROR_NOT_OK_RETURN(result);
956 fetch_reg_keys(&registry_key, subkeys);
957 fetch_reg_values(&registry_key, values);
959 result = regkey_get_secdesc(regfile->mem_ctx, &registry_key, &sec_desc);
960 if (!W_ERROR_IS_OK(result)) {
961 goto done;
964 /* write out this key */
966 key = regfio_write_key(regfile, keyname, values, subkeys, sec_desc,
967 parent);
968 if (key == NULL) {
969 result = WERR_CAN_NOT_COMPLETE;
970 goto done;
973 /* write each one of the subkeys out */
975 num_subkeys = regsubkey_ctr_numkeys(subkeys);
976 for (i=0; i<num_subkeys; i++) {
977 subkeyname = regsubkey_ctr_specific_key(subkeys, i);
978 subkeypath = talloc_asprintf(regfile->mem_ctx, "%s\\%s",
979 keypath, subkeyname);
980 if (subkeypath == NULL) {
981 result = WERR_NOMEM;
982 goto done;
984 result = reg_write_tree(regfile, subkeypath, key);
985 if (!W_ERROR_IS_OK(result))
986 goto done;
989 DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath));
991 done:
992 TALLOC_FREE(subkeys);
993 TALLOC_FREE(registry_key.name);
995 return result;
998 static WERROR backup_registry_key(struct registry_key_handle *krecord,
999 const char *fname)
1001 REGF_FILE *regfile;
1002 WERROR result;
1004 /* open the registry file....fail if the file already exists */
1006 regfile = regfio_open(fname, (O_RDWR|O_CREAT|O_EXCL),
1007 (S_IREAD|S_IWRITE));
1008 if (regfile == NULL) {
1009 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
1010 fname, strerror(errno) ));
1011 return ntstatus_to_werror(map_nt_error_from_unix(errno));
1014 /* write the registry tree to the file */
1016 result = reg_write_tree(regfile, krecord->name, NULL);
1018 /* cleanup */
1020 regfio_close(regfile);
1022 return result;
1025 WERROR reg_savekey(struct registry_key *key, const char *fname)
1027 return backup_registry_key(key->key, fname);
1030 /**********************************************************************
1031 * Higher level utility functions
1032 **********************************************************************/
1034 WERROR reg_deleteallvalues(struct registry_key *key)
1036 WERROR err;
1037 int i;
1039 if (!(key->key->access_granted & KEY_SET_VALUE)) {
1040 return WERR_ACCESS_DENIED;
1043 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
1044 return err;
1047 for (i=0; i < regval_ctr_numvals(key->values); i++) {
1048 struct regval_blob *blob;
1049 blob = regval_ctr_specific_value(key->values, i);
1050 regval_ctr_delvalue(key->values, regval_name(blob));
1053 if (!store_reg_values(key->key, key->values)) {
1054 TALLOC_FREE(key->values);
1055 return WERR_REG_IO_FAILURE;
1058 return WERR_OK;
1062 * Utility function to open a complete registry path including the hive prefix.
1065 WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
1066 uint32 desired_access, const struct nt_user_token *token,
1067 struct registry_key **pkey)
1069 struct registry_key *hive, *key;
1070 char *path, *p;
1071 WERROR err;
1073 if (!(path = SMB_STRDUP(orig_path))) {
1074 return WERR_NOMEM;
1077 p = strchr(path, '\\');
1079 if ((p == NULL) || (p[1] == '\0')) {
1081 * No key behind the hive, just return the hive
1084 err = reg_openhive(mem_ctx, path, desired_access, token,
1085 &hive);
1086 if (!W_ERROR_IS_OK(err)) {
1087 SAFE_FREE(path);
1088 return err;
1090 SAFE_FREE(path);
1091 *pkey = hive;
1092 return WERR_OK;
1095 *p = '\0';
1097 err = reg_openhive(mem_ctx, path, KEY_ENUMERATE_SUB_KEYS, token,
1098 &hive);
1099 if (!W_ERROR_IS_OK(err)) {
1100 SAFE_FREE(path);
1101 return err;
1104 err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
1106 TALLOC_FREE(hive);
1107 SAFE_FREE(path);
1109 if (!W_ERROR_IS_OK(err)) {
1110 return err;
1113 *pkey = key;
1114 return WERR_OK;
1118 * Utility function to delete a registry key with all its subkeys.
1119 * Note that reg_deletekey returns ACCESS_DENIED when called on a
1120 * key that has subkeys.
1122 static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
1123 struct registry_key *parent,
1124 const char *path,
1125 bool del_key)
1127 TALLOC_CTX *mem_ctx = NULL;
1128 WERROR werr = WERR_OK;
1129 struct registry_key *key;
1130 char *subkey_name = NULL;
1131 uint32 i;
1133 mem_ctx = talloc_new(ctx);
1134 if (mem_ctx == NULL) {
1135 werr = WERR_NOMEM;
1136 goto done;
1139 /* recurse through subkeys first */
1140 werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
1141 if (!W_ERROR_IS_OK(werr)) {
1142 goto done;
1145 werr = fill_subkey_cache(key);
1146 W_ERROR_NOT_OK_GOTO_DONE(werr);
1149 * loop from top to bottom for perfomance:
1150 * this way, we need to rehash the regsubkey containers less
1152 for (i = regsubkey_ctr_numkeys(key->subkeys) ; i > 0; i--) {
1153 subkey_name = regsubkey_ctr_specific_key(key->subkeys, i-1);
1154 werr = reg_deletekey_recursive_internal(mem_ctx, key,
1155 subkey_name,
1156 true);
1157 W_ERROR_NOT_OK_GOTO_DONE(werr);
1160 if (del_key) {
1161 /* now delete the actual key */
1162 werr = reg_deletekey(parent, path);
1165 done:
1166 TALLOC_FREE(mem_ctx);
1167 return werr;
1170 static WERROR reg_deletekey_recursive_trans(TALLOC_CTX *ctx,
1171 struct registry_key *parent,
1172 const char *path,
1173 bool del_key)
1175 WERROR werr;
1177 werr = regdb_transaction_start();
1178 if (!W_ERROR_IS_OK(werr)) {
1179 DEBUG(0, ("reg_deletekey_recursive_trans: "
1180 "error starting transaction: %s\n",
1181 win_errstr(werr)));
1182 return werr;
1185 werr = reg_deletekey_recursive_internal(ctx, parent, path, del_key);
1187 if (!W_ERROR_IS_OK(werr)) {
1188 DEBUG(1, (__location__ " failed to delete key '%s' from key "
1189 "'%s': %s\n", path, parent->key->name,
1190 win_errstr(werr)));
1191 werr = regdb_transaction_cancel();
1192 if (!W_ERROR_IS_OK(werr)) {
1193 DEBUG(0, ("reg_deletekey_recursive_trans: "
1194 "error cancelling transaction: %s\n",
1195 win_errstr(werr)));
1197 } else {
1198 werr = regdb_transaction_commit();
1199 if (!W_ERROR_IS_OK(werr)) {
1200 DEBUG(0, ("reg_deletekey_recursive_trans: "
1201 "error committing transaction: %s\n",
1202 win_errstr(werr)));
1206 return werr;
1209 WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
1210 struct registry_key *parent,
1211 const char *path)
1213 return reg_deletekey_recursive_trans(ctx, parent, path, true);
1216 WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
1217 struct registry_key *parent,
1218 const char *path)
1220 return reg_deletekey_recursive_trans(ctx, parent, path, false);
1223 #if 0
1224 /* these two functions are unused. */
1227 * Utility function to create a registry key without opening the hive
1228 * before. Assumes the hive already exists.
1231 WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path,
1232 uint32 desired_access,
1233 const struct nt_user_token *token,
1234 enum winreg_CreateAction *paction,
1235 struct registry_key **pkey)
1237 struct registry_key *hive;
1238 char *path, *p;
1239 WERROR err;
1241 if (!(path = SMB_STRDUP(orig_path))) {
1242 return WERR_NOMEM;
1245 p = strchr(path, '\\');
1247 if ((p == NULL) || (p[1] == '\0')) {
1249 * No key behind the hive, just return the hive
1252 err = reg_openhive(mem_ctx, path, desired_access, token,
1253 &hive);
1254 if (!W_ERROR_IS_OK(err)) {
1255 SAFE_FREE(path);
1256 return err;
1258 SAFE_FREE(path);
1259 *pkey = hive;
1260 *paction = REG_OPENED_EXISTING_KEY;
1261 return WERR_OK;
1264 *p = '\0';
1266 err = reg_openhive(mem_ctx, path,
1267 (strchr(p+1, '\\') != NULL) ?
1268 KEY_ENUMERATE_SUB_KEYS : KEY_CREATE_SUB_KEY,
1269 token, &hive);
1270 if (!W_ERROR_IS_OK(err)) {
1271 SAFE_FREE(path);
1272 return err;
1275 err = reg_createkey(mem_ctx, hive, p+1, desired_access, pkey, paction);
1276 SAFE_FREE(path);
1277 TALLOC_FREE(hive);
1278 return err;
1282 * Utility function to create a registry key without opening the hive
1283 * before. Will not delete a hive.
1286 WERROR reg_delete_path(const struct nt_user_token *token,
1287 const char *orig_path)
1289 struct registry_key *hive;
1290 char *path, *p;
1291 WERROR err;
1293 if (!(path = SMB_STRDUP(orig_path))) {
1294 return WERR_NOMEM;
1297 p = strchr(path, '\\');
1299 if ((p == NULL) || (p[1] == '\0')) {
1300 SAFE_FREE(path);
1301 return WERR_INVALID_PARAM;
1304 *p = '\0';
1306 err = reg_openhive(NULL, path,
1307 (strchr(p+1, '\\') != NULL) ?
1308 KEY_ENUMERATE_SUB_KEYS : KEY_CREATE_SUB_KEY,
1309 token, &hive);
1310 if (!W_ERROR_IS_OK(err)) {
1311 SAFE_FREE(path);
1312 return err;
1315 err = reg_deletekey(hive, p+1);
1316 SAFE_FREE(path);
1317 TALLOC_FREE(hive);
1318 return err;
1320 #endif /* #if 0 */