s3:dbwrap: move all .c and .h files of dbwrap to lib/dbwrap/
[kai/samba.git] / source3 / registry / reg_backend_db.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Gerald Carter                     2002-2005
5  *  Copyright (C) Michael Adam                      2007-2011
6  *  Copyright (C) Gregor Beck                       2011
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /* Implementation of internal registry database functions. */
23
24 #include "includes.h"
25 #include "system/filesys.h"
26 #include "registry.h"
27 #include "reg_db.h"
28 #include "reg_util_internal.h"
29 #include "reg_backend_db.h"
30 #include "reg_objects.h"
31 #include "nt_printing.h"
32 #include "util_tdb.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "../libcli/security/secdesc.h"
36
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_REGISTRY
39
40 static struct db_context *regdb = NULL;
41 static int regdb_refcount;
42
43 static bool regdb_key_exists(struct db_context *db, const char *key);
44 static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
45                                         struct regsubkey_ctr *ctr);
46 static bool regdb_store_keys_internal(struct db_context *db, const char *key,
47                                       struct regsubkey_ctr *ctr);
48 static int regdb_fetch_values_internal(struct db_context *db, const char* key,
49                                        struct regval_ctr *values);
50 static bool regdb_store_values_internal(struct db_context *db, const char *key,
51                                         struct regval_ctr *values);
52 static WERROR regdb_store_subkey_list(struct db_context *db, const char *parent,
53                                       const char *key);
54
55 static WERROR regdb_create_basekey(struct db_context *db, const char *key);
56 static WERROR regdb_create_subkey_internal(struct db_context *db,
57                                            const char *key,
58                                            const char *subkey);
59
60 /* List the deepest path into the registry.  All part components will be created.*/
61
62 /* If you want to have a part of the path controlled by the tdb and part by
63    a virtual registry db (e.g. printing), then you have to list the deepest path.
64    For example,"HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print" 
65    allows the reg_db backend to handle everything up to 
66    "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" and then we'll hook 
67    the reg_printing backend onto the last component of the path (see 
68    KEY_PRINTING_2K in include/rpc_reg.h)   --jerry */
69
70 static const char *builtin_registry_paths[] = {
71         KEY_PRINTING_2K,
72         KEY_PRINTING_PORTS,
73         KEY_PRINTING,
74         KEY_PRINTING "\\Forms",
75         KEY_PRINTING "\\Printers",
76         KEY_PRINTING "\\Environments\\Windows NT x86\\Print Processors\\winprint",
77         KEY_SHARES,
78         KEY_EVENTLOG,
79         KEY_SMBCONF,
80         KEY_PERFLIB,
81         KEY_PERFLIB_009,
82         KEY_GROUP_POLICY,
83         KEY_SAMBA_GROUP_POLICY,
84         KEY_GP_MACHINE_POLICY,
85         KEY_GP_MACHINE_WIN_POLICY,
86         KEY_HKCU,
87         KEY_GP_USER_POLICY,
88         KEY_GP_USER_WIN_POLICY,
89         "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions",
90         "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors",
91         KEY_PROD_OPTIONS,
92         "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\DefaultUserConfiguration",
93         KEY_TCPIP_PARAMS,
94         KEY_NETLOGON_PARAMS,
95         KEY_HKU,
96         KEY_HKCR,
97         KEY_HKPD,
98         KEY_HKPT,
99          NULL };
100
101 struct builtin_regkey_value {
102         const char *path;
103         const char *valuename;
104         uint32 type;
105         union {
106                 const char *string;
107                 uint32 dw_value;
108         } data;
109 };
110
111 static struct builtin_regkey_value builtin_registry_values[] = {
112         { KEY_PRINTING_PORTS,
113                 SAMBA_PRINTER_PORT_NAME, REG_SZ, { "" } },
114         { KEY_PRINTING_2K,
115                 "DefaultSpoolDirectory", REG_SZ, { "C:\\Windows\\System32\\Spool\\Printers" } },
116         { KEY_EVENTLOG,
117                 "DisplayName", REG_SZ, { "Event Log" } },
118         { KEY_EVENTLOG,
119                 "ErrorControl", REG_DWORD, { (char*)0x00000001 } },
120         { NULL, NULL, 0, { NULL } }
121 };
122
123 static WERROR create_key_recursive(struct db_context *db,
124                                    char *path,
125                                    const char *subkey)
126 {
127         WERROR werr;
128         char *p;
129
130         if (subkey == NULL) {
131                 return WERR_INVALID_PARAM;
132         }
133
134         if (path == NULL) {
135                 return regdb_create_basekey(db, subkey);
136         }
137
138         p = strrchr_m(path, '\\');
139
140         if (p == NULL) {
141                 werr = create_key_recursive(db, NULL, path);
142         } else {
143                 *p = '\0';
144                 werr = create_key_recursive(db, path, p+1);
145                 *p = '\\';
146         }
147
148         if (!W_ERROR_IS_OK(werr)) {
149                 goto done;
150         }
151
152         werr = regdb_create_subkey_internal(db, path, subkey);
153
154 done:
155         return werr;
156 }
157
158 /**
159  * Initialize a key in the registry:
160  * create each component key of the specified path.
161  */
162 static WERROR init_registry_key_internal(struct db_context *db,
163                                          const char *add_path)
164 {
165         char *subkey, *key;
166         WERROR werr;
167         TALLOC_CTX *frame = talloc_stackframe();
168
169         if (add_path == NULL) {
170                 werr = WERR_INVALID_PARAM;
171                 goto done;
172         }
173
174         key = talloc_strdup(frame, add_path);
175
176         subkey = strrchr_m(key, '\\');
177         if (subkey == NULL) {
178                 subkey = key;
179                 key = NULL;
180         } else {
181                 *subkey = '\0';
182                 subkey++;
183         }
184
185         werr = create_key_recursive(db, key, subkey);
186
187 done:
188         talloc_free(frame);
189         return werr;
190 }
191
192 struct init_registry_key_context {
193         const char *add_path;
194 };
195
196 static NTSTATUS init_registry_key_action(struct db_context *db,
197                                          void *private_data)
198 {
199         struct init_registry_key_context *init_ctx =
200                 (struct init_registry_key_context *)private_data;
201
202         return werror_to_ntstatus(init_registry_key_internal(
203                                         db, init_ctx->add_path));
204 }
205
206 /**
207  * Initialize a key in the registry:
208  * create each component key of the specified path,
209  * wrapped in one db transaction.
210  */
211 WERROR init_registry_key(const char *add_path)
212 {
213         struct init_registry_key_context init_ctx;
214
215         if (regdb_key_exists(regdb, add_path)) {
216                 return WERR_OK;
217         }
218
219         init_ctx.add_path = add_path;
220
221         return ntstatus_to_werror(dbwrap_trans_do(regdb,
222                                                   init_registry_key_action,
223                                                   &init_ctx));
224 }
225
226 /***********************************************************************
227  Open the registry data in the tdb
228  ***********************************************************************/
229
230 static void regdb_ctr_add_value(struct regval_ctr *ctr,
231                                 struct builtin_regkey_value *value)
232 {
233         switch(value->type) {
234         case REG_DWORD:
235                 regval_ctr_addvalue(ctr, value->valuename, REG_DWORD,
236                                     (uint8_t *)&value->data.dw_value,
237                                     sizeof(uint32));
238                 break;
239
240         case REG_SZ:
241                 regval_ctr_addvalue_sz(ctr, value->valuename,
242                                        value->data.string);
243                 break;
244
245         default:
246                 DEBUG(0, ("regdb_ctr_add_value: invalid value type in "
247                           "registry values [%d]\n", value->type));
248         }
249 }
250
251 static NTSTATUS init_registry_data_action(struct db_context *db,
252                                           void *private_data)
253 {
254         NTSTATUS status;
255         TALLOC_CTX *frame = talloc_stackframe();
256         struct regval_ctr *values;
257         int i;
258
259         /* loop over all of the predefined paths and add each component */
260
261         for (i=0; builtin_registry_paths[i] != NULL; i++) {
262                 if (regdb_key_exists(db, builtin_registry_paths[i])) {
263                         continue;
264                 }
265                 status = werror_to_ntstatus(init_registry_key_internal(db,
266                                                   builtin_registry_paths[i]));
267                 if (!NT_STATUS_IS_OK(status)) {
268                         goto done;
269                 }
270         }
271
272         /* loop over all of the predefined values and add each component */
273
274         for (i=0; builtin_registry_values[i].path != NULL; i++) {
275                 WERROR werr;
276
277                 werr = regval_ctr_init(frame, &values);
278                 if (!W_ERROR_IS_OK(werr)) {
279                         status = werror_to_ntstatus(werr);
280                         goto done;
281                 }
282
283                 regdb_fetch_values_internal(db,
284                                             builtin_registry_values[i].path,
285                                             values);
286
287                 /* preserve existing values across restarts. Only add new ones */
288
289                 if (!regval_ctr_key_exists(values,
290                                         builtin_registry_values[i].valuename))
291                 {
292                         regdb_ctr_add_value(values,
293                                             &builtin_registry_values[i]);
294                         regdb_store_values_internal(db,
295                                         builtin_registry_values[i].path,
296                                         values);
297                 }
298                 TALLOC_FREE(values);
299         }
300
301         status = NT_STATUS_OK;
302
303 done:
304
305         TALLOC_FREE(frame);
306         return status;
307 }
308
309 WERROR init_registry_data(void)
310 {
311         WERROR werr;
312         TALLOC_CTX *frame = talloc_stackframe();
313         struct regval_ctr *values;
314         int i;
315
316         /*
317          * First, check for the existence of the needed keys and values.
318          * If all do already exist, we can save the writes.
319          */
320         for (i=0; builtin_registry_paths[i] != NULL; i++) {
321                 if (!regdb_key_exists(regdb, builtin_registry_paths[i])) {
322                         goto do_init;
323                 }
324         }
325
326         for (i=0; builtin_registry_values[i].path != NULL; i++) {
327                 werr = regval_ctr_init(frame, &values);
328                 W_ERROR_NOT_OK_GOTO_DONE(werr);
329
330                 regdb_fetch_values_internal(regdb,
331                                             builtin_registry_values[i].path,
332                                             values);
333                 if (!regval_ctr_key_exists(values,
334                                         builtin_registry_values[i].valuename))
335                 {
336                         TALLOC_FREE(values);
337                         goto do_init;
338                 }
339
340                 TALLOC_FREE(values);
341         }
342
343         werr = WERR_OK;
344         goto done;
345
346 do_init:
347
348         /*
349          * There are potentially quite a few store operations which are all
350          * indiviually wrapped in tdb transactions. Wrapping them in a single
351          * transaction gives just a single transaction_commit() to actually do
352          * its fsync()s. See tdb/common/transaction.c for info about nested
353          * transaction behaviour.
354          */
355
356         werr = ntstatus_to_werror(dbwrap_trans_do(regdb,
357                                                   init_registry_data_action,
358                                                   NULL));
359
360 done:
361         TALLOC_FREE(frame);
362         return werr;
363 }
364
365 static int regdb_normalize_keynames_fn(struct db_record *rec,
366                                        void *private_data)
367 {
368         TALLOC_CTX *mem_ctx = talloc_tos();
369         const char *keyname;
370         NTSTATUS status;
371
372         if (rec->key.dptr == NULL || rec->key.dsize == 0) {
373                 return 0;
374         }
375
376         keyname = strchr((const char *) rec->key.dptr, '/');
377         if (keyname) {
378                 struct db_record new_rec;
379
380                 keyname = talloc_string_sub(mem_ctx,
381                                             (const char *) rec->key.dptr,
382                                             "/",
383                                             "\\");
384
385                 DEBUG(2, ("regdb_normalize_keynames_fn: Convert %s to %s\n",
386                           (const char *) rec->key.dptr,
387                           keyname));
388
389                 new_rec.value = rec->value;
390                 new_rec.key = string_term_tdb_data(keyname);
391                 new_rec.private_data = rec->private_data;
392
393                 /* Delete the original record and store the normalized key */
394                 status = rec->delete_rec(rec);
395                 if (!NT_STATUS_IS_OK(status)) {
396                         DEBUG(0,("regdb_normalize_keynames_fn: "
397                                  "tdb_delete for [%s] failed!\n",
398                                  rec->key.dptr));
399                         return 1;
400                 }
401
402                 status = rec->store(&new_rec, new_rec.value, TDB_REPLACE);
403                 if (!NT_STATUS_IS_OK(status)) {
404                         DEBUG(0,("regdb_normalize_keynames_fn: "
405                                  "failed to store new record for [%s]!\n",
406                                  keyname));
407                         return 1;
408                 }
409         }
410
411         return 0;
412 }
413
414 static WERROR regdb_store_regdb_version(struct db_context *db, uint32_t version)
415 {
416         NTSTATUS status;
417         const char *version_keyname = "INFO/version";
418
419         if (db == NULL) {
420                 return WERR_CAN_NOT_COMPLETE;
421         }
422
423         status = dbwrap_trans_store_int32(db, version_keyname, version);
424         if (!NT_STATUS_IS_OK(status)) {
425                 DEBUG(1, ("regdb_store_regdb_version: error storing %s = %d: %s\n",
426                           version_keyname, version, nt_errstr(status)));
427                 return ntstatus_to_werror(status);
428         } else {
429                 DEBUG(10, ("regdb_store_regdb_version: stored %s = %d\n",
430                           version_keyname, version));
431                 return WERR_OK;
432         }
433 }
434
435 static WERROR regdb_upgrade_v1_to_v2(struct db_context *db)
436 {
437         TALLOC_CTX *mem_ctx;
438         int rc;
439         WERROR werr;
440
441         mem_ctx = talloc_stackframe();
442
443         rc = regdb->traverse(db, regdb_normalize_keynames_fn, mem_ctx);
444
445         talloc_free(mem_ctx);
446
447         if (rc < 0) {
448                 return WERR_REG_IO_FAILURE;
449         }
450
451         werr = regdb_store_regdb_version(db, REGVER_V2);
452         return werr;
453 }
454
455 static int regdb_upgrade_v2_to_v3_fn(struct db_record *rec, void *private_data)
456 {
457         const char *keyname;
458         fstring subkeyname;
459         NTSTATUS status;
460         WERROR werr;
461         uint8_t *buf;
462         uint32_t buflen, len;
463         uint32_t num_items;
464         uint32_t i;
465
466         if (rec->key.dptr == NULL || rec->key.dsize == 0) {
467                 return 0;
468         }
469
470         keyname = (const char *)rec->key.dptr;
471
472         if (strncmp(keyname, REG_SORTED_SUBKEYS_PREFIX,
473                     strlen(REG_SORTED_SUBKEYS_PREFIX)) == 0)
474         {
475                 /* Delete the deprecated sorted subkeys cache. */
476
477                 DEBUG(10, ("regdb_upgrade_v2_to_v3: deleting [%s]\n", keyname));
478
479                 status = rec->delete_rec(rec);
480                 if (!NT_STATUS_IS_OK(status)) {
481                         DEBUG(0, ("regdb_upgrade_v2_to_v3: tdb_delete for [%s] "
482                                   "failed!\n", keyname));
483                         return 1;
484                 }
485
486                 return 0;
487         }
488
489         if (strncmp(keyname, REG_VALUE_PREFIX, strlen(REG_VALUE_PREFIX)) == 0) {
490                 DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping [%s]\n", keyname));
491                 return 0;
492         }
493
494         if (strncmp(keyname, REG_SECDESC_PREFIX,
495                     strlen(REG_SECDESC_PREFIX)) == 0)
496         {
497                 DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping [%s]\n", keyname));
498                 return 0;
499         }
500
501         /*
502          * Found a regular subkey list record.
503          * Walk the list and create the list record for those
504          * subkeys that don't already have one.
505          */
506         DEBUG(10, ("regdb_upgrade_v2_to_v3: scanning subkey list of [%s]\n",
507                    keyname));
508
509         buf = rec->value.dptr;
510         buflen = rec->value.dsize;
511
512         len = tdb_unpack(buf, buflen, "d", &num_items);
513         if (len == (uint32_t)-1) {
514                 /* invalid or empty - skip */
515                 return 0;
516         }
517
518         for (i=0; i<num_items; i++) {
519                 len += tdb_unpack(buf+len, buflen-len, "f", subkeyname);
520                 DEBUG(10, ("regdb_upgrade_v2_to_v3: "
521                            "writing subkey list for [%s\\%s]\n",
522                            keyname, subkeyname));
523                 werr = regdb_store_subkey_list(regdb, keyname, subkeyname);
524                 if (!W_ERROR_IS_OK(werr)) {
525                         return 1;
526                 }
527         }
528
529         return 0;
530 }
531
532 static WERROR regdb_upgrade_v2_to_v3(struct db_context *db)
533 {
534         int rc;
535         WERROR werr;
536         TALLOC_CTX *frame = talloc_stackframe();
537
538         rc = regdb->traverse(db, regdb_upgrade_v2_to_v3_fn, frame);
539         if (rc < 0) {
540                 werr = WERR_REG_IO_FAILURE;
541                 goto done;
542         }
543
544         werr = regdb_store_regdb_version(db, REGVER_V3);
545
546 done:
547         talloc_free(frame);
548         return werr;
549 }
550
551 /***********************************************************************
552  Open the registry database
553  ***********************************************************************/
554
555 WERROR regdb_init(void)
556 {
557         const char *vstring = "INFO/version";
558         uint32 vers_id, expected_version;
559         WERROR werr;
560
561         if (regdb) {
562                 DEBUG(10, ("regdb_init: incrementing refcount (%d->%d)\n",
563                            regdb_refcount, regdb_refcount+1));
564                 regdb_refcount++;
565                 return WERR_OK;
566         }
567
568         regdb = db_open(NULL, state_path("registry.tdb"), 0,
569                               REG_TDB_FLAGS, O_RDWR, 0600);
570         if (!regdb) {
571                 regdb = db_open(NULL, state_path("registry.tdb"), 0,
572                                       REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600);
573                 if (!regdb) {
574                         werr = ntstatus_to_werror(map_nt_error_from_unix(errno));
575                         DEBUG(1,("regdb_init: Failed to open registry %s (%s)\n",
576                                 state_path("registry.tdb"), strerror(errno) ));
577                         return werr;
578                 }
579
580                 DEBUG(10,("regdb_init: Successfully created registry tdb\n"));
581         }
582
583         regdb_refcount = 1;
584         DEBUG(10, ("regdb_init: registry db openend. refcount reset (%d)\n",
585                    regdb_refcount));
586
587         expected_version = REGVER_V3;
588
589         vers_id = dbwrap_fetch_int32(regdb, vstring);
590         if (vers_id == -1) {
591                 DEBUG(10, ("regdb_init: registry version uninitialized "
592                            "(got %d), initializing to version %d\n",
593                            vers_id, expected_version));
594
595                 werr = regdb_store_regdb_version(regdb, expected_version);
596                 return werr;
597         }
598
599         if (vers_id > expected_version || vers_id == 0) {
600                 DEBUG(1, ("regdb_init: unknown registry version %d "
601                           "(code version = %d), refusing initialization\n",
602                           vers_id, expected_version));
603                 return WERR_CAN_NOT_COMPLETE;
604         }
605
606         if (regdb->transaction_start(regdb) != 0) {
607                 return WERR_REG_IO_FAILURE;
608         }
609
610         if (vers_id == REGVER_V1) {
611                 DEBUG(10, ("regdb_init: upgrading registry fromversion %d "
612                            "to %d\n", REGVER_V1, REGVER_V2));
613
614                 werr = regdb_upgrade_v1_to_v2(regdb);
615                 if (!W_ERROR_IS_OK(werr)) {
616                         regdb->transaction_cancel(regdb);
617                         return werr;
618                 }
619
620                 vers_id = REGVER_V2;
621         }
622
623         if (vers_id == REGVER_V2) {
624                 DEBUG(10, ("regdb_init: upgrading registry from version %d "
625                            "to %d\n", REGVER_V2, REGVER_V3));
626
627                 werr = regdb_upgrade_v2_to_v3(regdb);
628                 if (!W_ERROR_IS_OK(werr)) {
629                         regdb->transaction_cancel(regdb);
630                         return werr;
631                 }
632
633                 vers_id = REGVER_V3;
634         }
635
636         /* future upgrade code should go here */
637
638         if (regdb->transaction_commit(regdb) != 0) {
639                 return WERR_REG_IO_FAILURE;
640         }
641
642         return WERR_OK;
643 }
644
645 /***********************************************************************
646  Open the registry.  Must already have been initialized by regdb_init()
647  ***********************************************************************/
648
649 WERROR regdb_open( void )
650 {
651         WERROR result = WERR_OK;
652
653         if ( regdb ) {
654                 DEBUG(10, ("regdb_open: incrementing refcount (%d->%d)\n",
655                            regdb_refcount, regdb_refcount+1));
656                 regdb_refcount++;
657                 return WERR_OK;
658         }
659
660         become_root();
661
662         regdb = db_open(NULL, state_path("registry.tdb"), 0,
663                               REG_TDB_FLAGS, O_RDWR, 0600);
664         if ( !regdb ) {
665                 result = ntstatus_to_werror( map_nt_error_from_unix( errno ) );
666                 DEBUG(0,("regdb_open: Failed to open %s! (%s)\n",
667                         state_path("registry.tdb"), strerror(errno) ));
668         }
669
670         unbecome_root();
671
672         regdb_refcount = 1;
673         DEBUG(10, ("regdb_open: registry db opened. refcount reset (%d)\n",
674                    regdb_refcount));
675
676         return result;
677 }
678
679 /***********************************************************************
680  ***********************************************************************/
681
682 int regdb_close( void )
683 {
684         if (regdb_refcount == 0) {
685                 return 0;
686         }
687
688         regdb_refcount--;
689
690         DEBUG(10, ("regdb_close: decrementing refcount (%d->%d)\n",
691                    regdb_refcount+1, regdb_refcount));
692
693         if ( regdb_refcount > 0 )
694                 return 0;
695
696         SMB_ASSERT( regdb_refcount >= 0 );
697
698         TALLOC_FREE(regdb);
699         return 0;
700 }
701
702 WERROR regdb_transaction_start(void)
703 {
704         return (regdb->transaction_start(regdb) == 0) ?
705                 WERR_OK : WERR_REG_IO_FAILURE;
706 }
707
708 WERROR regdb_transaction_commit(void)
709 {
710         return (regdb->transaction_commit(regdb) == 0) ?
711                 WERR_OK : WERR_REG_IO_FAILURE;
712 }
713
714 WERROR regdb_transaction_cancel(void)
715 {
716         return (regdb->transaction_cancel(regdb) == 0) ?
717                 WERR_OK : WERR_REG_IO_FAILURE;
718 }
719
720 /***********************************************************************
721  return the tdb sequence number of the registry tdb.
722  this is an indicator for the content of the registry
723  having changed. it will change upon regdb_init, too, though.
724  ***********************************************************************/
725 int regdb_get_seqnum(void)
726 {
727         return regdb->get_seqnum(regdb);
728 }
729
730
731 static WERROR regdb_delete_key_with_prefix(struct db_context *db,
732                                            const char *keyname,
733                                            const char *prefix)
734 {
735         char *path;
736         WERROR werr = WERR_NOMEM;
737         TALLOC_CTX *mem_ctx = talloc_stackframe();
738
739         if (keyname == NULL) {
740                 werr = WERR_INVALID_PARAM;
741                 goto done;
742         }
743
744         if (prefix == NULL) {
745                 path = discard_const_p(char, keyname);
746         } else {
747                 path = talloc_asprintf(mem_ctx, "%s\\%s", prefix, keyname);
748                 if (path == NULL) {
749                         goto done;
750                 }
751         }
752
753         path = normalize_reg_path(mem_ctx, path);
754         if (path == NULL) {
755                 goto done;
756         }
757
758         werr = ntstatus_to_werror(dbwrap_delete_bystring(db, path));
759
760         /* treat "not found" as ok */
761         if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) {
762                 werr = WERR_OK;
763         }
764
765 done:
766         talloc_free(mem_ctx);
767         return werr;
768 }
769
770
771 static WERROR regdb_delete_values(struct db_context *db, const char *keyname)
772 {
773         return regdb_delete_key_with_prefix(db, keyname, REG_VALUE_PREFIX);
774 }
775
776 static WERROR regdb_delete_secdesc(struct db_context *db, const char *keyname)
777 {
778         return regdb_delete_key_with_prefix(db, keyname, REG_SECDESC_PREFIX);
779 }
780
781 static WERROR regdb_delete_subkeylist(struct db_context *db, const char *keyname)
782 {
783         return regdb_delete_key_with_prefix(db, keyname, NULL);
784 }
785
786
787 static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname)
788 {
789         WERROR werr;
790
791         werr = regdb_delete_values(db, keyname);
792         if (!W_ERROR_IS_OK(werr)) {
793                 DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
794                           REG_VALUE_PREFIX, keyname, win_errstr(werr)));
795                 goto done;
796         }
797
798         werr = regdb_delete_secdesc(db, keyname);
799         if (!W_ERROR_IS_OK(werr)) {
800                 DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
801                           REG_SECDESC_PREFIX, keyname, win_errstr(werr)));
802                 goto done;
803         }
804
805         werr = regdb_delete_subkeylist(db, keyname);
806         if (!W_ERROR_IS_OK(werr)) {
807                 DEBUG(1, (__location__ " Deleting %s failed: %s\n",
808                           keyname, win_errstr(werr)));
809                 goto done;
810         }
811
812 done:
813         return werr;
814 }
815
816 /***********************************************************************
817  Add subkey strings to the registry tdb under a defined key
818  fmt is the same format as tdb_pack except this function only supports
819  fstrings
820  ***********************************************************************/
821
822 static WERROR regdb_store_keys_internal2(struct db_context *db,
823                                          const char *key,
824                                          struct regsubkey_ctr *ctr)
825 {
826         TDB_DATA dbuf;
827         uint8 *buffer = NULL;
828         int i = 0;
829         uint32 len, buflen;
830         uint32 num_subkeys = regsubkey_ctr_numkeys(ctr);
831         char *keyname = NULL;
832         TALLOC_CTX *ctx = talloc_stackframe();
833         WERROR werr;
834
835         if (!key) {
836                 werr = WERR_INVALID_PARAM;
837                 goto done;
838         }
839
840         keyname = talloc_strdup(ctx, key);
841         if (!keyname) {
842                 werr = WERR_NOMEM;
843                 goto done;
844         }
845
846         keyname = normalize_reg_path(ctx, keyname);
847         if (!keyname) {
848                 werr = WERR_NOMEM;
849                 goto done;
850         }
851
852         /* allocate some initial memory */
853
854         buffer = (uint8 *)SMB_MALLOC(1024);
855         if (buffer == NULL) {
856                 werr = WERR_NOMEM;
857                 goto done;
858         }
859         buflen = 1024;
860         len = 0;
861
862         /* store the number of subkeys */
863
864         len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys);
865
866         /* pack all the strings */
867
868         for (i=0; i<num_subkeys; i++) {
869                 size_t thistime;
870
871                 thistime = tdb_pack(buffer+len, buflen-len, "f",
872                                     regsubkey_ctr_specific_key(ctr, i));
873                 if (len+thistime > buflen) {
874                         size_t thistime2;
875                         /*
876                          * tdb_pack hasn't done anything because of the short
877                          * buffer, allocate extra space.
878                          */
879                         buffer = SMB_REALLOC_ARRAY(buffer, uint8_t,
880                                                    (len+thistime)*2);
881                         if(buffer == NULL) {
882                                 DEBUG(0, ("regdb_store_keys: Failed to realloc "
883                                           "memory of size [%u]\n",
884                                           (unsigned int)(len+thistime)*2));
885                                 werr = WERR_NOMEM;
886                                 goto done;
887                         }
888                         buflen = (len+thistime)*2;
889                         thistime2 = tdb_pack(
890                                 buffer+len, buflen-len, "f",
891                                 regsubkey_ctr_specific_key(ctr, i));
892                         if (thistime2 != thistime) {
893                                 DEBUG(0, ("tdb_pack failed\n"));
894                                 werr = WERR_CAN_NOT_COMPLETE;
895                                 goto done;
896                         }
897                 }
898                 len += thistime;
899         }
900
901         /* finally write out the data */
902
903         dbuf.dptr = buffer;
904         dbuf.dsize = len;
905         werr = ntstatus_to_werror(dbwrap_store_bystring(db, keyname, dbuf,
906                                                         TDB_REPLACE));
907
908 done:
909         TALLOC_FREE(ctx);
910         SAFE_FREE(buffer);
911         return werr;
912 }
913
914 /**
915  * Utility function to store a new empty list of
916  * subkeys of given key specified as parent and subkey name
917  * (thereby creating the key).
918  * If the parent keyname is NULL, then the "subkey" is
919  * interpreted as a base key.
920  * If the subkey list does already exist, it is not modified.
921  *
922  * Must be called from within a transaction.
923  */
924 static WERROR regdb_store_subkey_list(struct db_context *db, const char *parent,
925                                       const char *key)
926 {
927         WERROR werr;
928         char *path = NULL;
929         struct regsubkey_ctr *subkeys = NULL;
930         TALLOC_CTX *frame = talloc_stackframe();
931
932         if (parent == NULL) {
933                 path = talloc_strdup(frame, key);
934         } else {
935                 path = talloc_asprintf(frame, "%s\\%s", parent, key);
936         }
937         if (!path) {
938                 werr = WERR_NOMEM;
939                 goto done;
940         }
941
942         werr = regsubkey_ctr_init(frame, &subkeys);
943         W_ERROR_NOT_OK_GOTO_DONE(werr);
944
945         werr = regdb_fetch_keys_internal(db, path, subkeys);
946         if (W_ERROR_IS_OK(werr)) {
947                 /* subkey list exists already - don't modify */
948                 goto done;
949         }
950
951         werr = regsubkey_ctr_reinit(subkeys);
952         W_ERROR_NOT_OK_GOTO_DONE(werr);
953
954         /* create a record with 0 subkeys */
955         werr = regdb_store_keys_internal2(db, path, subkeys);
956         if (!W_ERROR_IS_OK(werr)) {
957                 DEBUG(0, ("regdb_store_keys: Failed to store new record for "
958                           "key [%s]: %s\n", path, win_errstr(werr)));
959                 goto done;
960         }
961
962 done:
963         talloc_free(frame);
964         return werr;
965 }
966
967 /***********************************************************************
968  Store the new subkey record and create any child key records that
969  do not currently exist
970  ***********************************************************************/
971
972 struct regdb_store_keys_context {
973         const char *key;
974         struct regsubkey_ctr *ctr;
975 };
976
977 static NTSTATUS regdb_store_keys_action(struct db_context *db,
978                                         void *private_data)
979 {
980         struct regdb_store_keys_context *store_ctx;
981         WERROR werr;
982         int num_subkeys, i;
983         char *path = NULL;
984         struct regsubkey_ctr *old_subkeys = NULL;
985         char *oldkeyname = NULL;
986         TALLOC_CTX *mem_ctx = talloc_stackframe();
987
988         store_ctx = (struct regdb_store_keys_context *)private_data;
989
990         /*
991          * Re-fetch the old keys inside the transaction
992          */
993
994         werr = regsubkey_ctr_init(mem_ctx, &old_subkeys);
995         W_ERROR_NOT_OK_GOTO_DONE(werr);
996
997         werr = regdb_fetch_keys_internal(db, store_ctx->key, old_subkeys);
998         if (!W_ERROR_IS_OK(werr) &&
999             !W_ERROR_EQUAL(werr, WERR_NOT_FOUND))
1000         {
1001                 goto done;
1002         }
1003
1004         /*
1005          * Make the store operation as safe as possible without transactions:
1006          *
1007          * (1) For each subkey removed from ctr compared with old_subkeys:
1008          *
1009          *     (a) First delete the value db entry.
1010          *
1011          *     (b) Next delete the secdesc db record.
1012          *
1013          *     (c) Then delete the subkey list entry.
1014          *
1015          * (2) Now write the list of subkeys of the parent key,
1016          *     deleting removed entries and adding new ones.
1017          *
1018          * (3) Finally create the subkey list entries for the added keys.
1019          *
1020          * This way if we crash half-way in between deleting the subkeys
1021          * and storing the parent's list of subkeys, no old data can pop up
1022          * out of the blue when re-adding keys later on.
1023          */
1024
1025         /* (1) delete removed keys' lists (values/secdesc/subkeys) */
1026
1027         num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
1028         for (i=0; i<num_subkeys; i++) {
1029                 oldkeyname = regsubkey_ctr_specific_key(old_subkeys, i);
1030
1031                 if (regsubkey_ctr_key_exists(store_ctx->ctr, oldkeyname)) {
1032                         /*
1033                          * It's still around, don't delete
1034                          */
1035                         continue;
1036                 }
1037
1038                 path = talloc_asprintf(mem_ctx, "%s\\%s", store_ctx->key,
1039                                        oldkeyname);
1040                 if (!path) {
1041                         werr = WERR_NOMEM;
1042                         goto done;
1043                 }
1044
1045                 werr = regdb_delete_key_lists(db, path);
1046                 W_ERROR_NOT_OK_GOTO_DONE(werr);
1047
1048                 TALLOC_FREE(path);
1049         }
1050
1051         TALLOC_FREE(old_subkeys);
1052
1053         /* (2) store the subkey list for the parent */
1054
1055         werr = regdb_store_keys_internal2(db, store_ctx->key, store_ctx->ctr);
1056         if (!W_ERROR_IS_OK(werr)) {
1057                 DEBUG(0,("regdb_store_keys: Failed to store new subkey list "
1058                          "for parent [%s]: %s\n", store_ctx->key,
1059                          win_errstr(werr)));
1060                 goto done;
1061         }
1062
1063         /* (3) now create records for any subkeys that don't already exist */
1064
1065         num_subkeys = regsubkey_ctr_numkeys(store_ctx->ctr);
1066
1067         for (i=0; i<num_subkeys; i++) {
1068                 const char *subkey;
1069
1070                 subkey = regsubkey_ctr_specific_key(store_ctx->ctr, i);
1071
1072                 werr = regdb_store_subkey_list(db, store_ctx->key, subkey);
1073                 W_ERROR_NOT_OK_GOTO_DONE(werr);
1074         }
1075
1076         werr = WERR_OK;
1077
1078 done:
1079         talloc_free(mem_ctx);
1080         return werror_to_ntstatus(werr);
1081 }
1082
1083 static bool regdb_store_keys_internal(struct db_context *db, const char *key,
1084                                       struct regsubkey_ctr *ctr)
1085 {
1086         int num_subkeys, old_num_subkeys, i;
1087         struct regsubkey_ctr *old_subkeys = NULL;
1088         TALLOC_CTX *ctx = talloc_stackframe();
1089         WERROR werr;
1090         bool ret = false;
1091         struct regdb_store_keys_context store_ctx;
1092
1093         if (!regdb_key_exists(db, key)) {
1094                 goto done;
1095         }
1096
1097         /*
1098          * fetch a list of the old subkeys so we can determine if anything has
1099          * changed
1100          */
1101
1102         werr = regsubkey_ctr_init(ctx, &old_subkeys);
1103         if (!W_ERROR_IS_OK(werr)) {
1104                 DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
1105                 goto done;
1106         }
1107
1108         werr = regdb_fetch_keys_internal(db, key, old_subkeys);
1109         if (!W_ERROR_IS_OK(werr) &&
1110             !W_ERROR_EQUAL(werr, WERR_NOT_FOUND))
1111         {
1112                 goto done;
1113         }
1114
1115         num_subkeys = regsubkey_ctr_numkeys(ctr);
1116         old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
1117         if ((num_subkeys && old_num_subkeys) &&
1118             (num_subkeys == old_num_subkeys)) {
1119
1120                 for (i = 0; i < num_subkeys; i++) {
1121                         if (strcmp(regsubkey_ctr_specific_key(ctr, i),
1122                                    regsubkey_ctr_specific_key(old_subkeys, i))
1123                             != 0)
1124                         {
1125                                 break;
1126                         }
1127                 }
1128                 if (i == num_subkeys) {
1129                         /*
1130                          * Nothing changed, no point to even start a tdb
1131                          * transaction
1132                          */
1133
1134                         ret = true;
1135                         goto done;
1136                 }
1137         }
1138
1139         TALLOC_FREE(old_subkeys);
1140
1141         store_ctx.key = key;
1142         store_ctx.ctr = ctr;
1143
1144         werr = ntstatus_to_werror(dbwrap_trans_do(db,
1145                                                   regdb_store_keys_action,
1146                                                   &store_ctx));
1147
1148         ret = W_ERROR_IS_OK(werr);
1149
1150 done:
1151         TALLOC_FREE(ctx);
1152
1153         return ret;
1154 }
1155
1156 bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
1157 {
1158         return regdb_store_keys_internal(regdb, key, ctr);
1159 }
1160
1161 /**
1162  * create a subkey of a given key
1163  */
1164
1165 struct regdb_create_subkey_context {
1166         const char *key;
1167         const char *subkey;
1168 };
1169
1170 static NTSTATUS regdb_create_subkey_action(struct db_context *db,
1171                                            void *private_data)
1172 {
1173         WERROR werr;
1174         struct regdb_create_subkey_context *create_ctx;
1175         struct regsubkey_ctr *subkeys;
1176         TALLOC_CTX *mem_ctx = talloc_stackframe();
1177
1178         create_ctx = (struct regdb_create_subkey_context *)private_data;
1179
1180         werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1181         W_ERROR_NOT_OK_GOTO_DONE(werr);
1182
1183         werr = regdb_fetch_keys_internal(db, create_ctx->key, subkeys);
1184         W_ERROR_NOT_OK_GOTO_DONE(werr);
1185
1186         werr = regsubkey_ctr_addkey(subkeys, create_ctx->subkey);
1187         W_ERROR_NOT_OK_GOTO_DONE(werr);
1188
1189         werr = regdb_store_keys_internal2(db, create_ctx->key, subkeys);
1190         if (!W_ERROR_IS_OK(werr)) {
1191                 DEBUG(0, (__location__ " failed to store new subkey list for "
1192                          "parent key %s: %s\n", create_ctx->key,
1193                          win_errstr(werr)));
1194         }
1195
1196         werr = regdb_store_subkey_list(db, create_ctx->key, create_ctx->subkey);
1197
1198 done:
1199         talloc_free(mem_ctx);
1200         return werror_to_ntstatus(werr);
1201 }
1202
1203 static WERROR regdb_create_subkey_internal(struct db_context *db,
1204                                            const char *key,
1205                                            const char *subkey)
1206 {
1207         WERROR werr;
1208         struct regsubkey_ctr *subkeys;
1209         TALLOC_CTX *mem_ctx = talloc_stackframe();
1210         struct regdb_create_subkey_context create_ctx;
1211
1212         if (!regdb_key_exists(db, key)) {
1213                 werr = WERR_NOT_FOUND;
1214                 goto done;
1215         }
1216
1217         werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1218         W_ERROR_NOT_OK_GOTO_DONE(werr);
1219
1220         werr = regdb_fetch_keys_internal(db, key, subkeys);
1221         W_ERROR_NOT_OK_GOTO_DONE(werr);
1222
1223         if (regsubkey_ctr_key_exists(subkeys, subkey)) {
1224                 werr = WERR_OK;
1225                 goto done;
1226         }
1227
1228         talloc_free(subkeys);
1229
1230         create_ctx.key = key;
1231         create_ctx.subkey = subkey;
1232
1233         werr = ntstatus_to_werror(dbwrap_trans_do(db,
1234                                                   regdb_create_subkey_action,
1235                                                   &create_ctx));
1236
1237 done:
1238         talloc_free(mem_ctx);
1239         return werr;
1240 }
1241
1242 static WERROR regdb_create_subkey(const char *key, const char *subkey)
1243 {
1244         return regdb_create_subkey_internal(regdb, key, subkey);
1245 }
1246
1247 /**
1248  * create a base key
1249  */
1250
1251 struct regdb_create_basekey_context {
1252         const char *key;
1253 };
1254
1255 static NTSTATUS regdb_create_basekey_action(struct db_context *db,
1256                                             void *private_data)
1257 {
1258         WERROR werr;
1259         struct regdb_create_basekey_context *create_ctx;
1260
1261         create_ctx = (struct regdb_create_basekey_context *)private_data;
1262
1263         werr = regdb_store_subkey_list(db, NULL, create_ctx->key);
1264
1265         return werror_to_ntstatus(werr);
1266 }
1267
1268 static WERROR regdb_create_basekey(struct db_context *db, const char *key)
1269 {
1270         WERROR werr;
1271         struct regdb_create_subkey_context create_ctx;
1272
1273         create_ctx.key = key;
1274
1275         werr = ntstatus_to_werror(dbwrap_trans_do(db,
1276                                                   regdb_create_basekey_action,
1277                                                   &create_ctx));
1278
1279         return werr;
1280 }
1281
1282 /**
1283  * create a subkey of a given key
1284  */
1285
1286 struct regdb_delete_subkey_context {
1287         const char *key;
1288         const char *subkey;
1289         const char *path;
1290 };
1291
1292 static NTSTATUS regdb_delete_subkey_action(struct db_context *db,
1293                                            void *private_data)
1294 {
1295         WERROR werr;
1296         struct regdb_delete_subkey_context *delete_ctx;
1297         struct regsubkey_ctr *subkeys;
1298         TALLOC_CTX *mem_ctx = talloc_stackframe();
1299
1300         delete_ctx = (struct regdb_delete_subkey_context *)private_data;
1301
1302         werr = regdb_delete_key_lists(db, delete_ctx->path);
1303         W_ERROR_NOT_OK_GOTO_DONE(werr);
1304
1305         werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1306         W_ERROR_NOT_OK_GOTO_DONE(werr);
1307
1308         werr = regdb_fetch_keys_internal(db, delete_ctx->key, subkeys);
1309         W_ERROR_NOT_OK_GOTO_DONE(werr);
1310
1311         werr = regsubkey_ctr_delkey(subkeys, delete_ctx->subkey);
1312         W_ERROR_NOT_OK_GOTO_DONE(werr);
1313
1314         werr = regdb_store_keys_internal2(db, delete_ctx->key, subkeys);
1315         if (!W_ERROR_IS_OK(werr)) {
1316                 DEBUG(0, (__location__ " failed to store new subkey_list for "
1317                          "parent key %s: %s\n", delete_ctx->key,
1318                          win_errstr(werr)));
1319         }
1320
1321 done:
1322         talloc_free(mem_ctx);
1323         return werror_to_ntstatus(werr);
1324 }
1325
1326 static WERROR regdb_delete_subkey(const char *key, const char *subkey)
1327 {
1328         WERROR werr;
1329         char *path;
1330         struct regdb_delete_subkey_context delete_ctx;
1331         TALLOC_CTX *mem_ctx = talloc_stackframe();
1332
1333         if (!regdb_key_exists(regdb, key)) {
1334                 werr = WERR_NOT_FOUND;
1335                 goto done;
1336         }
1337
1338         path = talloc_asprintf(mem_ctx, "%s\\%s", key, subkey);
1339         if (path == NULL) {
1340                 werr = WERR_NOMEM;
1341                 goto done;
1342         }
1343
1344         if (!regdb_key_exists(regdb, path)) {
1345                 werr = WERR_OK;
1346                 goto done;
1347         }
1348
1349         delete_ctx.key = key;
1350         delete_ctx.subkey = subkey;
1351         delete_ctx.path = path;
1352
1353         werr = ntstatus_to_werror(dbwrap_trans_do(regdb,
1354                                                   regdb_delete_subkey_action,
1355                                                   &delete_ctx));
1356
1357 done:
1358         talloc_free(mem_ctx);
1359         return werr;
1360 }
1361
1362 static TDB_DATA regdb_fetch_key_internal(struct db_context *db,
1363                                          TALLOC_CTX *mem_ctx, const char *key)
1364 {
1365         char *path = NULL;
1366         TDB_DATA data;
1367
1368         path = normalize_reg_path(mem_ctx, key);
1369         if (!path) {
1370                 return make_tdb_data(NULL, 0);
1371         }
1372
1373         data = dbwrap_fetch_bystring(db, mem_ctx, path);
1374
1375         TALLOC_FREE(path);
1376         return data;
1377 }
1378
1379
1380 /**
1381  * Check for the existence of a key.
1382  *
1383  * Existence of a key is authoritatively defined by
1384  * the existence of the record that contains the list
1385  * of its subkeys.
1386  */
1387 static bool regdb_key_exists(struct db_context *db, const char *key)
1388 {
1389         TALLOC_CTX *mem_ctx = talloc_stackframe();
1390         TDB_DATA value;
1391         bool ret = false;
1392         char *path;
1393
1394         if (key == NULL) {
1395                 goto done;
1396         }
1397
1398         path = normalize_reg_path(mem_ctx, key);
1399         if (path == NULL) {
1400                 DEBUG(0, ("out of memory! (talloc failed)\n"));
1401                 goto done;
1402         }
1403
1404         if (*path == '\0') {
1405                 goto done;
1406         }
1407
1408         value = regdb_fetch_key_internal(db, mem_ctx, path);
1409         ret = (value.dptr != NULL);
1410
1411 done:
1412         TALLOC_FREE(mem_ctx);
1413         return ret;
1414 }
1415
1416
1417 /***********************************************************************
1418  Retrieve an array of strings containing subkeys.  Memory should be
1419  released by the caller.
1420  ***********************************************************************/
1421
1422 static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
1423                                         struct regsubkey_ctr *ctr)
1424 {
1425         WERROR werr;
1426         uint32_t num_items;
1427         uint8 *buf;
1428         uint32 buflen, len;
1429         int i;
1430         fstring subkeyname;
1431         TALLOC_CTX *frame = talloc_stackframe();
1432         TDB_DATA value;
1433
1434         DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL"));
1435
1436         if (!regdb_key_exists(db, key)) {
1437                 DEBUG(10, ("key [%s] not found\n", key));
1438                 werr = WERR_NOT_FOUND;
1439                 goto done;
1440         }
1441
1442         werr = regsubkey_ctr_reinit(ctr);
1443         W_ERROR_NOT_OK_GOTO_DONE(werr);
1444
1445         werr = regsubkey_ctr_set_seqnum(ctr, db->get_seqnum(db));
1446         W_ERROR_NOT_OK_GOTO_DONE(werr);
1447
1448         value = regdb_fetch_key_internal(db, frame, key);
1449
1450         if (value.dsize == 0 || value.dptr == NULL) {
1451                 DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n",
1452                            key));
1453                 goto done;
1454         }
1455
1456         buf = value.dptr;
1457         buflen = value.dsize;
1458         len = tdb_unpack( buf, buflen, "d", &num_items);
1459         if (len == (uint32_t)-1) {
1460                 werr = WERR_NOT_FOUND;
1461                 goto done;
1462         }
1463
1464         for (i=0; i<num_items; i++) {
1465                 len += tdb_unpack(buf+len, buflen-len, "f", subkeyname);
1466                 werr = regsubkey_ctr_addkey(ctr, subkeyname);
1467                 if (!W_ERROR_IS_OK(werr)) {
1468                         DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey "
1469                                   "failed: %s\n", win_errstr(werr)));
1470                         num_items = 0;
1471                         goto done;
1472                 }
1473         }
1474
1475         DEBUG(11,("regdb_fetch_keys: Exit [%d] items\n", num_items));
1476
1477 done:
1478         TALLOC_FREE(frame);
1479         return werr;
1480 }
1481
1482 int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr)
1483 {
1484         WERROR werr;
1485
1486         werr = regdb_fetch_keys_internal(regdb, key, ctr);
1487         if (!W_ERROR_IS_OK(werr)) {
1488                 return -1;
1489         }
1490
1491         return regsubkey_ctr_numkeys(ctr);
1492 }
1493
1494 /****************************************************************************
1495  Unpack a list of registry values frem the TDB
1496  ***************************************************************************/
1497
1498 static int regdb_unpack_values(struct regval_ctr *values, uint8 *buf, int buflen)
1499 {
1500         int             len = 0;
1501         uint32          type;
1502         fstring valuename;
1503         uint32          size;
1504         uint8           *data_p;
1505         uint32          num_values = 0;
1506         int             i;
1507
1508         /* loop and unpack the rest of the registry values */
1509
1510         len += tdb_unpack(buf+len, buflen-len, "d", &num_values);
1511
1512         for ( i=0; i<num_values; i++ ) {
1513                 /* unpack the next regval */
1514
1515                 type = REG_NONE;
1516                 size = 0;
1517                 data_p = NULL;
1518                 valuename[0] = '\0';
1519                 len += tdb_unpack(buf+len, buflen-len, "fdB",
1520                                   valuename,
1521                                   &type,
1522                                   &size,
1523                                   &data_p);
1524
1525                 regval_ctr_addvalue(values, valuename, type,
1526                                 (uint8_t *)data_p, size);
1527                 SAFE_FREE(data_p); /* 'B' option to tdb_unpack does a malloc() */
1528
1529                 DEBUG(8,("specific: [%s], len: %d\n", valuename, size));
1530         }
1531
1532         return len;
1533 }
1534
1535 /****************************************************************************
1536  Pack all values in all printer keys
1537  ***************************************************************************/
1538
1539 static int regdb_pack_values(struct regval_ctr *values, uint8 *buf, int buflen)
1540 {
1541         int             len = 0;
1542         int             i;
1543         struct regval_blob      *val;
1544         int             num_values;
1545
1546         if ( !values )
1547                 return 0;
1548
1549         num_values = regval_ctr_numvals( values );
1550
1551         /* pack the number of values first */
1552
1553         len += tdb_pack( buf+len, buflen-len, "d", num_values );
1554
1555         /* loop over all values */
1556
1557         for ( i=0; i<num_values; i++ ) {
1558                 val = regval_ctr_specific_value( values, i );
1559                 len += tdb_pack(buf+len, buflen-len, "fdB",
1560                                 regval_name(val),
1561                                 regval_type(val),
1562                                 regval_size(val),
1563                                 regval_data_p(val) );
1564         }
1565
1566         return len;
1567 }
1568
1569 /***********************************************************************
1570  Retrieve an array of strings containing subkeys.  Memory should be
1571  released by the caller.
1572  ***********************************************************************/
1573
1574 static int regdb_fetch_values_internal(struct db_context *db, const char* key,
1575                                        struct regval_ctr *values)
1576 {
1577         char *keystr = NULL;
1578         TALLOC_CTX *ctx = talloc_stackframe();
1579         int ret = 0;
1580         TDB_DATA value;
1581         WERROR werr;
1582
1583         DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key));
1584
1585         if (!regdb_key_exists(db, key)) {
1586                 goto done;
1587         }
1588
1589         keystr = talloc_asprintf(ctx, "%s\\%s", REG_VALUE_PREFIX, key);
1590         if (!keystr) {
1591                 goto done;
1592         }
1593
1594         werr = regval_ctr_set_seqnum(values, db->get_seqnum(db));
1595         W_ERROR_NOT_OK_GOTO_DONE(werr);
1596
1597         value = regdb_fetch_key_internal(db, ctx, keystr);
1598
1599         if (!value.dptr) {
1600                 /* all keys have zero values by default */
1601                 goto done;
1602         }
1603
1604         regdb_unpack_values(values, value.dptr, value.dsize);
1605         ret = regval_ctr_numvals(values);
1606
1607 done:
1608         TALLOC_FREE(ctx);
1609         return ret;
1610 }
1611
1612 int regdb_fetch_values(const char* key, struct regval_ctr *values)
1613 {
1614         return regdb_fetch_values_internal(regdb, key, values);
1615 }
1616
1617 static bool regdb_store_values_internal(struct db_context *db, const char *key,
1618                                         struct regval_ctr *values)
1619 {
1620         TDB_DATA old_data, data;
1621         char *keystr = NULL;
1622         TALLOC_CTX *ctx = talloc_stackframe();
1623         int len;
1624         NTSTATUS status;
1625         bool result = false;
1626
1627         DEBUG(10,("regdb_store_values: Looking for value of key [%s] \n", key));
1628
1629         if (!regdb_key_exists(db, key)) {
1630                 goto done;
1631         }
1632
1633         ZERO_STRUCT(data);
1634
1635         len = regdb_pack_values(values, data.dptr, data.dsize);
1636         if (len <= 0) {
1637                 DEBUG(0,("regdb_store_values: unable to pack values. len <= 0\n"));
1638                 goto done;
1639         }
1640
1641         data.dptr = talloc_array(ctx, uint8, len);
1642         data.dsize = len;
1643
1644         len = regdb_pack_values(values, data.dptr, data.dsize);
1645
1646         SMB_ASSERT( len == data.dsize );
1647
1648         keystr = talloc_asprintf(ctx, "%s\\%s", REG_VALUE_PREFIX, key );
1649         if (!keystr) {
1650                 goto done;
1651         }
1652         keystr = normalize_reg_path(ctx, keystr);
1653         if (!keystr) {
1654                 goto done;
1655         }
1656
1657         old_data = dbwrap_fetch_bystring(db, ctx, keystr);
1658
1659         if ((old_data.dptr != NULL)
1660             && (old_data.dsize == data.dsize)
1661             && (memcmp(old_data.dptr, data.dptr, data.dsize) == 0))
1662         {
1663                 result = true;
1664                 goto done;
1665         }
1666
1667         status = dbwrap_trans_store_bystring(db, keystr, data, TDB_REPLACE);
1668
1669         result = NT_STATUS_IS_OK(status);
1670
1671 done:
1672         TALLOC_FREE(ctx);
1673         return result;
1674 }
1675
1676 bool regdb_store_values(const char *key, struct regval_ctr *values)
1677 {
1678         return regdb_store_values_internal(regdb, key, values);
1679 }
1680
1681 static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key,
1682                                 struct security_descriptor **psecdesc)
1683 {
1684         char *tdbkey;
1685         TDB_DATA data;
1686         NTSTATUS status;
1687         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1688         WERROR err = WERR_OK;
1689
1690         DEBUG(10, ("regdb_get_secdesc: Getting secdesc of key [%s]\n", key));
1691
1692         if (!regdb_key_exists(regdb, key)) {
1693                 err = WERR_BADFILE;
1694                 goto done;
1695         }
1696
1697         tdbkey = talloc_asprintf(tmp_ctx, "%s\\%s", REG_SECDESC_PREFIX, key);
1698         if (tdbkey == NULL) {
1699                 err = WERR_NOMEM;
1700                 goto done;
1701         }
1702
1703         tdbkey = normalize_reg_path(tmp_ctx, tdbkey);
1704         if (tdbkey == NULL) {
1705                 err = WERR_NOMEM;
1706                 goto done;
1707         }
1708
1709         data = dbwrap_fetch_bystring(regdb, tmp_ctx, tdbkey);
1710         if (data.dptr == NULL) {
1711                 err = WERR_BADFILE;
1712                 goto done;
1713         }
1714
1715         status = unmarshall_sec_desc(mem_ctx, (uint8 *)data.dptr, data.dsize,
1716                                      psecdesc);
1717
1718         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1719                 err = WERR_NOMEM;
1720         } else if (!NT_STATUS_IS_OK(status)) {
1721                 err = WERR_REG_CORRUPT;
1722         }
1723
1724 done:
1725         TALLOC_FREE(tmp_ctx);
1726         return err;
1727 }
1728
1729 static WERROR regdb_set_secdesc(const char *key,
1730                                 struct security_descriptor *secdesc)
1731 {
1732         TALLOC_CTX *mem_ctx = talloc_stackframe();
1733         char *tdbkey;
1734         WERROR err = WERR_NOMEM;
1735         TDB_DATA tdbdata;
1736
1737         if (!regdb_key_exists(regdb, key)) {
1738                 err = WERR_BADFILE;
1739                 goto done;
1740         }
1741
1742         tdbkey = talloc_asprintf(mem_ctx, "%s\\%s", REG_SECDESC_PREFIX, key);
1743         if (tdbkey == NULL) {
1744                 goto done;
1745         }
1746
1747         tdbkey = normalize_reg_path(mem_ctx, tdbkey);
1748         if (tdbkey == NULL) {
1749                 err = WERR_NOMEM;
1750                 goto done;
1751         }
1752
1753         if (secdesc == NULL) {
1754                 /* assuming a delete */
1755                 err = ntstatus_to_werror(dbwrap_trans_delete_bystring(regdb,
1756                                                                       tdbkey));
1757                 goto done;
1758         }
1759
1760         err = ntstatus_to_werror(marshall_sec_desc(mem_ctx, secdesc,
1761                                                    &tdbdata.dptr,
1762                                                    &tdbdata.dsize));
1763         W_ERROR_NOT_OK_GOTO_DONE(err);
1764
1765         err = ntstatus_to_werror(dbwrap_trans_store_bystring(regdb, tdbkey,
1766                                                              tdbdata, 0));
1767
1768  done:
1769         TALLOC_FREE(mem_ctx);
1770         return err;
1771 }
1772
1773 bool regdb_subkeys_need_update(struct regsubkey_ctr *subkeys)
1774 {
1775         return (regdb_get_seqnum() != regsubkey_ctr_get_seqnum(subkeys));
1776 }
1777
1778 bool regdb_values_need_update(struct regval_ctr *values)
1779 {
1780         return (regdb_get_seqnum() != regval_ctr_get_seqnum(values));
1781 }
1782
1783 /*
1784  * Table of function pointers for default access
1785  */
1786
1787 struct registry_ops regdb_ops = {
1788         .fetch_subkeys = regdb_fetch_keys,
1789         .fetch_values = regdb_fetch_values,
1790         .store_subkeys = regdb_store_keys,
1791         .store_values = regdb_store_values,
1792         .create_subkey = regdb_create_subkey,
1793         .delete_subkey = regdb_delete_subkey,
1794         .get_secdesc = regdb_get_secdesc,
1795         .set_secdesc = regdb_set_secdesc,
1796         .subkeys_need_update = regdb_subkeys_need_update,
1797         .values_need_update = regdb_values_need_update
1798 };