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