Add a reg_getversion() function to reg_api and use it in srv_winreg_nt.c.
[ddiss/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 assigned 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         REGSUBKEY_CTR *subkeys;
457
458         if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
459
460         if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
461                 err = WERR_NOMEM;
462                 goto done;
463         }
464
465         while ((end = strchr(path, '\\')) != NULL) {
466                 struct registry_key *tmp;
467                 enum winreg_CreateAction action;
468
469                 *end = '\0';
470
471                 err = reg_createkey(mem_ctx, key, path,
472                                     SEC_RIGHTS_ENUM_SUBKEYS, &tmp, &action);
473                 if (!W_ERROR_IS_OK(err)) {
474                         goto done;
475                 }
476
477                 if (key != parent) {
478                         TALLOC_FREE(key);
479                 }
480
481                 key = tmp;
482                 path = end+1;
483         }
484
485         /*
486          * At this point, "path" contains the one-element subkey of "key". We
487          * can try to open it.
488          */
489
490         err = reg_openkey(ctx, key, path, desired_access, pkey);
491         if (W_ERROR_IS_OK(err)) {
492                 if (paction != NULL) {
493                         *paction = REG_OPENED_EXISTING_KEY;
494                 }
495                 goto done;
496         }
497
498         if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
499                 /*
500                  * Something but "notfound" has happened, so bail out
501                  */
502                 goto done;
503         }
504
505         /*
506          * We have to make a copy of the current key, as we opened it only
507          * with ENUM_SUBKEY access.
508          */
509
510         err = reg_openkey(mem_ctx, key, "", SEC_RIGHTS_CREATE_SUBKEY,
511                           &create_parent);
512         if (!W_ERROR_IS_OK(err)) {
513                 goto done;
514         }
515
516         /*
517          * Actually create the subkey
518          */
519
520         if (!(subkeys = TALLOC_ZERO_P(mem_ctx, REGSUBKEY_CTR))) {
521                 err = WERR_NOMEM;
522                 goto done;
523         }
524
525         err = fill_subkey_cache(create_parent);
526         if (!W_ERROR_IS_OK(err)) goto done;
527
528         err = regsubkey_ctr_addkey(create_parent->subkeys, path);
529         if (!W_ERROR_IS_OK(err)) goto done;
530
531         if (!store_reg_keys(create_parent->key, create_parent->subkeys)) {
532                 TALLOC_FREE(create_parent->subkeys);
533                 err = WERR_REG_IO_FAILURE;
534                 goto done;
535         }
536
537         /*
538          * Now open the newly created key
539          */
540
541         err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
542         if (W_ERROR_IS_OK(err) && (paction != NULL)) {
543                 *paction = REG_CREATED_NEW_KEY;
544         }
545
546  done:
547         TALLOC_FREE(mem_ctx);
548         return err;
549 }
550
551 WERROR reg_deletekey(struct registry_key *parent, const char *path)
552 {
553         WERROR err;
554         TALLOC_CTX *mem_ctx;
555         char *name, *end;
556         int num_subkeys;
557         struct registry_key *tmp_key, *key;
558
559         if (!(mem_ctx = talloc_init("reg_createkey"))) return WERR_NOMEM;
560
561         if (!(name = talloc_strdup(mem_ctx, path))) {
562                 err = WERR_NOMEM;
563                 goto error;
564         }
565
566         /* check if the key has subkeys */
567         err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
568         if (!W_ERROR_IS_OK(err)) {
569                 goto error;
570         }
571         if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
572                 goto error;
573         }
574         if (key->subkeys->num_subkeys > 0) {
575                 err = WERR_ACCESS_DENIED;
576                 goto error;
577         }
578
579         /* no subkeys - proceed with delete */
580         if ((end = strrchr(name, '\\')) != NULL) {
581                 *end = '\0';
582
583                 err = reg_openkey(mem_ctx, parent, name,
584                                   SEC_RIGHTS_CREATE_SUBKEY, &tmp_key);
585                 if (!W_ERROR_IS_OK(err)) {
586                         goto error;
587                 }
588
589                 parent = tmp_key;
590                 name = end+1;
591         }
592
593         if (name[0] == '\0') {
594                 err = WERR_INVALID_PARAM;
595                 goto error;
596         }
597
598         if (!W_ERROR_IS_OK(err = fill_subkey_cache(parent))) {
599                 goto error;
600         }
601
602         num_subkeys = parent->subkeys->num_subkeys;
603
604         if (regsubkey_ctr_delkey(parent->subkeys, name) == num_subkeys) {
605                 err = WERR_BADFILE;
606                 goto error;
607         }
608
609         if (!store_reg_keys(parent->key, parent->subkeys)) {
610                 TALLOC_FREE(parent->subkeys);
611                 err = WERR_REG_IO_FAILURE;
612                 goto error;
613         }
614
615         regkey_set_secdesc(key->key, NULL);
616
617         err = WERR_OK;
618
619  error:
620         TALLOC_FREE(mem_ctx);
621         return err;
622 }
623
624 WERROR reg_setvalue(struct registry_key *key, const char *name,
625                     const struct registry_value *val)
626 {
627         WERROR err;
628         DATA_BLOB value_data;
629         int res;
630
631         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
632                 return WERR_ACCESS_DENIED;
633         }
634
635         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
636                 return err;
637         }
638
639         err = registry_push_value(key, val, &value_data);
640         if (!W_ERROR_IS_OK(err)) {
641                 return err;
642         }
643
644         res = regval_ctr_addvalue(key->values, name, val->type,
645                                   (char *)value_data.data, value_data.length);
646         TALLOC_FREE(value_data.data);
647
648         if (res == 0) {
649                 TALLOC_FREE(key->values);
650                 return WERR_NOMEM;
651         }
652
653         if (!store_reg_values(key->key, key->values)) {
654                 TALLOC_FREE(key->values);
655                 return WERR_REG_IO_FAILURE;
656         }
657
658         return WERR_OK;
659 }
660
661 WERROR reg_deletevalue(struct registry_key *key, const char *name)
662 {
663         WERROR err;
664
665         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
666                 return WERR_ACCESS_DENIED;
667         }
668
669         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
670                 return err;
671         }
672
673         regval_ctr_delvalue(key->values, name);
674
675         if (!store_reg_values(key->key, key->values)) {
676                 TALLOC_FREE(key->values);
677                 return WERR_REG_IO_FAILURE;
678         }
679
680         return WERR_OK;
681 }
682
683 WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key,
684                           struct security_descriptor **psecdesc)
685 {
686         return regkey_get_secdesc(mem_ctx, key->key, psecdesc);
687 }
688
689 WERROR reg_setkeysecurity(struct registry_key *key,
690                           struct security_descriptor *psecdesc)
691 {
692         return regkey_set_secdesc(key->key, psecdesc);
693 }
694
695 WERROR reg_getversion(uint32_t *version)
696 {
697         if (version == NULL) {
698                 return WERR_INVALID_PARAM;
699         }
700
701         *version = 0x00000005; /* Windows 2000 registry API version */
702         return WERR_OK;
703 }
704
705 /**********************************************************************
706  * Higher level utility functions
707  **********************************************************************/
708
709 WERROR reg_deleteallvalues(struct registry_key *key)
710 {
711         WERROR err;
712         int i;
713
714         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
715                 return WERR_ACCESS_DENIED;
716         }
717
718         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
719                 return err;
720         }
721
722         for (i=0; i<key->values->num_values; i++) {
723                 regval_ctr_delvalue(key->values, key->values->values[i]->valuename);
724         }
725
726         if (!store_reg_values(key->key, key->values)) {
727                 TALLOC_FREE(key->values);
728                 return WERR_REG_IO_FAILURE;
729         }
730
731         return WERR_OK;
732 }
733
734 /*
735  * Utility function to open a complete registry path including the hive
736  * prefix. This should become the replacement function for
737  * regkey_open_internal.
738  */
739
740 WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
741                      uint32 desired_access, const struct nt_user_token *token,
742                      struct registry_key **pkey)
743 {
744         struct registry_key *hive, *key;
745         char *path, *p;
746         WERROR err;
747
748         if (!(path = SMB_STRDUP(orig_path))) {
749                 return WERR_NOMEM;
750         }
751
752         p = strchr(path, '\\');
753
754         if ((p == NULL) || (p[1] == '\0')) {
755                 /*
756                  * No key behind the hive, just return the hive
757                  */
758
759                 err = reg_openhive(mem_ctx, path, desired_access, token,
760                                    &hive);
761                 if (!W_ERROR_IS_OK(err)) {
762                         SAFE_FREE(path);
763                         return err;
764                 }
765                 SAFE_FREE(path);
766                 *pkey = hive;
767                 return WERR_OK;
768         }
769
770         *p = '\0';
771
772         err = reg_openhive(mem_ctx, path, SEC_RIGHTS_ENUM_SUBKEYS, token,
773                            &hive);
774         if (!W_ERROR_IS_OK(err)) {
775                 SAFE_FREE(path);
776                 return err;
777         }
778
779         err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
780
781         TALLOC_FREE(hive);
782         SAFE_FREE(path);
783
784         if (!W_ERROR_IS_OK(err)) {
785                 return err;
786         }
787
788         *pkey = key;
789         return WERR_OK;
790 }
791
792 /*
793  * Utility function to delete a registry key with all its subkeys.
794  * Note that reg_deletekey returns ACCESS_DENIED when called on a
795  * key that has subkeys.
796  */
797 static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
798                                                struct registry_key *parent,
799                                                const char *path,
800                                                bool del_key)
801 {
802         TALLOC_CTX *mem_ctx = NULL;
803         WERROR werr = WERR_OK;
804         struct registry_key *key;
805         char *subkey_name = NULL;
806
807         mem_ctx = talloc_new(ctx);
808         if (mem_ctx == NULL) {
809                 werr = WERR_NOMEM;
810                 goto done;
811         }
812
813         /* recurse through subkeys first */
814         werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
815         if (!W_ERROR_IS_OK(werr)) {
816                 goto done;
817         }
818
819         while (W_ERROR_IS_OK(werr = reg_enumkey(mem_ctx, key, 0,
820                                                 &subkey_name, NULL)))
821         {
822                 werr = reg_deletekey_recursive_internal(mem_ctx, key,
823                                                         subkey_name,
824                                                         true);
825                 if (!W_ERROR_IS_OK(werr)) {
826                         goto done;
827                 }
828         }
829         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
830                 DEBUG(1, ("reg_deletekey_recursive_internal: "
831                           "Error enumerating subkeys: %s\n",
832                           dos_errstr(werr)));
833                 goto done;
834         }
835
836         werr = WERR_OK;
837
838         if (del_key) {
839                 /* now delete the actual key */
840                 werr = reg_deletekey(parent, path);
841         }
842
843 done:
844         TALLOC_FREE(mem_ctx);
845         return werr;
846 }
847
848 WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
849                                struct registry_key *parent,
850                                const char *path)
851 {
852         return reg_deletekey_recursive_internal(ctx, parent, path, true);
853 }
854
855 WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
856                                    struct registry_key *parent,
857                                    const char *path)
858 {
859         return reg_deletekey_recursive_internal(ctx, parent, path, false);
860 }
861
862 #if 0
863 /* these two functions are unused. */
864
865 /**
866  * Utility function to create a registry key without opening the hive
867  * before. Assumes the hive already exists.
868  */
869
870 WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path,
871                        uint32 desired_access,
872                        const struct nt_user_token *token,
873                        enum winreg_CreateAction *paction,
874                        struct registry_key **pkey)
875 {
876         struct registry_key *hive;
877         char *path, *p;
878         WERROR err;
879
880         if (!(path = SMB_STRDUP(orig_path))) {
881                 return WERR_NOMEM;
882         }
883
884         p = strchr(path, '\\');
885
886         if ((p == NULL) || (p[1] == '\0')) {
887                 /*
888                  * No key behind the hive, just return the hive
889                  */
890
891                 err = reg_openhive(mem_ctx, path, desired_access, token,
892                                    &hive);
893                 if (!W_ERROR_IS_OK(err)) {
894                         SAFE_FREE(path);
895                         return err;
896                 }
897                 SAFE_FREE(path);
898                 *pkey = hive;
899                 *paction = REG_OPENED_EXISTING_KEY;
900                 return WERR_OK;
901         }
902
903         *p = '\0';
904
905         err = reg_openhive(mem_ctx, path,
906                            (strchr(p+1, '\\') != NULL) ?
907                            SEC_RIGHTS_ENUM_SUBKEYS : SEC_RIGHTS_CREATE_SUBKEY,
908                            token, &hive);
909         if (!W_ERROR_IS_OK(err)) {
910                 SAFE_FREE(path);
911                 return err;
912         }
913
914         err = reg_createkey(mem_ctx, hive, p+1, desired_access, pkey, paction);
915         SAFE_FREE(path);
916         TALLOC_FREE(hive);
917         return err;
918 }
919
920 /*
921  * Utility function to create a registry key without opening the hive
922  * before. Will not delete a hive.
923  */
924
925 WERROR reg_delete_path(const struct nt_user_token *token,
926                        const char *orig_path)
927 {
928         struct registry_key *hive;
929         char *path, *p;
930         WERROR err;
931
932         if (!(path = SMB_STRDUP(orig_path))) {
933                 return WERR_NOMEM;
934         }
935
936         p = strchr(path, '\\');
937
938         if ((p == NULL) || (p[1] == '\0')) {
939                 SAFE_FREE(path);
940                 return WERR_INVALID_PARAM;
941         }
942
943         *p = '\0';
944
945         err = reg_openhive(NULL, path,
946                            (strchr(p+1, '\\') != NULL) ?
947                            SEC_RIGHTS_ENUM_SUBKEYS : SEC_RIGHTS_CREATE_SUBKEY,
948                            token, &hive);
949         if (!W_ERROR_IS_OK(err)) {
950                 SAFE_FREE(path);
951                 return err;
952         }
953
954         err = reg_deletekey(hive, p+1);
955         SAFE_FREE(path);
956         TALLOC_FREE(hive);
957         return err;
958 }
959 #endif /* #if 0 */