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