libsmbconf: refactor get_includes on opened key into smbconf_reg_get_includes_internal()
[amitay/samba.git] / source3 / lib / smbconf / smbconf_reg.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  libsmbconf - Samba configuration library, registry backend
4  *  Copyright (C) Michael Adam 2008
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "smbconf_private.h"
22
23 #define INCLUDES_VALNAME "includes"
24
25 struct reg_private_data {
26         NT_USER_TOKEN *token;
27         bool open;              /* did _we_ open the registry? */
28 };
29
30 /**********************************************************************
31  *
32  * helper functions
33  *
34  **********************************************************************/
35
36 /**
37  * a convenience helper to cast the private data structure
38  */
39 static struct reg_private_data *rpd(struct smbconf_ctx *ctx)
40 {
41         return (struct reg_private_data *)(ctx->data);
42 }
43
44 /*
45  * check whether a given value name is forbidden in registry (smbconf)
46  */
47 static bool smbconf_reg_valname_forbidden(const char *valname)
48 {
49         /* hard code the list of forbidden names here for now */
50         const char *forbidden_valnames[] = {
51                 "lock directory",
52                 "lock dir",
53                 "config backend",
54                 NULL
55         };
56         const char **forbidden = NULL;
57
58         for (forbidden = forbidden_valnames; *forbidden != NULL; forbidden++) {
59                 if (strwicmp(valname, *forbidden) == 0) {
60                         return true;
61                 }
62         }
63         return false;
64 }
65
66 /**
67  * Open a registry key specified by "path"
68  */
69 static WERROR smbconf_reg_open_path(TALLOC_CTX *mem_ctx,
70                                     struct smbconf_ctx *ctx,
71                                     const char *path,
72                                     uint32 desired_access,
73                                     struct registry_key **key)
74 {
75         WERROR werr = WERR_OK;
76
77         if (ctx == NULL) {
78                 DEBUG(1, ("Error: configuration is not open!\n"));
79                 werr = WERR_INVALID_PARAM;
80                 goto done;
81         }
82
83         if (rpd(ctx)->token == NULL) {
84                 DEBUG(1, ("Error: token missing from smbconf_ctx. "
85                           "was smbconf_init() called?\n"));
86                 werr = WERR_INVALID_PARAM;
87                 goto done;
88         }
89
90         werr = ctx->ops->open_conf(ctx);
91         if (!W_ERROR_IS_OK(werr)) {
92                 DEBUG(1, ("Error opening the registry.\n"));
93                 goto done;
94         }
95
96         if (path == NULL) {
97                 DEBUG(1, ("Error: NULL path string given\n"));
98                 werr = WERR_INVALID_PARAM;
99                 goto done;
100         }
101
102         werr = reg_open_path(mem_ctx, path, desired_access, rpd(ctx)->token,
103                              key);
104
105         if (!W_ERROR_IS_OK(werr)) {
106                 DEBUG(1, ("Error opening registry path '%s': %s\n",
107                           path, dos_errstr(werr)));
108         }
109
110 done:
111         return werr;
112 }
113
114 /**
115  * Open a subkey of the base key (i.e a service)
116  */
117 static WERROR smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
118                                            struct smbconf_ctx *ctx,
119                                            const char *servicename,
120                                            uint32 desired_access,
121                                            struct registry_key **key)
122 {
123         WERROR werr = WERR_OK;
124         char *path = NULL;
125
126         if (servicename == NULL) {
127                 DEBUG(3, ("Error: NULL servicename given.\n"));
128                 werr = WERR_INVALID_PARAM;
129                 goto done;
130         }
131
132         path = talloc_asprintf(mem_ctx, "%s\\%s", ctx->path, servicename);
133         if (path == NULL) {
134                 werr = WERR_NOMEM;
135                 goto done;
136         }
137
138         werr = smbconf_reg_open_path(mem_ctx, ctx, path, desired_access, key);
139
140 done:
141         TALLOC_FREE(path);
142         return werr;
143 }
144
145 /**
146  * open the base key
147  */
148 static WERROR smbconf_reg_open_base_key(TALLOC_CTX *mem_ctx,
149                                         struct smbconf_ctx *ctx,
150                                         uint32 desired_access,
151                                         struct registry_key **key)
152 {
153         return smbconf_reg_open_path(mem_ctx, ctx, ctx->path, desired_access,
154                                      key);
155 }
156
157 /**
158  * check if a value exists in a given registry key
159  */
160 static bool smbconf_value_exists(struct registry_key *key, const char *param)
161 {
162         bool ret = false;
163         WERROR werr = WERR_OK;
164         TALLOC_CTX *ctx = talloc_stackframe();
165         struct registry_value *value = NULL;
166
167         werr = reg_queryvalue(ctx, key, param, &value);
168         if (W_ERROR_IS_OK(werr)) {
169                 ret = true;
170         }
171
172         TALLOC_FREE(ctx);
173         return ret;
174 }
175
176 /**
177  * create a subkey of the base key (i.e. a service...)
178  */
179 static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
180                                              struct smbconf_ctx *ctx,
181                                              const char * subkeyname,
182                                              struct registry_key **newkey)
183 {
184         WERROR werr = WERR_OK;
185         struct registry_key *create_parent = NULL;
186         TALLOC_CTX *create_ctx;
187         enum winreg_CreateAction action = REG_ACTION_NONE;
188
189         /* create a new talloc ctx for creation. it will hold
190          * the intermediate parent key (SMBCONF) for creation
191          * and will be destroyed when leaving this function... */
192         if (!(create_ctx = talloc_stackframe())) {
193                 werr = WERR_NOMEM;
194                 goto done;
195         }
196
197         werr = smbconf_reg_open_base_key(create_ctx, ctx, REG_KEY_WRITE,
198                                          &create_parent);
199         if (!W_ERROR_IS_OK(werr)) {
200                 goto done;
201         }
202
203         werr = reg_createkey(mem_ctx, create_parent, subkeyname,
204                              REG_KEY_WRITE, newkey, &action);
205         if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
206                 DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
207                 werr = WERR_ALREADY_EXISTS;
208         }
209         if (!W_ERROR_IS_OK(werr)) {
210                 DEBUG(5, ("Error creating key %s: %s\n",
211                          subkeyname, dos_errstr(werr)));
212         }
213
214 done:
215         TALLOC_FREE(create_ctx);
216         return werr;
217 }
218
219 /**
220  * add a value to a key.
221  */
222 static WERROR smbconf_reg_set_value(struct registry_key *key,
223                                     const char *valname,
224                                     const char *valstr)
225 {
226         struct registry_value val;
227         WERROR werr = WERR_OK;
228         char *subkeyname;
229         const char *canon_valname;
230         const char *canon_valstr;
231
232         if (!lp_canonicalize_parameter_with_value(valname, valstr,
233                                                   &canon_valname,
234                                                   &canon_valstr))
235         {
236                 if (canon_valname == NULL) {
237                         DEBUG(5, ("invalid parameter '%s' given\n",
238                                   valname));
239                 } else {
240                         DEBUG(5, ("invalid value '%s' given for "
241                                   "parameter '%s'\n", valstr, valname));
242                 }
243                 werr = WERR_INVALID_PARAM;
244                 goto done;
245         }
246
247         if (smbconf_reg_valname_forbidden(canon_valname)) {
248                 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
249                           canon_valname));
250                 werr = WERR_INVALID_PARAM;
251                 goto done;
252         }
253
254         subkeyname = strrchr_m(key->key->name, '\\');
255         if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
256                 DEBUG(5, ("Invalid registry key '%s' given as "
257                           "smbconf section.\n", key->key->name));
258                 werr = WERR_INVALID_PARAM;
259                 goto done;
260         }
261         subkeyname++;
262         if (!strequal(subkeyname, GLOBAL_NAME) &&
263             lp_parameter_is_global(valname))
264         {
265                 DEBUG(5, ("Global paramter '%s' not allowed in "
266                           "service definition ('%s').\n", canon_valname,
267                           subkeyname));
268                 werr = WERR_INVALID_PARAM;
269                 goto done;
270         }
271
272         ZERO_STRUCT(val);
273
274         val.type = REG_SZ;
275         val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
276         val.v.sz.len = strlen(canon_valstr) + 1;
277
278         werr = reg_setvalue(key, canon_valname, &val);
279         if (!W_ERROR_IS_OK(werr)) {
280                 DEBUG(5, ("Error adding value '%s' to "
281                           "key '%s': %s\n",
282                           canon_valname, key->key->name, dos_errstr(werr)));
283         }
284
285 done:
286         return werr;
287 }
288
289 static WERROR smbconf_reg_set_multi_sz_value(struct registry_key *key,
290                                              const char *valname,
291                                              const uint32_t num_strings,
292                                              const char **strings)
293 {
294         WERROR werr;
295         struct registry_value *value;
296         uint32_t count;
297         TALLOC_CTX *tmp_ctx = talloc_stackframe();
298
299         if (strings == NULL) {
300                 werr = WERR_INVALID_PARAM;
301                 goto done;
302         }
303
304         value = TALLOC_ZERO_P(tmp_ctx, struct registry_value);
305
306         value->type = REG_MULTI_SZ;
307         value->v.multi_sz.num_strings = num_strings;
308         value->v.multi_sz.strings = TALLOC_ARRAY(tmp_ctx, char *, num_strings);
309         if (value->v.multi_sz.strings == NULL) {
310                 werr = WERR_NOMEM;
311                 goto done;
312         }
313         for (count = 0; count < num_strings; count++) {
314                 value->v.multi_sz.strings[count] =
315                         talloc_strdup(value->v.multi_sz.strings,
316                                       strings[count]);
317                 if (value->v.multi_sz.strings[count] == NULL) {
318                         werr = WERR_NOMEM;
319                         goto done;
320                 }
321         }
322
323         werr = reg_setvalue(key, valname, value);
324         if (!W_ERROR_IS_OK(werr)) {
325                 DEBUG(5, ("Error adding value '%s' to key '%s': %s\n",
326                           valname, key->key->name, dos_errstr(werr)));
327         }
328
329 done:
330         TALLOC_FREE(tmp_ctx);
331         return werr;
332 }
333
334 /**
335  * format a registry_value into a string.
336  *
337  * This is intended to be used for smbconf registry values,
338  * which are ar stored as REG_SZ values, so the incomplete
339  * handling should be ok.
340  */
341 static char *smbconf_format_registry_value(TALLOC_CTX *mem_ctx,
342                                            struct registry_value *value)
343 {
344         char *result = NULL;
345
346         /* alternatively, create a new talloc context? */
347         if (mem_ctx == NULL) {
348                 return result;
349         }
350
351         switch (value->type) {
352         case REG_DWORD:
353                 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
354                 break;
355         case REG_SZ:
356         case REG_EXPAND_SZ:
357                 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
358                 break;
359         case REG_MULTI_SZ: {
360                 uint32 j;
361                 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
362                         result = talloc_asprintf(mem_ctx, "%s\"%s\" ",
363                                                  result ? result : "" ,
364                                                  value->v.multi_sz.strings[j]);
365                         if (result == NULL) {
366                                 break;
367                         }
368                 }
369                 break;
370         }
371         case REG_BINARY:
372                 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
373                                          (int)value->v.binary.length);
374                 break;
375         default:
376                 result = talloc_asprintf(mem_ctx, "<unprintable>");
377                 break;
378         }
379         return result;
380 }
381
382 static WERROR smbconf_reg_get_includes_internal(TALLOC_CTX *mem_ctx,
383                                                 struct registry_key *key,
384                                                 uint32_t *num_includes,
385                                                 char ***includes)
386 {
387         WERROR werr;
388         uint32_t count;
389         struct registry_value *value = NULL;
390         char **tmp_includes = NULL;
391         TALLOC_CTX *tmp_ctx = talloc_stackframe();
392
393         if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
394                 /* no includes */
395                 goto done;
396         }
397
398         werr = reg_queryvalue(tmp_ctx, key, INCLUDES_VALNAME, &value);
399         if (!W_ERROR_IS_OK(werr)) {
400                 goto done;
401         }
402
403         if (value->type != REG_MULTI_SZ) {
404                 /* wront type -- ignore */
405                 goto done;
406         }
407
408         for (count = 0; count < value->v.multi_sz.num_strings; count++)
409         {
410                 werr = smbconf_add_string_to_array(tmp_ctx,
411                                         &tmp_includes,
412                                         count,
413                                         value->v.multi_sz.strings[count]);
414                 if (!W_ERROR_IS_OK(werr)) {
415                         goto done;
416                 }
417         }
418
419         if (count > 0) {
420                 *includes = talloc_move(mem_ctx, &tmp_includes);
421                 if (*includes == NULL) {
422                         werr = WERR_NOMEM;
423                         goto done;
424                 }
425                 *num_includes = count;
426         } else {
427                 *num_includes = 0;
428                 *includes = NULL;
429         }
430
431 done:
432         TALLOC_FREE(tmp_ctx);
433         return werr;
434 }
435
436 /**
437  * Get the values of a key as a list of value names
438  * and a list of value strings (ordered)
439  */
440 static WERROR smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
441                                      struct registry_key *key,
442                                      uint32_t *num_values,
443                                      char ***value_names,
444                                      char ***value_strings)
445 {
446         TALLOC_CTX *tmp_ctx = NULL;
447         WERROR werr = WERR_OK;
448         uint32_t count;
449         struct registry_value *valvalue = NULL;
450         char *valname = NULL;
451         char **tmp_valnames = NULL;
452         char **tmp_valstrings = NULL;
453
454         if ((num_values == NULL) || (value_names == NULL) ||
455             (value_strings == NULL))
456         {
457                 werr = WERR_INVALID_PARAM;
458                 goto done;
459         }
460
461         tmp_ctx = talloc_stackframe();
462         if (tmp_ctx == NULL) {
463                 werr = WERR_NOMEM;
464                 goto done;
465         }
466
467         for (count = 0;
468              werr = reg_enumvalue(tmp_ctx, key, count, &valname, &valvalue),
469              W_ERROR_IS_OK(werr);
470              count++)
471         {
472                 char *valstring;
473
474                 werr = smbconf_add_string_to_array(tmp_ctx,
475                                                    &tmp_valnames,
476                                                    count, valname);
477                 if (!W_ERROR_IS_OK(werr)) {
478                         goto done;
479                 }
480
481                 valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
482                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
483                                                    count, valstring);
484                 if (!W_ERROR_IS_OK(werr)) {
485                         goto done;
486                 }
487         }
488         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
489                 goto done;
490         }
491
492         werr = WERR_OK;
493
494         *num_values = count;
495         if (count > 0) {
496                 *value_names = talloc_move(mem_ctx, &tmp_valnames);
497                 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
498         } else {
499                 *value_names = NULL;
500                 *value_strings = NULL;
501         }
502
503 done:
504         TALLOC_FREE(tmp_ctx);
505         return werr;
506 }
507
508 /**********************************************************************
509  *
510  * smbconf operations: registry implementations
511  *
512  **********************************************************************/
513
514 /**
515  * initialize the registry smbconf backend
516  */
517 static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
518 {
519         WERROR werr = WERR_OK;
520
521         if (path == NULL) {
522                 path = KEY_SMBCONF;
523         }
524         ctx->path = talloc_strdup(ctx, path);
525         if (ctx->path == NULL) {
526                 werr = WERR_NOMEM;
527                 goto done;
528         }
529
530         ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
531
532         werr = ntstatus_to_werror(registry_create_admin_token(ctx,
533                                                         &(rpd(ctx)->token)));
534         if (!W_ERROR_IS_OK(werr)) {
535                 DEBUG(1, ("Error creating admin token\n"));
536                 goto done;
537         }
538         rpd(ctx)->open = false;
539
540         if (!registry_init_smbconf()) {
541                 werr = WERR_REG_IO_FAILURE;
542                 goto done;
543         }
544
545 done:
546         return werr;
547 }
548
549 static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
550 {
551         return ctx->ops->close_conf(ctx);
552 }
553
554 static WERROR smbconf_reg_open(struct smbconf_ctx *ctx)
555 {
556         WERROR werr;
557
558         if (rpd(ctx)->open) {
559                 return WERR_OK;
560         }
561
562         werr = regdb_open();
563         if (W_ERROR_IS_OK(werr)) {
564                 rpd(ctx)->open = true;
565         }
566         return werr;
567 }
568
569 static int smbconf_reg_close(struct smbconf_ctx *ctx)
570 {
571         int ret;
572
573         if (!rpd(ctx)->open) {
574                 return 0;
575         }
576
577         ret = regdb_close();
578         if (ret == 0) {
579                 rpd(ctx)->open = false;
580         }
581         return ret;
582 }
583
584 /**
585  * Get the change sequence number of the given service/parameter.
586  * service and parameter strings may be NULL.
587  */
588 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
589                                 struct smbconf_csn *csn,
590                                 const char *service, const char *param)
591 {
592         if (csn == NULL) {
593                 return;
594         }
595
596         if (!W_ERROR_IS_OK(ctx->ops->open_conf(ctx))) {
597                 return;
598         }
599
600         csn->csn = (uint64_t)regdb_get_seqnum();
601 }
602
603 /**
604  * Drop the whole configuration (restarting empty) - registry version
605  */
606 static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
607 {
608         char *path, *p;
609         WERROR werr = WERR_OK;
610         struct registry_key *parent_key = NULL;
611         struct registry_key *new_key = NULL;
612         TALLOC_CTX* mem_ctx = talloc_stackframe();
613         enum winreg_CreateAction action;
614
615         path = talloc_strdup(mem_ctx, ctx->path);
616         if (path == NULL) {
617                 werr = WERR_NOMEM;
618                 goto done;
619         }
620         p = strrchr(path, '\\');
621         *p = '\0';
622         werr = smbconf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
623                                      &parent_key);
624
625         if (!W_ERROR_IS_OK(werr)) {
626                 goto done;
627         }
628
629         werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
630
631         if (!W_ERROR_IS_OK(werr)) {
632                 goto done;
633         }
634
635         werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
636                              &new_key, &action);
637
638 done:
639         TALLOC_FREE(mem_ctx);
640         return werr;
641 }
642
643 /**
644  * get the list of share names defined in the configuration.
645  * registry version.
646  */
647 static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
648                                           TALLOC_CTX *mem_ctx,
649                                           uint32_t *num_shares,
650                                           char ***share_names)
651 {
652         uint32_t count;
653         uint32_t added_count = 0;
654         TALLOC_CTX *tmp_ctx = NULL;
655         WERROR werr = WERR_OK;
656         struct registry_key *key = NULL;
657         char *subkey_name = NULL;
658         char **tmp_share_names = NULL;
659
660         if ((num_shares == NULL) || (share_names == NULL)) {
661                 werr = WERR_INVALID_PARAM;
662                 goto done;
663         }
664
665         tmp_ctx = talloc_stackframe();
666         if (tmp_ctx == NULL) {
667                 werr = WERR_NOMEM;
668                 goto done;
669         }
670
671         /* make sure "global" is always listed first */
672         if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
673                 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
674                                                    0, GLOBAL_NAME);
675                 if (!W_ERROR_IS_OK(werr)) {
676                         goto done;
677                 }
678                 added_count++;
679         }
680
681         werr = smbconf_reg_open_base_key(tmp_ctx, ctx,
682                                          SEC_RIGHTS_ENUM_SUBKEYS, &key);
683         if (!W_ERROR_IS_OK(werr)) {
684                 goto done;
685         }
686
687         for (count = 0;
688              werr = reg_enumkey(tmp_ctx, key, count, &subkey_name, NULL),
689              W_ERROR_IS_OK(werr);
690              count++)
691         {
692                 if (strequal(subkey_name, GLOBAL_NAME)) {
693                         continue;
694                 }
695
696                 werr = smbconf_add_string_to_array(tmp_ctx,
697                                                    &tmp_share_names,
698                                                    added_count,
699                                                    subkey_name);
700                 if (!W_ERROR_IS_OK(werr)) {
701                         goto done;
702                 }
703                 added_count++;
704         }
705         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
706                 goto done;
707         }
708         werr = WERR_OK;
709
710         *num_shares = added_count;
711         if (added_count > 0) {
712                 *share_names = talloc_move(mem_ctx, &tmp_share_names);
713         } else {
714                 *share_names = NULL;
715         }
716
717 done:
718         TALLOC_FREE(tmp_ctx);
719         return werr;
720 }
721
722 /**
723  * check if a share/service of a given name exists - registry version
724  */
725 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
726                                      const char *servicename)
727 {
728         bool ret = false;
729         WERROR werr = WERR_OK;
730         TALLOC_CTX *mem_ctx = talloc_stackframe();
731         struct registry_key *key = NULL;
732
733         werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
734                                             REG_KEY_READ, &key);
735         if (W_ERROR_IS_OK(werr)) {
736                 ret = true;
737         }
738
739         TALLOC_FREE(mem_ctx);
740         return ret;
741 }
742
743 /**
744  * Add a service if it does not already exist - registry version
745  */
746 static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
747                                        const char *servicename)
748 {
749         WERROR werr;
750         TALLOC_CTX *mem_ctx = talloc_stackframe();
751         struct registry_key *key = NULL;
752
753         werr = smbconf_reg_create_service_key(mem_ctx, ctx, servicename, &key);
754
755         TALLOC_FREE(mem_ctx);
756         return werr;
757 }
758
759 /**
760  * get a definition of a share (service) from configuration.
761  */
762 static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
763                                     TALLOC_CTX *mem_ctx,
764                                     const char *servicename,
765                                     uint32_t *num_params,
766                                     char ***param_names, char ***param_values)
767 {
768         WERROR werr = WERR_OK;
769         struct registry_key *key = NULL;
770
771         werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
772                                             REG_KEY_READ, &key);
773         if (!W_ERROR_IS_OK(werr)) {
774                 goto done;
775         }
776
777         werr = smbconf_reg_get_values(mem_ctx, key, num_params,
778                                       param_names, param_values);
779
780 done:
781         TALLOC_FREE(key);
782         return werr;
783 }
784
785 /**
786  * delete a service from configuration
787  */
788 static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
789                                        const char *servicename)
790 {
791         WERROR werr = WERR_OK;
792         struct registry_key *key = NULL;
793         TALLOC_CTX *mem_ctx = talloc_stackframe();
794
795         werr = smbconf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
796         if (!W_ERROR_IS_OK(werr)) {
797                 goto done;
798         }
799
800         werr = reg_deletekey_recursive(key, key, servicename);
801
802 done:
803         TALLOC_FREE(mem_ctx);
804         return werr;
805 }
806
807 /**
808  * set a configuration parameter to the value provided.
809  */
810 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
811                                         const char *service,
812                                         const char *param,
813                                         const char *valstr)
814 {
815         WERROR werr;
816         struct registry_key *key = NULL;
817         TALLOC_CTX *mem_ctx = talloc_stackframe();
818
819         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
820                                             REG_KEY_WRITE, &key);
821         if (!W_ERROR_IS_OK(werr)) {
822                 goto done;
823         }
824
825         werr = smbconf_reg_set_value(key, param, valstr);
826
827 done:
828         TALLOC_FREE(mem_ctx);
829         return werr;
830 }
831
832 /**
833  * get the value of a configuration parameter as a string
834  */
835 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
836                                         TALLOC_CTX *mem_ctx,
837                                         const char *service,
838                                         const char *param,
839                                         char **valstr)
840 {
841         WERROR werr = WERR_OK;
842         struct registry_key *key = NULL;
843         struct registry_value *value = NULL;
844
845         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
846                                             REG_KEY_READ, &key);
847         if (!W_ERROR_IS_OK(werr)) {
848                 goto done;
849         }
850
851         if (!smbconf_value_exists(key, param)) {
852                 werr = WERR_INVALID_PARAM;
853                 goto done;
854         }
855
856         werr = reg_queryvalue(mem_ctx, key, param, &value);
857         if (!W_ERROR_IS_OK(werr)) {
858                 goto done;
859         }
860
861         *valstr = smbconf_format_registry_value(mem_ctx, value);
862
863         if (*valstr == NULL) {
864                 werr = WERR_NOMEM;
865         }
866
867 done:
868         TALLOC_FREE(key);
869         TALLOC_FREE(value);
870         return werr;
871 }
872
873 /**
874  * delete a parameter from configuration
875  */
876 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
877                                            const char *service,
878                                            const char *param)
879 {
880         struct registry_key *key = NULL;
881         WERROR werr = WERR_OK;
882         TALLOC_CTX *mem_ctx = talloc_stackframe();
883
884         werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
885                                             REG_KEY_ALL, &key);
886         if (!W_ERROR_IS_OK(werr)) {
887                 goto done;
888         }
889
890         if (!smbconf_value_exists(key, param)) {
891                 werr = WERR_INVALID_PARAM;
892                 goto done;
893         }
894
895         werr = reg_deletevalue(key, param);
896
897 done:
898         TALLOC_FREE(mem_ctx);
899         return werr;
900 }
901
902 static WERROR smbconf_reg_get_includes(struct smbconf_ctx *ctx,
903                                        TALLOC_CTX *mem_ctx,
904                                        const char *service,
905                                        uint32_t *num_includes,
906                                        char ***includes)
907 {
908         WERROR werr;
909         struct registry_key *key = NULL;
910         TALLOC_CTX *tmp_ctx = talloc_stackframe();
911
912         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
913                                             REG_KEY_READ, &key);
914         if (!W_ERROR_IS_OK(werr)) {
915                 goto done;
916         }
917
918         werr = smbconf_reg_get_includes_internal(mem_ctx, key, num_includes,
919                                                  includes);
920
921 done:
922         TALLOC_FREE(tmp_ctx);
923         return werr;
924 }
925
926 static WERROR smbconf_reg_set_includes(struct smbconf_ctx *ctx,
927                                        const char *service,
928                                        uint32_t num_includes,
929                                        const char **includes)
930 {
931         WERROR werr = WERR_OK;
932         struct registry_key *key = NULL;
933         TALLOC_CTX *tmp_ctx = talloc_stackframe();
934
935         werr = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
936                                             REG_KEY_ALL, &key);
937         if (!W_ERROR_IS_OK(werr)) {
938                 goto done;
939         }
940
941         werr = smbconf_reg_set_multi_sz_value(key, INCLUDES_VALNAME,
942                                               num_includes, includes);
943
944 done:
945         TALLOC_FREE(tmp_ctx);
946         return werr;
947 }
948
949
950 struct smbconf_ops smbconf_ops_reg = {
951         .init                   = smbconf_reg_init,
952         .shutdown               = smbconf_reg_shutdown,
953         .open_conf              = smbconf_reg_open,
954         .close_conf             = smbconf_reg_close,
955         .get_csn                = smbconf_reg_get_csn,
956         .drop                   = smbconf_reg_drop,
957         .get_share_names        = smbconf_reg_get_share_names,
958         .share_exists           = smbconf_reg_share_exists,
959         .create_share           = smbconf_reg_create_share,
960         .get_share              = smbconf_reg_get_share,
961         .delete_share           = smbconf_reg_delete_share,
962         .set_parameter          = smbconf_reg_set_parameter,
963         .get_parameter          = smbconf_reg_get_parameter,
964         .delete_parameter       = smbconf_reg_delete_parameter,
965         .get_includes           = smbconf_reg_get_includes,
966         .set_includes           = smbconf_reg_set_includes,
967 };
968
969
970 /**
971  * initialize the smbconf registry backend
972  * the only function that is exported from this module
973  */
974 WERROR smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
975                         const char *path)
976 {
977         return smbconf_init(mem_ctx, conf_ctx, path, &smbconf_ops_reg);
978 }