Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
[kai/samba.git] / source3 / registry / reg_api.c
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
47  * 0x14         winreg_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
67 #undef DBGC_CLASS
68 #define DBGC_CLASS DBGC_REGISTRY
69
70
71 /**********************************************************************
72  * Helper functions
73  **********************************************************************/
74
75 static WERROR fill_value_cache(struct registry_key *key)
76 {
77         if (key->values != NULL) {
78                 if (!reg_values_need_update(key->key, key->values)) {
79                         return WERR_OK;
80                 }
81         }
82
83         if (!(key->values = TALLOC_ZERO_P(key, REGVAL_CTR))) {
84                 return WERR_NOMEM;
85         }
86         if (fetch_reg_values(key->key, key->values) == -1) {
87                 TALLOC_FREE(key->values);
88                 return WERR_BADFILE;
89         }
90
91         return WERR_OK;
92 }
93
94 static WERROR fill_subkey_cache(struct registry_key *key)
95 {
96         if (key->subkeys != NULL) {
97                 if (!reg_subkeys_need_update(key->key, key->subkeys)) {
98                         return WERR_OK;
99                 }
100         }
101
102         if (!(key->subkeys = TALLOC_ZERO_P(key, REGSUBKEY_CTR))) {
103                 return WERR_NOMEM;
104         }
105
106         if (fetch_reg_keys(key->key, key->subkeys) == -1) {
107                 TALLOC_FREE(key->subkeys);
108                 return WERR_NO_MORE_ITEMS;
109         }
110
111         return WERR_OK;
112 }
113
114 static int regkey_destructor(REGISTRY_KEY *key)
115 {
116         return regdb_close();
117 }
118
119 static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx, 
120                                    struct registry_key *parent,
121                                    const char *name,
122                                    const struct nt_user_token *token,
123                                    uint32 access_desired,
124                                    struct registry_key **pregkey)
125 {
126         WERROR          result = WERR_OK;
127         struct registry_key *regkey;
128         REGISTRY_KEY *key;
129         REGSUBKEY_CTR   *subkeys = NULL;
130
131         DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
132
133         SMB_ASSERT(strchr(name, '\\') == NULL);
134
135         if (!(regkey = TALLOC_ZERO_P(mem_ctx, struct registry_key)) ||
136             !(regkey->token = dup_nt_token(regkey, token)) ||
137             !(regkey->key = TALLOC_ZERO_P(regkey, REGISTRY_KEY))) {
138                 result = WERR_NOMEM;
139                 goto done;
140         }
141
142         if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
143                 goto done;
144         }
145
146         key = regkey->key;
147         talloc_set_destructor(key, regkey_destructor);
148                 
149         /* initialization */
150         
151         key->type = REG_KEY_GENERIC;
152
153         if (name[0] == '\0') {
154                 /*
155                  * Open a copy of the parent key
156                  */
157                 if (!parent) {
158                         result = WERR_BADFILE;
159                         goto done;
160                 }
161                 key->name = talloc_strdup(key, parent->key->name);
162         }
163         else {
164                 /*
165                  * Normal subkey open
166                  */
167                 key->name = talloc_asprintf(key, "%s%s%s",
168                                             parent ? parent->key->name : "",
169                                             parent ? "\\": "",
170                                             name);
171         }
172
173         if (key->name == NULL) {
174                 result = WERR_NOMEM;
175                 goto done;
176         }
177
178         /* Tag this as a Performance Counter Key */
179
180         if( StrnCaseCmp(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
181                 key->type = REG_KEY_HKPD;
182         
183         /* Look up the table of registry I/O operations */
184
185         if ( !(key->hook = reghook_cache_find( key->name )) ) {
186                 DEBUG(0,("reg_open_onelevel: Failed to assign a "
187                          "REGISTRY_HOOK to [%s]\n", key->name ));
188                 result = WERR_BADFILE;
189                 goto done;
190         }
191
192         /* check if the path really exists; failed is indicated by -1 */
193         /* if the subkey count failed, bail out */
194
195         if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
196                 result = WERR_NOMEM;
197                 goto done;
198         }
199
200         if ( fetch_reg_keys( key, subkeys ) == -1 )  {
201                 result = WERR_BADFILE;
202                 goto done;
203         }
204
205         TALLOC_FREE( subkeys );
206
207         if ( !regkey_access_check( key, access_desired, &key->access_granted,
208                                    token ) ) {
209                 result = WERR_ACCESS_DENIED;
210                 goto done;
211         }
212
213         *pregkey = regkey;
214         result = WERR_OK;
215         
216 done:
217         if ( !W_ERROR_IS_OK(result) ) {
218                 TALLOC_FREE(regkey);
219         }
220
221         return result;
222 }
223
224 WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive,
225                     uint32 desired_access,
226                     const struct nt_user_token *token,
227                     struct registry_key **pkey)
228 {
229         SMB_ASSERT(hive != NULL);
230         SMB_ASSERT(hive[0] != '\0');
231         SMB_ASSERT(strchr(hive, '\\') == NULL);
232
233         return regkey_open_onelevel(mem_ctx, NULL, hive, token, desired_access,
234                                     pkey);
235 }
236
237
238 /**********************************************************************
239  * The API functions
240  **********************************************************************/
241
242 WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
243                    const char *name, uint32 desired_access,
244                    struct registry_key **pkey)
245 {
246         struct registry_key *direct_parent = parent;
247         WERROR err;
248         char *p, *path, *to_free;
249         size_t len;
250
251         if (!(path = SMB_STRDUP(name))) {
252                 return WERR_NOMEM;
253         }
254         to_free = path;
255
256         len = strlen(path);
257
258         if ((len > 0) && (path[len-1] == '\\')) {
259                 path[len-1] = '\0';
260         }
261
262         while ((p = strchr(path, '\\')) != NULL) {
263                 char *name_component;
264                 struct registry_key *tmp;
265
266                 if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
267                         err = WERR_NOMEM;
268                         goto error;
269                 }
270
271                 err = regkey_open_onelevel(mem_ctx, direct_parent,
272                                            name_component, parent->token,
273                                            SEC_RIGHTS_ENUM_SUBKEYS, &tmp);
274                 SAFE_FREE(name_component);
275
276                 if (!W_ERROR_IS_OK(err)) {
277                         goto error;
278                 }
279                 if (direct_parent != parent) {
280                         TALLOC_FREE(direct_parent);
281                 }
282
283                 direct_parent = tmp;
284                 path = p+1;
285         }
286
287         err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
288                                    desired_access, pkey);
289  error:
290         if (direct_parent != parent) {
291                 TALLOC_FREE(direct_parent);
292         }
293         SAFE_FREE(to_free);
294         return err;
295 }
296
297 WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
298                    uint32 idx, char **name, NTTIME *last_write_time)
299 {
300         WERROR err;
301
302         if (!(key->key->access_granted & SEC_RIGHTS_ENUM_SUBKEYS)) {
303                 return WERR_ACCESS_DENIED;
304         }
305
306         if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
307                 return err;
308         }
309
310         if (idx >= key->subkeys->num_subkeys) {
311                 return WERR_NO_MORE_ITEMS;
312         }
313
314         if (!(*name = talloc_strdup(mem_ctx, key->subkeys->subkeys[idx]))) {
315                 return WERR_NOMEM;
316         }
317
318         if (last_write_time) {
319                 *last_write_time = 0;
320         }
321
322         return WERR_OK;
323 }
324
325 WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
326                      uint32 idx, char **pname, struct registry_value **pval)
327 {
328         struct registry_value *val;
329         WERROR err;
330
331         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
332                 return WERR_ACCESS_DENIED;
333         }
334
335         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
336                 return err;
337         }
338
339         if (idx >= key->values->num_values) {
340                 return WERR_NO_MORE_ITEMS;
341         }
342
343         err = registry_pull_value(mem_ctx, &val,
344                                   key->values->values[idx]->type,
345                                   key->values->values[idx]->data_p,
346                                   key->values->values[idx]->size,
347                                   key->values->values[idx]->size);
348         if (!W_ERROR_IS_OK(err)) {
349                 return err;
350         }
351
352         if (pname
353             && !(*pname = talloc_strdup(
354                          mem_ctx, key->values->values[idx]->valuename))) {
355                 SAFE_FREE(val);
356                 return WERR_NOMEM;
357         }
358
359         *pval = val;
360         return WERR_OK;
361 }
362
363 WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
364                       const char *name, struct registry_value **pval)
365 {
366         WERROR err;
367         uint32 i;
368
369         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
370                 return WERR_ACCESS_DENIED;
371         }
372
373         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
374                 return err;
375         }
376
377         for (i=0; i<key->values->num_values; i++) {
378                 if (strequal(key->values->values[i]->valuename, name)) {
379                         return reg_enumvalue(mem_ctx, key, i, NULL, pval);
380                 }
381         }
382
383         return WERR_BADFILE;
384 }
385
386 WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
387                         uint32_t *max_subkeylen, uint32_t *max_subkeysize, 
388                         uint32_t *num_values, uint32_t *max_valnamelen, 
389                         uint32_t *max_valbufsize, uint32_t *secdescsize,
390                         NTTIME *last_changed_time)
391 {
392         uint32 i, max_size;
393         size_t max_len;
394         TALLOC_CTX *mem_ctx;
395         WERROR err;
396         struct security_descriptor *secdesc;
397
398         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
399                 return WERR_ACCESS_DENIED;
400         }
401
402         if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
403             !W_ERROR_IS_OK(fill_value_cache(key))) {
404                 return WERR_BADFILE;
405         }
406
407         max_len = 0;
408         for (i=0; i<key->subkeys->num_subkeys; i++) {
409                 max_len = MAX(max_len, strlen(key->subkeys->subkeys[i]));
410         }
411
412         *num_subkeys = key->subkeys->num_subkeys;
413         *max_subkeylen = max_len;
414         *max_subkeysize = 0;    /* Class length? */
415
416         max_len = 0;
417         max_size = 0;
418         for (i=0; i<key->values->num_values; i++) {
419                 max_len = MAX(max_len,
420                               strlen(key->values->values[i]->valuename));
421                 max_size = MAX(max_size, key->values->values[i]->size);
422         }
423
424         *num_values = key->values->num_values;
425         *max_valnamelen = max_len;
426         *max_valbufsize = max_size;
427
428         if (!(mem_ctx = talloc_new(key))) {
429                 return WERR_NOMEM;
430         }
431
432         err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
433         if (!W_ERROR_IS_OK(err)) {
434                 TALLOC_FREE(mem_ctx);
435                 return err;
436         }
437
438         *secdescsize = ndr_size_security_descriptor(secdesc, 0);
439         TALLOC_FREE(mem_ctx);
440
441         *last_changed_time = 0;
442
443         return WERR_OK;
444 }
445
446 WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
447                      const char *subkeypath, uint32 desired_access,
448                      struct registry_key **pkey,
449                      enum winreg_CreateAction *paction)
450 {
451         struct registry_key *key = parent;
452         struct registry_key *create_parent;
453         TALLOC_CTX *mem_ctx;
454         char *path, *end;
455         WERROR err;
456
457         if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
458
459         if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
460                 err = WERR_NOMEM;
461                 goto done;
462         }
463
464         while ((end = strchr(path, '\\')) != NULL) {
465                 struct registry_key *tmp;
466                 enum winreg_CreateAction action;
467
468                 *end = '\0';
469
470                 err = reg_createkey(mem_ctx, key, path,
471                                     SEC_RIGHTS_ENUM_SUBKEYS, &tmp, &action);
472                 if (!W_ERROR_IS_OK(err)) {
473                         goto done;
474                 }
475
476                 if (key != parent) {
477                         TALLOC_FREE(key);
478                 }
479
480                 key = tmp;
481                 path = end+1;
482         }
483
484         /*
485          * At this point, "path" contains the one-element subkey of "key". We
486          * can try to open it.
487          */
488
489         err = reg_openkey(ctx, key, path, desired_access, pkey);
490         if (W_ERROR_IS_OK(err)) {
491                 if (paction != NULL) {
492                         *paction = REG_OPENED_EXISTING_KEY;
493                 }
494                 goto done;
495         }
496
497         if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
498                 /*
499                  * Something but "notfound" has happened, so bail out
500                  */
501                 goto done;
502         }
503
504         /*
505          * We have to make a copy of the current key, as we opened it only
506          * with ENUM_SUBKEY access.
507          */
508
509         err = reg_openkey(mem_ctx, key, "", SEC_RIGHTS_CREATE_SUBKEY,
510                           &create_parent);
511         if (!W_ERROR_IS_OK(err)) {
512                 goto done;
513         }
514
515         /*
516          * Actually create the subkey
517          */
518
519         err = fill_subkey_cache(create_parent);
520         if (!W_ERROR_IS_OK(err)) goto done;
521
522         err = regsubkey_ctr_addkey(create_parent->subkeys, path);
523         if (!W_ERROR_IS_OK(err)) goto done;
524
525         if (!store_reg_keys(create_parent->key, create_parent->subkeys)) {
526                 TALLOC_FREE(create_parent->subkeys);
527                 err = WERR_REG_IO_FAILURE;
528                 goto done;
529         }
530
531         /*
532          * Now open the newly created key
533          */
534
535         err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
536         if (W_ERROR_IS_OK(err) && (paction != NULL)) {
537                 *paction = REG_CREATED_NEW_KEY;
538         }
539
540  done:
541         TALLOC_FREE(mem_ctx);
542         return err;
543 }
544
545 WERROR reg_deletekey(struct registry_key *parent, const char *path)
546 {
547         WERROR err;
548         TALLOC_CTX *mem_ctx;
549         char *name, *end;
550         int num_subkeys;
551         struct registry_key *tmp_key, *key;
552
553         if (!(mem_ctx = talloc_init("reg_createkey"))) return WERR_NOMEM;
554
555         if (!(name = talloc_strdup(mem_ctx, path))) {
556                 err = WERR_NOMEM;
557                 goto error;
558         }
559
560         /* check if the key has subkeys */
561         err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
562         if (!W_ERROR_IS_OK(err)) {
563                 goto error;
564         }
565         if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
566                 goto error;
567         }
568         if (key->subkeys->num_subkeys > 0) {
569                 err = WERR_ACCESS_DENIED;
570                 goto error;
571         }
572
573         /* no subkeys - proceed with delete */
574         if ((end = strrchr(name, '\\')) != NULL) {
575                 *end = '\0';
576
577                 err = reg_openkey(mem_ctx, parent, name,
578                                   SEC_RIGHTS_CREATE_SUBKEY, &tmp_key);
579                 if (!W_ERROR_IS_OK(err)) {
580                         goto error;
581                 }
582
583                 parent = tmp_key;
584                 name = end+1;
585         }
586
587         if (name[0] == '\0') {
588                 err = WERR_INVALID_PARAM;
589                 goto error;
590         }
591
592         if (!W_ERROR_IS_OK(err = fill_subkey_cache(parent))) {
593                 goto error;
594         }
595
596         num_subkeys = parent->subkeys->num_subkeys;
597
598         if (regsubkey_ctr_delkey(parent->subkeys, name) == num_subkeys) {
599                 err = WERR_BADFILE;
600                 goto error;
601         }
602
603         if (!store_reg_keys(parent->key, parent->subkeys)) {
604                 TALLOC_FREE(parent->subkeys);
605                 err = WERR_REG_IO_FAILURE;
606                 goto error;
607         }
608
609         regkey_set_secdesc(key->key, NULL);
610
611         err = WERR_OK;
612
613  error:
614         TALLOC_FREE(mem_ctx);
615         return err;
616 }
617
618 WERROR reg_setvalue(struct registry_key *key, const char *name,
619                     const struct registry_value *val)
620 {
621         WERROR err;
622         DATA_BLOB value_data;
623         int res;
624
625         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
626                 return WERR_ACCESS_DENIED;
627         }
628
629         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
630                 return err;
631         }
632
633         err = registry_push_value(key, val, &value_data);
634         if (!W_ERROR_IS_OK(err)) {
635                 return err;
636         }
637
638         res = regval_ctr_addvalue(key->values, name, val->type,
639                                   (char *)value_data.data, value_data.length);
640         TALLOC_FREE(value_data.data);
641
642         if (res == 0) {
643                 TALLOC_FREE(key->values);
644                 return WERR_NOMEM;
645         }
646
647         if (!store_reg_values(key->key, key->values)) {
648                 TALLOC_FREE(key->values);
649                 return WERR_REG_IO_FAILURE;
650         }
651
652         return WERR_OK;
653 }
654
655 WERROR reg_deletevalue(struct registry_key *key, const char *name)
656 {
657         WERROR err;
658
659         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
660                 return WERR_ACCESS_DENIED;
661         }
662
663         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
664                 return err;
665         }
666
667         regval_ctr_delvalue(key->values, name);
668
669         if (!store_reg_values(key->key, key->values)) {
670                 TALLOC_FREE(key->values);
671                 return WERR_REG_IO_FAILURE;
672         }
673
674         return WERR_OK;
675 }
676
677 WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key,
678                           struct security_descriptor **psecdesc)
679 {
680         return regkey_get_secdesc(mem_ctx, key->key, psecdesc);
681 }
682
683 WERROR reg_setkeysecurity(struct registry_key *key,
684                           struct security_descriptor *psecdesc)
685 {
686         return regkey_set_secdesc(key->key, psecdesc);
687 }
688
689 WERROR reg_getversion(uint32_t *version)
690 {
691         if (version == NULL) {
692                 return WERR_INVALID_PARAM;
693         }
694
695         *version = 0x00000005; /* Windows 2000 registry API version */
696         return WERR_OK;
697 }
698
699 /**********************************************************************
700  * Higher level utility functions
701  **********************************************************************/
702
703 WERROR reg_deleteallvalues(struct registry_key *key)
704 {
705         WERROR err;
706         int i;
707
708         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
709                 return WERR_ACCESS_DENIED;
710         }
711
712         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
713                 return err;
714         }
715
716         for (i=0; i<key->values->num_values; i++) {
717                 regval_ctr_delvalue(key->values, key->values->values[i]->valuename);
718         }
719
720         if (!store_reg_values(key->key, key->values)) {
721                 TALLOC_FREE(key->values);
722                 return WERR_REG_IO_FAILURE;
723         }
724
725         return WERR_OK;
726 }
727
728 /*
729  * Utility function to open a complete registry path including the hive
730  * prefix. This should become the replacement function for
731  * regkey_open_internal.
732  */
733
734 WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
735                      uint32 desired_access, const struct nt_user_token *token,
736                      struct registry_key **pkey)
737 {
738         struct registry_key *hive, *key;
739         char *path, *p;
740         WERROR err;
741
742         if (!(path = SMB_STRDUP(orig_path))) {
743                 return WERR_NOMEM;
744         }
745
746         p = strchr(path, '\\');
747
748         if ((p == NULL) || (p[1] == '\0')) {
749                 /*
750                  * No key behind the hive, just return the hive
751                  */
752
753                 err = reg_openhive(mem_ctx, path, desired_access, token,
754                                    &hive);
755                 if (!W_ERROR_IS_OK(err)) {
756                         SAFE_FREE(path);
757                         return err;
758                 }
759                 SAFE_FREE(path);
760                 *pkey = hive;
761                 return WERR_OK;
762         }
763
764         *p = '\0';
765
766         err = reg_openhive(mem_ctx, path, SEC_RIGHTS_ENUM_SUBKEYS, token,
767                            &hive);
768         if (!W_ERROR_IS_OK(err)) {
769                 SAFE_FREE(path);
770                 return err;
771         }
772
773         err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
774
775         TALLOC_FREE(hive);
776         SAFE_FREE(path);
777
778         if (!W_ERROR_IS_OK(err)) {
779                 return err;
780         }
781
782         *pkey = key;
783         return WERR_OK;
784 }
785
786 /*
787  * Utility function to delete a registry key with all its subkeys.
788  * Note that reg_deletekey returns ACCESS_DENIED when called on a
789  * key that has subkeys.
790  */
791 static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
792                                                struct registry_key *parent,
793                                                const char *path,
794                                                bool del_key)
795 {
796         TALLOC_CTX *mem_ctx = NULL;
797         WERROR werr = WERR_OK;
798         struct registry_key *key;
799         char *subkey_name = NULL;
800
801         mem_ctx = talloc_new(ctx);
802         if (mem_ctx == NULL) {
803                 werr = WERR_NOMEM;
804                 goto done;
805         }
806
807         /* recurse through subkeys first */
808         werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
809         if (!W_ERROR_IS_OK(werr)) {
810                 goto done;
811         }
812
813         while (W_ERROR_IS_OK(werr = reg_enumkey(mem_ctx, key, 0,
814                                                 &subkey_name, NULL)))
815         {
816                 werr = reg_deletekey_recursive_internal(mem_ctx, key,
817                                                         subkey_name,
818                                                         true);
819                 if (!W_ERROR_IS_OK(werr)) {
820                         goto done;
821                 }
822         }
823         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
824                 DEBUG(1, ("reg_deletekey_recursive_internal: "
825                           "Error enumerating subkeys: %s\n",
826                           dos_errstr(werr)));
827                 goto done;
828         }
829
830         werr = WERR_OK;
831
832         if (del_key) {
833                 /* now delete the actual key */
834                 werr = reg_deletekey(parent, path);
835         }
836
837 done:
838         TALLOC_FREE(mem_ctx);
839         return werr;
840 }
841
842 WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
843                                struct registry_key *parent,
844                                const char *path)
845 {
846         return reg_deletekey_recursive_internal(ctx, parent, path, true);
847 }
848
849 WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
850                                    struct registry_key *parent,
851                                    const char *path)
852 {
853         return reg_deletekey_recursive_internal(ctx, parent, path, false);
854 }
855
856 #if 0
857 /* these two functions are unused. */
858
859 /**
860  * Utility function to create a registry key without opening the hive
861  * before. Assumes the hive already exists.
862  */
863
864 WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path,
865                        uint32 desired_access,
866                        const struct nt_user_token *token,
867                        enum winreg_CreateAction *paction,
868                        struct registry_key **pkey)
869 {
870         struct registry_key *hive;
871         char *path, *p;
872         WERROR err;
873
874         if (!(path = SMB_STRDUP(orig_path))) {
875                 return WERR_NOMEM;
876         }
877
878         p = strchr(path, '\\');
879
880         if ((p == NULL) || (p[1] == '\0')) {
881                 /*
882                  * No key behind the hive, just return the hive
883                  */
884
885                 err = reg_openhive(mem_ctx, path, desired_access, token,
886                                    &hive);
887                 if (!W_ERROR_IS_OK(err)) {
888                         SAFE_FREE(path);
889                         return err;
890                 }
891                 SAFE_FREE(path);
892                 *pkey = hive;
893                 *paction = REG_OPENED_EXISTING_KEY;
894                 return WERR_OK;
895         }
896
897         *p = '\0';
898
899         err = reg_openhive(mem_ctx, path,
900                            (strchr(p+1, '\\') != NULL) ?
901                            SEC_RIGHTS_ENUM_SUBKEYS : SEC_RIGHTS_CREATE_SUBKEY,
902                            token, &hive);
903         if (!W_ERROR_IS_OK(err)) {
904                 SAFE_FREE(path);
905                 return err;
906         }
907
908         err = reg_createkey(mem_ctx, hive, p+1, desired_access, pkey, paction);
909         SAFE_FREE(path);
910         TALLOC_FREE(hive);
911         return err;
912 }
913
914 /*
915  * Utility function to create a registry key without opening the hive
916  * before. Will not delete a hive.
917  */
918
919 WERROR reg_delete_path(const struct nt_user_token *token,
920                        const char *orig_path)
921 {
922         struct registry_key *hive;
923         char *path, *p;
924         WERROR err;
925
926         if (!(path = SMB_STRDUP(orig_path))) {
927                 return WERR_NOMEM;
928         }
929
930         p = strchr(path, '\\');
931
932         if ((p == NULL) || (p[1] == '\0')) {
933                 SAFE_FREE(path);
934                 return WERR_INVALID_PARAM;
935         }
936
937         *p = '\0';
938
939         err = reg_openhive(NULL, path,
940                            (strchr(p+1, '\\') != NULL) ?
941                            SEC_RIGHTS_ENUM_SUBKEYS : SEC_RIGHTS_CREATE_SUBKEY,
942                            token, &hive);
943         if (!W_ERROR_IS_OK(err)) {
944                 SAFE_FREE(path);
945                 return err;
946         }
947
948         err = reg_deletekey(hive, p+1);
949         SAFE_FREE(path);
950         TALLOC_FREE(hive);
951         return err;
952 }
953 #endif /* #if 0 */