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