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