source: branches/samba-3.2.x/source/registry/reg_api.c

Last change on this file was 272, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 to 3.2.12

File size: 28.9 KB
Line 
1/*
2 * Unix SMB/CIFS implementation.
3 * Virtual Windows Registry Layer
4 * Copyright (C) Volker Lendecke 2006
5 * Copyright (C) Michael Adam 2007-2008
6 *
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.
11 *
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.
16 *
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/>.
19 */
20
21/* Attempt to wrap the existing API in a more winreg.idl-like way */
22
23/*
24 * Here is a list of winreg.idl functions and corresponding implementations
25 * provided here:
26 *
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
62 *
63 */
64
65#include "includes.h"
66#include "regfio.h"
67
68#undef DBGC_CLASS
69#define DBGC_CLASS DBGC_REGISTRY
70
71
72/**********************************************************************
73 * Helper functions
74 **********************************************************************/
75
76static WERROR fill_value_cache(struct registry_key *key)
77{
78 if (key->values != NULL) {
79 if (!reg_values_need_update(key->key, key->values)) {
80 return WERR_OK;
81 }
82 }
83
84 if (!(key->values = TALLOC_ZERO_P(key, REGVAL_CTR))) {
85 return WERR_NOMEM;
86 }
87 if (fetch_reg_values(key->key, key->values) == -1) {
88 TALLOC_FREE(key->values);
89 return WERR_BADFILE;
90 }
91
92 return WERR_OK;
93}
94
95static WERROR fill_subkey_cache(struct registry_key *key)
96{
97 if (key->subkeys != NULL) {
98 if (!reg_subkeys_need_update(key->key, key->subkeys)) {
99 return WERR_OK;
100 }
101 }
102
103 if (!(key->subkeys = TALLOC_ZERO_P(key, REGSUBKEY_CTR))) {
104 return WERR_NOMEM;
105 }
106
107 if (fetch_reg_keys(key->key, key->subkeys) == -1) {
108 TALLOC_FREE(key->subkeys);
109 return WERR_NO_MORE_ITEMS;
110 }
111
112 return WERR_OK;
113}
114
115static int regkey_destructor(REGISTRY_KEY *key)
116{
117 return regdb_close();
118}
119
120static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
121 struct registry_key *parent,
122 const char *name,
123 const struct nt_user_token *token,
124 uint32 access_desired,
125 struct registry_key **pregkey)
126{
127 WERROR result = WERR_OK;
128 struct registry_key *regkey;
129 REGISTRY_KEY *key;
130 REGSUBKEY_CTR *subkeys = NULL;
131
132 DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
133
134 SMB_ASSERT(strchr(name, '\\') == NULL);
135
136 if (!(regkey = TALLOC_ZERO_P(mem_ctx, struct registry_key)) ||
137 !(regkey->token = dup_nt_token(regkey, token)) ||
138 !(regkey->key = TALLOC_ZERO_P(regkey, REGISTRY_KEY))) {
139 result = WERR_NOMEM;
140 goto done;
141 }
142
143 if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
144 goto done;
145 }
146
147 key = regkey->key;
148 talloc_set_destructor(key, regkey_destructor);
149
150 /* initialization */
151
152 key->type = REG_KEY_GENERIC;
153
154 if (name[0] == '\0') {
155 /*
156 * Open a copy of the parent key
157 */
158 if (!parent) {
159 result = WERR_BADFILE;
160 goto done;
161 }
162 key->name = talloc_strdup(key, parent->key->name);
163 }
164 else {
165 /*
166 * Normal subkey open
167 */
168 key->name = talloc_asprintf(key, "%s%s%s",
169 parent ? parent->key->name : "",
170 parent ? "\\": "",
171 name);
172 }
173
174 if (key->name == NULL) {
175 result = WERR_NOMEM;
176 goto done;
177 }
178
179 /* Tag this as a Performance Counter Key */
180
181 if( StrnCaseCmp(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
182 key->type = REG_KEY_HKPD;
183
184 /* Look up the table of registry I/O operations */
185
186 if ( !(key->ops = reghook_cache_find( key->name )) ) {
187 DEBUG(0,("reg_open_onelevel: Failed to assign "
188 "REGISTRY_OPS to [%s]\n", key->name ));
189 result = WERR_BADFILE;
190 goto done;
191 }
192
193 /* check if the path really exists; failed is indicated by -1 */
194 /* if the subkey count failed, bail out */
195
196 if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
197 result = WERR_NOMEM;
198 goto done;
199 }
200
201 if ( fetch_reg_keys( key, subkeys ) == -1 ) {
202 result = WERR_BADFILE;
203 goto done;
204 }
205
206 TALLOC_FREE( subkeys );
207
208 if ( !regkey_access_check( key, access_desired, &key->access_granted,
209 token ) ) {
210 result = WERR_ACCESS_DENIED;
211 goto done;
212 }
213
214 *pregkey = regkey;
215 result = WERR_OK;
216
217done:
218 if ( !W_ERROR_IS_OK(result) ) {
219 TALLOC_FREE(regkey);
220 }
221
222 return result;
223}
224
225WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive,
226 uint32 desired_access,
227 const struct nt_user_token *token,
228 struct registry_key **pkey)
229{
230 SMB_ASSERT(hive != NULL);
231 SMB_ASSERT(hive[0] != '\0');
232 SMB_ASSERT(strchr(hive, '\\') == NULL);
233
234 return regkey_open_onelevel(mem_ctx, NULL, hive, token, desired_access,
235 pkey);
236}
237
238
239/**********************************************************************
240 * The API functions
241 **********************************************************************/
242
243WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
244 const char *name, uint32 desired_access,
245 struct registry_key **pkey)
246{
247 struct registry_key *direct_parent = parent;
248 WERROR err;
249 char *p, *path, *to_free;
250 size_t len;
251
252 if (!(path = SMB_STRDUP(name))) {
253 return WERR_NOMEM;
254 }
255 to_free = path;
256
257 len = strlen(path);
258
259 if ((len > 0) && (path[len-1] == '\\')) {
260 path[len-1] = '\0';
261 }
262
263 while ((p = strchr(path, '\\')) != NULL) {
264 char *name_component;
265 struct registry_key *tmp;
266
267 if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
268 err = WERR_NOMEM;
269 goto error;
270 }
271
272 err = regkey_open_onelevel(mem_ctx, direct_parent,
273 name_component, parent->token,
274 SEC_RIGHTS_ENUM_SUBKEYS, &tmp);
275 SAFE_FREE(name_component);
276
277 if (!W_ERROR_IS_OK(err)) {
278 goto error;
279 }
280 if (direct_parent != parent) {
281 TALLOC_FREE(direct_parent);
282 }
283
284 direct_parent = tmp;
285 path = p+1;
286 }
287
288 err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
289 desired_access, pkey);
290 error:
291 if (direct_parent != parent) {
292 TALLOC_FREE(direct_parent);
293 }
294 SAFE_FREE(to_free);
295 return err;
296}
297
298WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
299 uint32 idx, char **name, NTTIME *last_write_time)
300{
301 WERROR err;
302
303 if (!(key->key->access_granted & SEC_RIGHTS_ENUM_SUBKEYS)) {
304 return WERR_ACCESS_DENIED;
305 }
306
307 if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
308 return err;
309 }
310
311 if (idx >= key->subkeys->num_subkeys) {
312 return WERR_NO_MORE_ITEMS;
313 }
314
315 if (!(*name = talloc_strdup(mem_ctx, key->subkeys->subkeys[idx]))) {
316 return WERR_NOMEM;
317 }
318
319 if (last_write_time) {
320 *last_write_time = 0;
321 }
322
323 return WERR_OK;
324}
325
326WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
327 uint32 idx, char **pname, struct registry_value **pval)
328{
329 struct registry_value *val;
330 WERROR err;
331
332 if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
333 return WERR_ACCESS_DENIED;
334 }
335
336 if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
337 return err;
338 }
339
340 if (idx >= key->values->num_values) {
341 return WERR_NO_MORE_ITEMS;
342 }
343
344 err = registry_pull_value(mem_ctx, &val,
345 key->values->values[idx]->type,
346 key->values->values[idx]->data_p,
347 key->values->values[idx]->size,
348 key->values->values[idx]->size);
349 if (!W_ERROR_IS_OK(err)) {
350 return err;
351 }
352
353 if (pname
354 && !(*pname = talloc_strdup(
355 mem_ctx, key->values->values[idx]->valuename))) {
356 SAFE_FREE(val);
357 return WERR_NOMEM;
358 }
359
360 *pval = val;
361 return WERR_OK;
362}
363
364WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
365 const char *name, struct registry_value **pval)
366{
367 WERROR err;
368 uint32 i;
369
370 if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
371 return WERR_ACCESS_DENIED;
372 }
373
374 if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
375 return err;
376 }
377
378 for (i=0; i<key->values->num_values; i++) {
379 if (strequal(key->values->values[i]->valuename, name)) {
380 return reg_enumvalue(mem_ctx, key, i, NULL, pval);
381 }
382 }
383
384 return WERR_BADFILE;
385}
386
387WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
388 uint32_t *max_subkeylen, uint32_t *max_subkeysize,
389 uint32_t *num_values, uint32_t *max_valnamelen,
390 uint32_t *max_valbufsize, uint32_t *secdescsize,
391 NTTIME *last_changed_time)
392{
393 uint32 i, max_size;
394 size_t max_len;
395 TALLOC_CTX *mem_ctx;
396 WERROR err;
397 struct security_descriptor *secdesc;
398
399 if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
400 return WERR_ACCESS_DENIED;
401 }
402
403 if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
404 !W_ERROR_IS_OK(fill_value_cache(key))) {
405 return WERR_BADFILE;
406 }
407
408 max_len = 0;
409 for (i=0; i<key->subkeys->num_subkeys; i++) {
410 max_len = MAX(max_len, strlen(key->subkeys->subkeys[i]));
411 }
412
413 *num_subkeys = key->subkeys->num_subkeys;
414 *max_subkeylen = max_len;
415 *max_subkeysize = 0; /* Class length? */
416
417 max_len = 0;
418 max_size = 0;
419 for (i=0; i<key->values->num_values; i++) {
420 max_len = MAX(max_len,
421 strlen(key->values->values[i]->valuename));
422 max_size = MAX(max_size, key->values->values[i]->size);
423 }
424
425 *num_values = key->values->num_values;
426 *max_valnamelen = max_len;
427 *max_valbufsize = max_size;
428
429 if (!(mem_ctx = talloc_new(key))) {
430 return WERR_NOMEM;
431 }
432
433 err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
434 if (!W_ERROR_IS_OK(err)) {
435 TALLOC_FREE(mem_ctx);
436 return err;
437 }
438
439 *secdescsize = ndr_size_security_descriptor(secdesc, 0);
440 TALLOC_FREE(mem_ctx);
441
442 *last_changed_time = 0;
443
444 return WERR_OK;
445}
446
447WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
448 const char *subkeypath, uint32 desired_access,
449 struct registry_key **pkey,
450 enum winreg_CreateAction *paction)
451{
452 struct registry_key *key = parent;
453 struct registry_key *create_parent;
454 TALLOC_CTX *mem_ctx;
455 char *path, *end;
456 WERROR err;
457
458 /*
459 * We must refuse to handle subkey-paths containing
460 * a '/' character because at a lower level, after
461 * normalization, '/' is treated as a key separator
462 * just like '\\'.
463 */
464 if (strchr(subkeypath, '/') != NULL) {
465 return WERR_INVALID_PARAM;
466 }
467
468 if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
469
470 if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
471 err = WERR_NOMEM;
472 goto done;
473 }
474
475 while ((end = strchr(path, '\\')) != NULL) {
476 struct registry_key *tmp;
477 enum winreg_CreateAction action;
478
479 *end = '\0';
480
481 err = reg_createkey(mem_ctx, key, path,
482 SEC_RIGHTS_ENUM_SUBKEYS, &tmp, &action);
483 if (!W_ERROR_IS_OK(err)) {
484 goto done;
485 }
486
487 if (key != parent) {
488 TALLOC_FREE(key);
489 }
490
491 key = tmp;
492 path = end+1;
493 }
494
495 /*
496 * At this point, "path" contains the one-element subkey of "key". We
497 * can try to open it.
498 */
499
500 err = reg_openkey(ctx, key, path, desired_access, pkey);
501 if (W_ERROR_IS_OK(err)) {
502 if (paction != NULL) {
503 *paction = REG_OPENED_EXISTING_KEY;
504 }
505 goto done;
506 }
507
508 if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
509 /*
510 * Something but "notfound" has happened, so bail out
511 */
512 goto done;
513 }
514
515 /*
516 * We have to make a copy of the current key, as we opened it only
517 * with ENUM_SUBKEY access.
518 */
519
520 err = reg_openkey(mem_ctx, key, "", SEC_RIGHTS_CREATE_SUBKEY,
521 &create_parent);
522 if (!W_ERROR_IS_OK(err)) {
523 goto done;
524 }
525
526 /*
527 * Actually create the subkey
528 */
529
530 err = fill_subkey_cache(create_parent);
531 if (!W_ERROR_IS_OK(err)) goto done;
532
533 err = regsubkey_ctr_addkey(create_parent->subkeys, path);
534 if (!W_ERROR_IS_OK(err)) goto done;
535
536 if (!store_reg_keys(create_parent->key, create_parent->subkeys)) {
537 TALLOC_FREE(create_parent->subkeys);
538 err = WERR_REG_IO_FAILURE;
539 goto done;
540 }
541
542 /*
543 * Now open the newly created key
544 */
545
546 err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
547 if (W_ERROR_IS_OK(err) && (paction != NULL)) {
548 *paction = REG_CREATED_NEW_KEY;
549 }
550
551 done:
552 TALLOC_FREE(mem_ctx);
553 return err;
554}
555
556WERROR reg_deletekey(struct registry_key *parent, const char *path)
557{
558 WERROR err;
559 TALLOC_CTX *mem_ctx;
560 char *name, *end;
561 int num_subkeys;
562 struct registry_key *tmp_key, *key;
563
564 if (!(mem_ctx = talloc_init("reg_createkey"))) return WERR_NOMEM;
565
566 if (!(name = talloc_strdup(mem_ctx, path))) {
567 err = WERR_NOMEM;
568 goto error;
569 }
570
571 /* check if the key has subkeys */
572 err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
573 if (!W_ERROR_IS_OK(err)) {
574 goto error;
575 }
576 if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
577 goto error;
578 }
579 if (key->subkeys->num_subkeys > 0) {
580 err = WERR_ACCESS_DENIED;
581 goto error;
582 }
583
584 /* no subkeys - proceed with delete */
585 if ((end = strrchr(name, '\\')) != NULL) {
586 *end = '\0';
587
588 err = reg_openkey(mem_ctx, parent, name,
589 SEC_RIGHTS_CREATE_SUBKEY, &tmp_key);
590 if (!W_ERROR_IS_OK(err)) {
591 goto error;
592 }
593
594 parent = tmp_key;
595 name = end+1;
596 }
597
598 if (name[0] == '\0') {
599 err = WERR_INVALID_PARAM;
600 goto error;
601 }
602
603 if (!W_ERROR_IS_OK(err = fill_subkey_cache(parent))) {
604 goto error;
605 }
606
607 num_subkeys = parent->subkeys->num_subkeys;
608
609 if (regsubkey_ctr_delkey(parent->subkeys, name) == num_subkeys) {
610 err = WERR_BADFILE;
611 goto error;
612 }
613
614 if (!store_reg_keys(parent->key, parent->subkeys)) {
615 TALLOC_FREE(parent->subkeys);
616 err = WERR_REG_IO_FAILURE;
617 goto error;
618 }
619
620 regkey_set_secdesc(key->key, NULL);
621
622 err = WERR_OK;
623
624 error:
625 TALLOC_FREE(mem_ctx);
626 return err;
627}
628
629WERROR reg_setvalue(struct registry_key *key, const char *name,
630 const struct registry_value *val)
631{
632 WERROR err;
633 DATA_BLOB value_data;
634 int res;
635
636 if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
637 return WERR_ACCESS_DENIED;
638 }
639
640 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
641 return err;
642 }
643
644 err = registry_push_value(key, val, &value_data);
645 if (!W_ERROR_IS_OK(err)) {
646 return err;
647 }
648
649 res = regval_ctr_addvalue(key->values, name, val->type,
650 (char *)value_data.data, value_data.length);
651 TALLOC_FREE(value_data.data);
652
653 if (res == 0) {
654 TALLOC_FREE(key->values);
655 return WERR_NOMEM;
656 }
657
658 if (!store_reg_values(key->key, key->values)) {
659 TALLOC_FREE(key->values);
660 return WERR_REG_IO_FAILURE;
661 }
662
663 return WERR_OK;
664}
665
666static WERROR reg_value_exists(struct registry_key *key, const char *name)
667{
668 int i;
669
670 for (i=0; i<key->values->num_values; i++) {
671 if (strequal(key->values->values[i]->valuename, name)) {
672 return WERR_OK;
673 }
674 }
675
676 return WERR_BADFILE;
677}
678
679WERROR reg_deletevalue(struct registry_key *key, const char *name)
680{
681 WERROR err;
682
683 if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
684 return WERR_ACCESS_DENIED;
685 }
686
687 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
688 return err;
689 }
690
691 err = reg_value_exists(key, name);
692 if (!W_ERROR_IS_OK(err)) {
693 return err;
694 }
695
696 regval_ctr_delvalue(key->values, name);
697
698 if (!store_reg_values(key->key, key->values)) {
699 TALLOC_FREE(key->values);
700 return WERR_REG_IO_FAILURE;
701 }
702
703 return WERR_OK;
704}
705
706WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key,
707 struct security_descriptor **psecdesc)
708{
709 return regkey_get_secdesc(mem_ctx, key->key, psecdesc);
710}
711
712WERROR reg_setkeysecurity(struct registry_key *key,
713 struct security_descriptor *psecdesc)
714{
715 return regkey_set_secdesc(key->key, psecdesc);
716}
717
718WERROR reg_getversion(uint32_t *version)
719{
720 if (version == NULL) {
721 return WERR_INVALID_PARAM;
722 }
723
724 *version = 0x00000005; /* Windows 2000 registry API version */
725 return WERR_OK;
726}
727
728/*******************************************************************
729 Note: topkeypat is the *full* path that this *key will be
730 loaded into (including the name of the key)
731 ********************************************************************/
732
733static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
734 REGF_NK_REC *key)
735{
736 REGF_NK_REC *subkey;
737 REGISTRY_KEY registry_key;
738 REGVAL_CTR *values;
739 REGSUBKEY_CTR *subkeys;
740 int i;
741 char *path = NULL;
742 WERROR result = WERR_OK;
743
744 /* initialize the REGISTRY_KEY structure */
745
746 registry_key.ops = reghook_cache_find(topkeypath);
747 if (!registry_key.ops) {
748 DEBUG(0, ("reg_load_tree: Failed to assign REGISTRY_OPS "
749 "to [%s]\n", topkeypath));
750 return WERR_BADFILE;
751 }
752
753 registry_key.name = talloc_strdup(regfile->mem_ctx, topkeypath);
754 if (!registry_key.name) {
755 DEBUG(0, ("reg_load_tree: Talloc failed for reg_key.name!\n"));
756 return WERR_NOMEM;
757 }
758
759 /* now start parsing the values and subkeys */
760
761 subkeys = TALLOC_ZERO_P(regfile->mem_ctx, REGSUBKEY_CTR);
762 if (subkeys == NULL) {
763 return WERR_NOMEM;
764 }
765
766 values = TALLOC_ZERO_P(subkeys, REGVAL_CTR);
767 if (values == NULL) {
768 return WERR_NOMEM;
769 }
770
771 /* copy values into the REGVAL_CTR */
772
773 for (i=0; i<key->num_values; i++) {
774 regval_ctr_addvalue(values, key->values[i].valuename,
775 key->values[i].type,
776 (char*)key->values[i].data,
777 (key->values[i].data_size & ~VK_DATA_IN_OFFSET));
778 }
779
780 /* copy subkeys into the REGSUBKEY_CTR */
781
782 key->subkey_index = 0;
783 while ((subkey = regfio_fetch_subkey( regfile, key ))) {
784 result = regsubkey_ctr_addkey(subkeys, subkey->keyname);
785 if (!W_ERROR_IS_OK(result)) {
786 TALLOC_FREE(subkeys);
787 return result;
788 }
789 }
790
791 /* write this key and values out */
792
793 if (!store_reg_values(&registry_key, values)
794 || !store_reg_keys(&registry_key, subkeys))
795 {
796 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
797 result = WERR_REG_IO_FAILURE;
798 }
799
800 TALLOC_FREE(subkeys);
801
802 if (!W_ERROR_IS_OK(result)) {
803 return result;
804 }
805
806 /* now continue to load each subkey registry tree */
807
808 key->subkey_index = 0;
809 while ((subkey = regfio_fetch_subkey(regfile, key))) {
810 path = talloc_asprintf(regfile->mem_ctx,
811 "%s\\%s",
812 topkeypath,
813 subkey->keyname);
814 if (path == NULL) {
815 return WERR_NOMEM;
816 }
817 result = reg_load_tree(regfile, path, subkey);
818 if (!W_ERROR_IS_OK(result)) {
819 break;
820 }
821 }
822
823 return result;
824}
825
826/*******************************************************************
827 ********************************************************************/
828
829static WERROR restore_registry_key(REGISTRY_KEY *krecord, const char *fname)
830{
831 REGF_FILE *regfile;
832 REGF_NK_REC *rootkey;
833 WERROR result;
834
835 /* open the registry file....fail if the file already exists */
836
837 regfile = regfio_open(fname, (O_RDONLY), 0);
838 if (regfile == NULL) {
839 DEBUG(0, ("restore_registry_key: failed to open \"%s\" (%s)\n",
840 fname, strerror(errno)));
841 return ntstatus_to_werror(map_nt_error_from_unix(errno));
842 }
843
844 /* get the rootkey from the regf file and then load the tree
845 via recursive calls */
846
847 if (!(rootkey = regfio_rootkey(regfile))) {
848 regfio_close(regfile);
849 return WERR_REG_FILE_INVALID;
850 }
851
852 result = reg_load_tree(regfile, krecord->name, rootkey);
853
854 /* cleanup */
855
856 regfio_close(regfile);
857
858 return result;
859}
860
861WERROR reg_restorekey(struct registry_key *key, const char *fname)
862{
863 return restore_registry_key(key->key, fname);
864}
865
866/********************************************************************
867********************************************************************/
868
869static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
870 REGF_NK_REC *parent)
871{
872 REGF_NK_REC *key;
873 REGVAL_CTR *values;
874 REGSUBKEY_CTR *subkeys;
875 int i, num_subkeys;
876 char *key_tmp = NULL;
877 char *keyname, *parentpath;
878 char *subkeypath = NULL;
879 char *subkeyname;
880 REGISTRY_KEY registry_key;
881 WERROR result = WERR_OK;
882 SEC_DESC *sec_desc = NULL;
883
884 if (!regfile) {
885 return WERR_GENERAL_FAILURE;
886 }
887
888 if (!keypath) {
889 return WERR_OBJECT_PATH_INVALID;
890 }
891
892 /* split up the registry key path */
893
894 key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
895 if (!key_tmp) {
896 return WERR_NOMEM;
897 }
898 if (!reg_split_key(key_tmp, &parentpath, &keyname)) {
899 return WERR_OBJECT_PATH_INVALID;
900 }
901
902 if (!keyname) {
903 keyname = parentpath;
904 }
905
906 /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
907
908 ZERO_STRUCT(registry_key);
909
910 registry_key.name = talloc_strdup(regfile->mem_ctx, keypath);
911 if (registry_key.name == NULL) {
912 return WERR_NOMEM;
913 }
914
915 registry_key.ops = reghook_cache_find(registry_key.name);
916 if (registry_key.ops == NULL) {
917 return WERR_BADFILE;
918 }
919
920 /* lookup the values and subkeys */
921
922 subkeys = TALLOC_ZERO_P(regfile->mem_ctx, REGSUBKEY_CTR);
923 if (subkeys == NULL) {
924 return WERR_NOMEM;
925 }
926
927 values = TALLOC_ZERO_P(subkeys, REGVAL_CTR);
928 if (values == NULL) {
929 return WERR_NOMEM;
930 }
931
932 fetch_reg_keys(&registry_key, subkeys);
933 fetch_reg_values(&registry_key, values);
934
935 result = regkey_get_secdesc(regfile->mem_ctx, &registry_key, &sec_desc);
936 if (!W_ERROR_IS_OK(result)) {
937 goto done;
938 }
939
940 /* write out this key */
941
942 key = regfio_write_key(regfile, keyname, values, subkeys, sec_desc,
943 parent);
944 if (key == NULL) {
945 result = WERR_CAN_NOT_COMPLETE;
946 goto done;
947 }
948
949 /* write each one of the subkeys out */
950
951 num_subkeys = regsubkey_ctr_numkeys(subkeys);
952 for (i=0; i<num_subkeys; i++) {
953 subkeyname = regsubkey_ctr_specific_key(subkeys, i);
954 subkeypath = talloc_asprintf(regfile->mem_ctx, "%s\\%s",
955 keypath, subkeyname);
956 if (subkeypath == NULL) {
957 result = WERR_NOMEM;
958 goto done;
959 }
960 result = reg_write_tree(regfile, subkeypath, key);
961 if (!W_ERROR_IS_OK(result))
962 goto done;
963 }
964
965 DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath));
966
967done:
968 TALLOC_FREE(subkeys);
969 TALLOC_FREE(registry_key.name);
970
971 return result;
972}
973
974static WERROR backup_registry_key(REGISTRY_KEY *krecord, const char *fname)
975{
976 REGF_FILE *regfile;
977 WERROR result;
978
979 /* open the registry file....fail if the file already exists */
980
981 regfile = regfio_open(fname, (O_RDWR|O_CREAT|O_EXCL),
982 (S_IREAD|S_IWRITE));
983 if (regfile == NULL) {
984 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
985 fname, strerror(errno) ));
986 return ntstatus_to_werror(map_nt_error_from_unix(errno));
987 }
988
989 /* write the registry tree to the file */
990
991 result = reg_write_tree(regfile, krecord->name, NULL);
992
993 /* cleanup */
994
995 regfio_close(regfile);
996
997 return result;
998}
999
1000WERROR reg_savekey(struct registry_key *key, const char *fname)
1001{
1002 return backup_registry_key(key->key, fname);
1003}
1004
1005/**********************************************************************
1006 * Higher level utility functions
1007 **********************************************************************/
1008
1009WERROR reg_deleteallvalues(struct registry_key *key)
1010{
1011 WERROR err;
1012 int i;
1013
1014 if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
1015 return WERR_ACCESS_DENIED;
1016 }
1017
1018 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
1019 return err;
1020 }
1021
1022 for (i=0; i<key->values->num_values; i++) {
1023 regval_ctr_delvalue(key->values, key->values->values[i]->valuename);
1024 }
1025
1026 if (!store_reg_values(key->key, key->values)) {
1027 TALLOC_FREE(key->values);
1028 return WERR_REG_IO_FAILURE;
1029 }
1030
1031 return WERR_OK;
1032}
1033
1034/*
1035 * Utility function to open a complete registry path including the hive prefix.
1036 */
1037
1038WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
1039 uint32 desired_access, const struct nt_user_token *token,
1040 struct registry_key **pkey)
1041{
1042 struct registry_key *hive, *key;
1043 char *path, *p;
1044 WERROR err;
1045
1046 if (!(path = SMB_STRDUP(orig_path))) {
1047 return WERR_NOMEM;
1048 }
1049
1050 p = strchr(path, '\\');
1051
1052 if ((p == NULL) || (p[1] == '\0')) {
1053 /*
1054 * No key behind the hive, just return the hive
1055 */
1056
1057 err = reg_openhive(mem_ctx, path, desired_access, token,
1058 &hive);
1059 if (!W_ERROR_IS_OK(err)) {
1060 SAFE_FREE(path);
1061 return err;
1062 }
1063 SAFE_FREE(path);
1064 *pkey = hive;
1065 return WERR_OK;
1066 }
1067
1068 *p = '\0';
1069
1070 err = reg_openhive(mem_ctx, path, SEC_RIGHTS_ENUM_SUBKEYS, token,
1071 &hive);
1072 if (!W_ERROR_IS_OK(err)) {
1073 SAFE_FREE(path);
1074 return err;
1075 }
1076
1077 err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
1078
1079 TALLOC_FREE(hive);
1080 SAFE_FREE(path);
1081
1082 if (!W_ERROR_IS_OK(err)) {
1083 return err;
1084 }
1085
1086 *pkey = key;
1087 return WERR_OK;
1088}
1089
1090/*
1091 * Utility function to delete a registry key with all its subkeys.
1092 * Note that reg_deletekey returns ACCESS_DENIED when called on a
1093 * key that has subkeys.
1094 */
1095static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
1096 struct registry_key *parent,
1097 const char *path,
1098 bool del_key)
1099{
1100 TALLOC_CTX *mem_ctx = NULL;
1101 WERROR werr = WERR_OK;
1102 struct registry_key *key;
1103 char *subkey_name = NULL;
1104
1105 mem_ctx = talloc_new(ctx);
1106 if (mem_ctx == NULL) {
1107 werr = WERR_NOMEM;
1108 goto done;
1109 }
1110
1111 /* recurse through subkeys first */
1112 werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
1113 if (!W_ERROR_IS_OK(werr)) {
1114 goto done;
1115 }
1116
1117 while (W_ERROR_IS_OK(werr = reg_enumkey(mem_ctx, key, 0,
1118 &subkey_name, NULL)))
1119 {
1120 werr = reg_deletekey_recursive_internal(mem_ctx, key,
1121 subkey_name,
1122 true);
1123 if (!W_ERROR_IS_OK(werr)) {
1124 goto done;
1125 }
1126 }
1127 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
1128 DEBUG(1, ("reg_deletekey_recursive_internal: "
1129 "Error enumerating subkeys: %s\n",
1130 dos_errstr(werr)));
1131 goto done;
1132 }
1133
1134 werr = WERR_OK;
1135
1136 if (del_key) {
1137 /* now delete the actual key */
1138 werr = reg_deletekey(parent, path);
1139 }
1140
1141done:
1142 TALLOC_FREE(mem_ctx);
1143 return werr;
1144}
1145
1146WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
1147 struct registry_key *parent,
1148 const char *path)
1149{
1150 return reg_deletekey_recursive_internal(ctx, parent, path, true);
1151}
1152
1153WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
1154 struct registry_key *parent,
1155 const char *path)
1156{
1157 return reg_deletekey_recursive_internal(ctx, parent, path, false);
1158}
1159
1160#if 0
1161/* these two functions are unused. */
1162
1163/**
1164 * Utility function to create a registry key without opening the hive
1165 * before. Assumes the hive already exists.
1166 */
1167
1168WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path,
1169 uint32 desired_access,
1170 const struct nt_user_token *token,
1171 enum winreg_CreateAction *paction,
1172 struct registry_key **pkey)
1173{
1174 struct registry_key *hive;
1175 char *path, *p;
1176 WERROR err;
1177
1178 if (!(path = SMB_STRDUP(orig_path))) {
1179 return WERR_NOMEM;
1180 }
1181
1182 p = strchr(path, '\\');
1183
1184 if ((p == NULL) || (p[1] == '\0')) {
1185 /*
1186 * No key behind the hive, just return the hive
1187 */
1188
1189 err = reg_openhive(mem_ctx, path, desired_access, token,
1190 &hive);
1191 if (!W_ERROR_IS_OK(err)) {
1192 SAFE_FREE(path);
1193 return err;
1194 }
1195 SAFE_FREE(path);
1196 *pkey = hive;
1197 *paction = REG_OPENED_EXISTING_KEY;
1198 return WERR_OK;
1199 }
1200
1201 *p = '\0';
1202
1203 err = reg_openhive(mem_ctx, path,
1204 (strchr(p+1, '\\') != NULL) ?
1205 SEC_RIGHTS_ENUM_SUBKEYS : SEC_RIGHTS_CREATE_SUBKEY,
1206 token, &hive);
1207 if (!W_ERROR_IS_OK(err)) {
1208 SAFE_FREE(path);
1209 return err;
1210 }
1211
1212 err = reg_createkey(mem_ctx, hive, p+1, desired_access, pkey, paction);
1213 SAFE_FREE(path);
1214 TALLOC_FREE(hive);
1215 return err;
1216}
1217
1218/*
1219 * Utility function to create a registry key without opening the hive
1220 * before. Will not delete a hive.
1221 */
1222
1223WERROR reg_delete_path(const struct nt_user_token *token,
1224 const char *orig_path)
1225{
1226 struct registry_key *hive;
1227 char *path, *p;
1228 WERROR err;
1229
1230 if (!(path = SMB_STRDUP(orig_path))) {
1231 return WERR_NOMEM;
1232 }
1233
1234 p = strchr(path, '\\');
1235
1236 if ((p == NULL) || (p[1] == '\0')) {
1237 SAFE_FREE(path);
1238 return WERR_INVALID_PARAM;
1239 }
1240
1241 *p = '\0';
1242
1243 err = reg_openhive(NULL, path,
1244 (strchr(p+1, '\\') != NULL) ?
1245 SEC_RIGHTS_ENUM_SUBKEYS : SEC_RIGHTS_CREATE_SUBKEY,
1246 token, &hive);
1247 if (!W_ERROR_IS_OK(err)) {
1248 SAFE_FREE(path);
1249 return err;
1250 }
1251
1252 err = reg_deletekey(hive, p+1);
1253 SAFE_FREE(path);
1254 TALLOC_FREE(hive);
1255 return err;
1256}
1257#endif /* #if 0 */
Note: See TracBrowser for help on using the repository browser.