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