s3:registry: move the reg_api prototypes to their own header.
[amitay/samba.git] / source3 / utils / net_registry.c
1 /*
2  * Samba Unix/Linux SMB client library
3  * Distributed SMB/CIFS Server Management Utility
4  * Local registry interface
5  *
6  * Copyright (C) Michael Adam 2008
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "registry.h"
24 #include "registry/reg_api.h"
25 #include "registry/reg_util_token.h"
26 #include "utils/net.h"
27 #include "utils/net_registry_util.h"
28 #include "include/g_lock.h"
29
30 /*
31  *
32  * Helper functions
33  *
34  */
35
36 /**
37  * split given path into hive and remaining path and open the hive key
38  */
39 static WERROR open_hive(TALLOC_CTX *ctx, const char *path,
40                         uint32 desired_access,
41                         struct registry_key **hive,
42                         char **subkeyname)
43 {
44         WERROR werr;
45         struct security_token *token = NULL;
46         char *hivename = NULL;
47         char *tmp_subkeyname = NULL;
48         TALLOC_CTX *tmp_ctx = talloc_stackframe();
49
50         if ((hive == NULL) || (subkeyname == NULL)) {
51                 werr = WERR_INVALID_PARAM;
52                 goto done;
53         }
54
55         werr = split_hive_key(tmp_ctx, path, &hivename, &tmp_subkeyname);
56         if (!W_ERROR_IS_OK(werr)) {
57                 goto done;
58         }
59         *subkeyname = talloc_strdup(ctx, tmp_subkeyname);
60         if (*subkeyname == NULL) {
61                 werr = WERR_NOMEM;
62                 goto done;
63         }
64
65         werr = ntstatus_to_werror(registry_create_admin_token(tmp_ctx, &token));
66         if (!W_ERROR_IS_OK(werr)) {
67                 goto done;
68         }
69
70         werr = reg_openhive(ctx, hivename, desired_access, token, hive);
71         if (!W_ERROR_IS_OK(werr)) {
72                 goto done;
73         }
74
75         werr = WERR_OK;
76
77 done:
78         TALLOC_FREE(tmp_ctx);
79         return werr;
80 }
81
82 static WERROR open_key(TALLOC_CTX *ctx, const char *path,
83                        uint32 desired_access,
84                        struct registry_key **key)
85 {
86         WERROR werr;
87         char *subkey_name = NULL;
88         struct registry_key *hive = NULL;
89         TALLOC_CTX *tmp_ctx = talloc_stackframe();
90
91         if ((path == NULL) || (key == NULL)) {
92                 return WERR_INVALID_PARAM;
93         }
94
95         werr = open_hive(tmp_ctx, path, desired_access, &hive, &subkey_name);
96         if (!W_ERROR_IS_OK(werr)) {
97                 d_fprintf(stderr, _("open_hive failed: %s\n"),
98                           win_errstr(werr));
99                 goto done;
100         }
101
102         werr = reg_openkey(ctx, hive, subkey_name, desired_access, key);
103         if (!W_ERROR_IS_OK(werr)) {
104                 d_fprintf(stderr, _("reg_openkey failed: %s\n"),
105                           win_errstr(werr));
106                 goto done;
107         }
108
109         werr = WERR_OK;
110
111 done:
112         TALLOC_FREE(tmp_ctx);
113         return werr;
114 }
115
116 /*
117  *
118  * the main "net registry" function implementations
119  *
120  */
121
122 static int net_registry_enumerate(struct net_context *c, int argc,
123                                   const char **argv)
124 {
125         WERROR werr;
126         struct registry_key *key = NULL;
127         TALLOC_CTX *ctx = talloc_stackframe();
128         char *subkey_name;
129         NTTIME modtime;
130         uint32_t count;
131         char *valname = NULL;
132         struct registry_value *valvalue = NULL;
133         int ret = -1;
134
135         if (argc != 1 || c->display_usage) {
136                 d_printf("%s\n%s",
137                          _("Usage:"),
138                          _("net registry enumerate <path>\n"));
139                 d_printf("%s\n%s",
140                          _("Example:"),
141                          _("net registry enumerate 'HKLM\\Software\\Samba'\n"));
142                 goto done;
143         }
144
145         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
146         if (!W_ERROR_IS_OK(werr)) {
147                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
148                 goto done;
149         }
150
151         for (count = 0;
152              werr = reg_enumkey(ctx, key, count, &subkey_name, &modtime),
153              W_ERROR_IS_OK(werr);
154              count++)
155         {
156                 print_registry_key(subkey_name, &modtime);
157         }
158         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
159                 goto done;
160         }
161
162         for (count = 0;
163              werr = reg_enumvalue(ctx, key, count, &valname, &valvalue),
164              W_ERROR_IS_OK(werr);
165              count++)
166         {
167                 print_registry_value_with_name(valname, valvalue);
168         }
169         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
170                 goto done;
171         }
172
173         ret = 0;
174 done:
175         TALLOC_FREE(ctx);
176         return ret;
177 }
178
179 static int net_registry_createkey(struct net_context *c, int argc,
180                                   const char **argv)
181 {
182         WERROR werr;
183         enum winreg_CreateAction action;
184         char *subkeyname;
185         struct registry_key *hivekey = NULL;
186         struct registry_key *subkey = NULL;
187         TALLOC_CTX *ctx = talloc_stackframe();
188         int ret = -1;
189
190         if (argc != 1 || c->display_usage) {
191                 d_printf("%s\n%s",
192                          _("Usage:"),
193                          _("net registry createkey <path>\n"));
194                 d_printf("%s\n%s",
195                          _("Example:"),
196                          _("net registry createkey "
197                            "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n"));
198                 goto done;
199         }
200         if (strlen(argv[0]) == 0) {
201                 d_fprintf(stderr, _("error: zero length key name given\n"));
202                 goto done;
203         }
204
205         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
206         if (!W_ERROR_IS_OK(werr)) {
207                 d_fprintf(stderr, _("open_hive failed: %s\n"),
208                           win_errstr(werr));
209                 goto done;
210         }
211
212         werr = reg_createkey(ctx, hivekey, subkeyname, REG_KEY_WRITE,
213                              &subkey, &action);
214         if (!W_ERROR_IS_OK(werr)) {
215                 d_fprintf(stderr, _("reg_createkey failed: %s\n"),
216                           win_errstr(werr));
217                 goto done;
218         }
219         switch (action) {
220                 case REG_ACTION_NONE:
221                         d_printf(_("createkey did nothing -- huh?\n"));
222                         break;
223                 case REG_CREATED_NEW_KEY:
224                         d_printf(_("createkey created %s\n"), argv[0]);
225                         break;
226                 case REG_OPENED_EXISTING_KEY:
227                         d_printf(_("createkey opened existing %s\n"), argv[0]);
228                         break;
229         }
230
231         ret = 0;
232
233 done:
234         TALLOC_FREE(ctx);
235         return ret;
236 }
237
238 static int net_registry_deletekey(struct net_context *c, int argc,
239                                   const char **argv)
240 {
241         WERROR werr;
242         char *subkeyname;
243         struct registry_key *hivekey = NULL;
244         TALLOC_CTX *ctx = talloc_stackframe();
245         int ret = -1;
246
247         if (argc != 1 || c->display_usage) {
248                 d_printf("%s\n%s",
249                          _("Usage:"),
250                          _("net registry deletekey <path>\n"));
251                 d_printf("%s\n%s",
252                          _("Example:"),
253                          _("net registry deletekey "
254                            "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n"));
255                 goto done;
256         }
257         if (strlen(argv[0]) == 0) {
258                 d_fprintf(stderr, _("error: zero length key name given\n"));
259                 goto done;
260         }
261
262         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
263         if (!W_ERROR_IS_OK(werr)) {
264                 d_fprintf(stderr, "open_hive %s: %s\n", _("failed"),
265                           win_errstr(werr));
266                 goto done;
267         }
268
269         werr = reg_deletekey(hivekey, subkeyname);
270         if (!W_ERROR_IS_OK(werr)) {
271                 d_fprintf(stderr, "reg_deletekey %s: %s\n", _("failed"),
272                           win_errstr(werr));
273                 goto done;
274         }
275
276         ret = 0;
277
278 done:
279         TALLOC_FREE(ctx);
280         return ret;
281 }
282
283 static int net_registry_getvalue_internal(struct net_context *c, int argc,
284                                           const char **argv, bool raw)
285 {
286         WERROR werr;
287         int ret = -1;
288         struct registry_key *key = NULL;
289         struct registry_value *value = NULL;
290         TALLOC_CTX *ctx = talloc_stackframe();
291
292         if (argc != 2 || c->display_usage) {
293                 d_fprintf(stderr, "%s\n%s",
294                           _("Usage:"),
295                           _("net registry getvalue <key> <valuename>\n"));
296                 goto done;
297         }
298
299         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
300         if (!W_ERROR_IS_OK(werr)) {
301                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
302                 goto done;
303         }
304
305         werr = reg_queryvalue(ctx, key, argv[1], &value);
306         if (!W_ERROR_IS_OK(werr)) {
307                 d_fprintf(stderr, _("reg_queryvalue failed: %s\n"),
308                           win_errstr(werr));
309                 goto done;
310         }
311
312         print_registry_value(value, raw);
313
314         ret = 0;
315
316 done:
317         TALLOC_FREE(ctx);
318         return ret;
319 }
320
321 static int net_registry_getvalue(struct net_context *c, int argc,
322                                  const char **argv)
323 {
324         return net_registry_getvalue_internal(c, argc, argv, false);
325 }
326
327 static int net_registry_getvalueraw(struct net_context *c, int argc,
328                                     const char **argv)
329 {
330         return net_registry_getvalue_internal(c, argc, argv, true);
331 }
332
333 static int net_registry_setvalue(struct net_context *c, int argc,
334                                  const char **argv)
335 {
336         WERROR werr;
337         struct registry_value value;
338         struct registry_key *key = NULL;
339         int ret = -1;
340         TALLOC_CTX *ctx = talloc_stackframe();
341
342         if (argc < 4 || c->display_usage) {
343                 d_fprintf(stderr, "%s\n%s",
344                           _("Usage:"),
345                           _("net registry setvalue <key> <valuename> "
346                             "<type> [<val>]+\n"));
347                 goto done;
348         }
349
350         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
351                 d_fprintf(stderr, _("Too many args for type %s\n"), argv[2]);
352                 goto done;
353         }
354
355         if (strequal(argv[2], "dword")) {
356                 uint32_t v = strtoul(argv[3], NULL, 10);
357                 value.type = REG_DWORD;
358                 value.data = data_blob_talloc(ctx, NULL, 4);
359                 SIVAL(value.data.data, 0, v);
360         } else if (strequal(argv[2], "sz")) {
361                 value.type = REG_SZ;
362                 if (!push_reg_sz(ctx, &value.data, argv[3])) {
363                         goto done;
364                 }
365         } else if (strequal(argv[2], "multi_sz")) {
366                 const char **array;
367                 int count = argc - 3;
368                 int i;
369                 value.type = REG_MULTI_SZ;
370                 array = talloc_zero_array(ctx, const char *, count + 1);
371                 if (array == NULL) {
372                         goto done;
373                 }
374                 for (i=0; i < count; i++) {
375                         array[i] = talloc_strdup(array, argv[count+i]);
376                         if (array[i] == NULL) {
377                                 goto done;
378                         }
379                 }
380                 if (!push_reg_multi_sz(ctx, &value.data, array)) {
381                         goto done;
382                 }
383         } else {
384                 d_fprintf(stderr, _("type \"%s\" not implemented\n"), argv[2]);
385                 goto done;
386         }
387
388         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
389         if (!W_ERROR_IS_OK(werr)) {
390                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
391                 goto done;
392         }
393
394         werr = reg_setvalue(key, argv[1], &value);
395         if (!W_ERROR_IS_OK(werr)) {
396                 d_fprintf(stderr, _("reg_setvalue failed: %s\n"),
397                           win_errstr(werr));
398                 goto done;
399         }
400
401         ret = 0;
402
403 done:
404         TALLOC_FREE(ctx);
405         return ret;
406 }
407
408 struct net_registry_increment_state {
409         const char *keyname;
410         const char *valuename;
411         uint32_t increment;
412         uint32_t newvalue;
413         WERROR werr;
414 };
415
416 static void net_registry_increment_fn(void *private_data)
417 {
418         struct net_registry_increment_state *state =
419                 (struct net_registry_increment_state *)private_data;
420         struct registry_value *value;
421         struct registry_key *key = NULL;
422         uint32_t v;
423
424         state->werr = open_key(talloc_tos(), state->keyname,
425                                REG_KEY_READ|REG_KEY_WRITE, &key);
426         if (!W_ERROR_IS_OK(state->werr)) {
427                 d_fprintf(stderr, _("open_key failed: %s\n"),
428                           win_errstr(state->werr));
429                 goto done;
430         }
431
432         state->werr = reg_queryvalue(key, key, state->valuename, &value);
433         if (!W_ERROR_IS_OK(state->werr)) {
434                 d_fprintf(stderr, _("reg_queryvalue failed: %s\n"),
435                           win_errstr(state->werr));
436                 goto done;
437         }
438
439         if (value->type != REG_DWORD) {
440                 d_fprintf(stderr, _("value not a DWORD: %s\n"),
441                           str_regtype(value->type));
442                 goto done;
443         }
444
445         if (value->data.length < 4) {
446                 d_fprintf(stderr, _("value too short for regular DWORD\n"));
447                 goto done;
448         }
449
450         v = IVAL(value->data.data, 0);
451         v += state->increment;
452         state->newvalue = v;
453
454         SIVAL(value->data.data, 0, v);
455
456         state->werr = reg_setvalue(key, state->valuename, value);
457         if (!W_ERROR_IS_OK(state->werr)) {
458                 d_fprintf(stderr, _("reg_setvalue failed: %s\n"),
459                           win_errstr(state->werr));
460                 goto done;
461         }
462
463 done:
464         TALLOC_FREE(key);
465         return;
466 }
467
468 static int net_registry_increment(struct net_context *c, int argc,
469                                   const char **argv)
470 {
471         struct net_registry_increment_state state;
472         NTSTATUS status;
473         int ret = -1;
474
475         if (argc < 2 || c->display_usage) {
476                 d_fprintf(stderr, "%s\n%s",
477                           _("Usage:"),
478                           _("net registry increment <key> <valuename> "
479                             "[<increment>]\n"));
480                 goto done;
481         }
482
483         state.keyname = argv[0];
484         state.valuename = argv[1];
485
486         state.increment = 1;
487         if (argc == 3) {
488                 state.increment = strtoul(argv[2], NULL, 10);
489         }
490
491         status = g_lock_do("registry_increment_lock", G_LOCK_WRITE,
492                            timeval_set(600, 0), procid_self(),
493                            net_registry_increment_fn, &state);
494         if (!NT_STATUS_IS_OK(status)) {
495                 d_fprintf(stderr, _("g_lock_do failed: %s\n"),
496                           nt_errstr(status));
497                 goto done;
498         }
499         if (!W_ERROR_IS_OK(state.werr)) {
500                 d_fprintf(stderr, _("increment failed: %s\n"),
501                           win_errstr(state.werr));
502                 goto done;
503         }
504
505         d_printf(_("%u\n"), (unsigned)state.newvalue);
506
507         ret = 0;
508
509 done:
510         return ret;
511 }
512
513 static int net_registry_deletevalue(struct net_context *c, int argc,
514                                     const char **argv)
515 {
516         WERROR werr;
517         struct registry_key *key = NULL;
518         TALLOC_CTX *ctx = talloc_stackframe();
519         int ret = -1;
520
521         if (argc != 2 || c->display_usage) {
522                 d_fprintf(stderr, "%s\n%s",
523                           _("Usage:"),
524                           _("net registry deletevalue <key> <valuename>\n"));
525                 goto done;
526         }
527
528         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
529         if (!W_ERROR_IS_OK(werr)) {
530                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
531                 goto done;
532         }
533
534         werr = reg_deletevalue(key, argv[1]);
535         if (!W_ERROR_IS_OK(werr)) {
536                 d_fprintf(stderr, _("reg_deletekey failed: %s\n"),
537                           win_errstr(werr));
538                 goto done;
539         }
540
541         ret = 0;
542
543 done:
544         TALLOC_FREE(ctx);
545         return ret;
546 }
547
548 static WERROR net_registry_getsd_internal(struct net_context *c,
549                                           TALLOC_CTX *mem_ctx,
550                                           const char *keyname,
551                                           struct security_descriptor **sd)
552 {
553         WERROR werr;
554         struct registry_key *key = NULL;
555         TALLOC_CTX *ctx = talloc_stackframe();
556         uint32_t access_mask = REG_KEY_READ |
557                                SEC_FLAG_MAXIMUM_ALLOWED |
558                                SEC_FLAG_SYSTEM_SECURITY;
559
560         /*
561          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
562          * is denied with these perms right now...
563          */
564         access_mask = REG_KEY_READ;
565
566         if (sd == NULL) {
567                 d_fprintf(stderr, _("internal error: invalid argument\n"));
568                 werr = WERR_INVALID_PARAM;
569                 goto done;
570         }
571
572         if (strlen(keyname) == 0) {
573                 d_fprintf(stderr, _("error: zero length key name given\n"));
574                 werr = WERR_INVALID_PARAM;
575                 goto done;
576         }
577
578         werr = open_key(ctx, keyname, access_mask, &key);
579         if (!W_ERROR_IS_OK(werr)) {
580                 d_fprintf(stderr, "%s%s\n", _("open_key failed: "),
581                           win_errstr(werr));
582                 goto done;
583         }
584
585         werr = reg_getkeysecurity(mem_ctx, key, sd);
586         if (!W_ERROR_IS_OK(werr)) {
587                 d_fprintf(stderr, "%s%s\n", _("reg_getkeysecurity failed: "),
588                           win_errstr(werr));
589                 goto done;
590         }
591
592         werr = WERR_OK;
593
594 done:
595         TALLOC_FREE(ctx);
596         return werr;
597 }
598
599 static int net_registry_getsd(struct net_context *c, int argc,
600                               const char **argv)
601 {
602         WERROR werr;
603         int ret = -1;
604         struct security_descriptor *secdesc = NULL;
605         TALLOC_CTX *ctx = talloc_stackframe();
606
607         if (argc != 1 || c->display_usage) {
608                 d_printf("%s\n%s",
609                          _("Usage:"),
610                          _("net registry getsd <path>\n"));
611                 d_printf("%s\n%s",
612                          _("Example:"),
613                          _("net registry getsd 'HKLM\\Software\\Samba'\n"));
614                 goto done;
615         }
616
617         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
618         if (!W_ERROR_IS_OK(werr)) {
619                 goto done;
620         }
621
622         display_sec_desc(secdesc);
623
624         ret = 0;
625
626 done:
627         TALLOC_FREE(ctx);
628         return ret;
629 }
630
631 static int net_registry_getsd_sddl(struct net_context *c,
632                                    int argc, const char **argv)
633 {
634         WERROR werr;
635         int ret = -1;
636         struct security_descriptor *secdesc = NULL;
637         TALLOC_CTX *ctx = talloc_stackframe();
638
639         if (argc != 1 || c->display_usage) {
640                 d_printf("%s\n%s",
641                          _("Usage:"),
642                          _("net registry getsd_sddl <path>\n"));
643                 d_printf("%s\n%s",
644                          _("Example:"),
645                          _("net registry getsd_sddl 'HKLM\\Software\\Samba'\n"));
646                 goto done;
647         }
648
649         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
650         if (!W_ERROR_IS_OK(werr)) {
651                 goto done;
652         }
653
654         d_printf("%s\n", sddl_encode(ctx, secdesc, get_global_sam_sid()));
655
656         ret = 0;
657
658 done:
659         TALLOC_FREE(ctx);
660         return ret;
661 }
662
663 static WERROR net_registry_setsd_internal(struct net_context *c,
664                                           TALLOC_CTX *mem_ctx,
665                                           const char *keyname,
666                                           struct security_descriptor *sd)
667 {
668         WERROR werr;
669         struct registry_key *key = NULL;
670         TALLOC_CTX *ctx = talloc_stackframe();
671         uint32_t access_mask = REG_KEY_WRITE |
672                                SEC_FLAG_MAXIMUM_ALLOWED |
673                                SEC_FLAG_SYSTEM_SECURITY;
674
675         /*
676          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
677          * is denied with these perms right now...
678          */
679         access_mask = REG_KEY_WRITE;
680
681         if (strlen(keyname) == 0) {
682                 d_fprintf(stderr, _("error: zero length key name given\n"));
683                 werr = WERR_INVALID_PARAM;
684                 goto done;
685         }
686
687         werr = open_key(ctx, keyname, access_mask, &key);
688         if (!W_ERROR_IS_OK(werr)) {
689                 d_fprintf(stderr, "%s%s\n", _("open_key failed: "),
690                           win_errstr(werr));
691                 goto done;
692         }
693
694         werr = reg_setkeysecurity(key, sd);
695         if (!W_ERROR_IS_OK(werr)) {
696                 d_fprintf(stderr, "%s%s\n", _("reg_setkeysecurity failed: "),
697                           win_errstr(werr));
698                 goto done;
699         }
700
701         werr = WERR_OK;
702
703 done:
704         TALLOC_FREE(ctx);
705         return werr;
706 }
707
708 static int net_registry_setsd_sddl(struct net_context *c,
709                                    int argc, const char **argv)
710 {
711         WERROR werr;
712         int ret = -1;
713         struct security_descriptor *secdesc = NULL;
714         TALLOC_CTX *ctx = talloc_stackframe();
715
716         if (argc != 2 || c->display_usage) {
717                 d_printf("%s\n%s",
718                          _("Usage:"),
719                          _("net registry setsd_sddl <path> <security_descriptor>\n"));
720                 d_printf("%s\n%s",
721                          _("Example:"),
722                          _("net registry setsd_sddl 'HKLM\\Software\\Samba'\n"));
723                 goto done;
724         }
725
726         secdesc = sddl_decode(ctx, argv[1], get_global_sam_sid());
727         if (secdesc == NULL) {
728                 goto done;
729         }
730
731         werr = net_registry_setsd_internal(c, ctx, argv[0], secdesc);
732         if (!W_ERROR_IS_OK(werr)) {
733                 goto done;
734         }
735
736         ret = 0;
737
738 done:
739         TALLOC_FREE(ctx);
740         return ret;
741 }
742
743 int net_registry(struct net_context *c, int argc, const char **argv)
744 {
745         int ret = -1;
746
747         struct functable func[] = {
748                 {
749                         "enumerate",
750                         net_registry_enumerate,
751                         NET_TRANSPORT_LOCAL,
752                         N_("Enumerate registry keys and values"),
753                         N_("net registry enumerate\n"
754                            "    Enumerate registry keys and values")
755                 },
756                 {
757                         "createkey",
758                         net_registry_createkey,
759                         NET_TRANSPORT_LOCAL,
760                         N_("Create a new registry key"),
761                         N_("net registry createkey\n"
762                            "    Create a new registry key")
763                 },
764                 {
765                         "deletekey",
766                         net_registry_deletekey,
767                         NET_TRANSPORT_LOCAL,
768                         N_("Delete a registry key"),
769                         N_("net registry deletekey\n"
770                            "    Delete a registry key")
771                 },
772                 {
773                         "getvalue",
774                         net_registry_getvalue,
775                         NET_TRANSPORT_LOCAL,
776                         N_("Print a registry value"),
777                         N_("net registry getvalue\n"
778                            "    Print a registry value")
779                 },
780                 {
781                         "getvalueraw",
782                         net_registry_getvalueraw,
783                         NET_TRANSPORT_LOCAL,
784                         N_("Print a registry value (raw format)"),
785                         N_("net registry getvalueraw\n"
786                            "    Print a registry value (raw format)")
787                 },
788                 {
789                         "setvalue",
790                         net_registry_setvalue,
791                         NET_TRANSPORT_LOCAL,
792                         N_("Set a new registry value"),
793                         N_("net registry setvalue\n"
794                            "    Set a new registry value")
795                 },
796                 {
797                         "increment",
798                         net_registry_increment,
799                         NET_TRANSPORT_LOCAL,
800                         N_("Increment a DWORD registry value under a lock"),
801                         N_("net registry increment\n"
802                            "    Increment a DWORD registry value under a lock")
803                 },
804                 {
805                         "deletevalue",
806                         net_registry_deletevalue,
807                         NET_TRANSPORT_LOCAL,
808                         N_("Delete a registry value"),
809                         N_("net registry deletevalue\n"
810                            "    Delete a registry value")
811                 },
812                 {
813                         "getsd",
814                         net_registry_getsd,
815                         NET_TRANSPORT_LOCAL,
816                         N_("Get security descriptor"),
817                         N_("net registry getsd\n"
818                            "    Get security descriptor")
819                 },
820                 {
821                         "getsd_sddl",
822                         net_registry_getsd_sddl,
823                         NET_TRANSPORT_LOCAL,
824                         N_("Get security descriptor in sddl format"),
825                         N_("net registry getsd_sddl\n"
826                            "    Get security descriptor in sddl format")
827                 },
828                 {
829                         "setsd_sddl",
830                         net_registry_setsd_sddl,
831                         NET_TRANSPORT_LOCAL,
832                         N_("Set security descriptor from sddl format string"),
833                         N_("net registry setsd_sddl\n"
834                            "    Set security descriptor from sddl format string")
835                 },
836         { NULL, NULL, 0, NULL, NULL }
837         };
838
839         if (!W_ERROR_IS_OK(registry_init_basic())) {
840                 return -1;
841         }
842
843         ret = net_run_function(c, argc, argv, "net registry", func);
844
845         return ret;
846 }