s3-registry: avoid using registry_value union.
[nivanova/samba-autobuild/.git] / source3 / utils / net_rpc_registry.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4
5    Copyright (C) Gerald (Jerry) Carter          2005-2006
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19  
20 #include "includes.h"
21 #include "registry.h"
22 #include "utils/net.h"
23 #include "utils/net_registry_util.h"
24 #include "regfio.h"
25 #include "../librpc/gen_ndr/cli_winreg.h"
26 #include "registry/reg_util_marshalling.h"
27 #include "registry/reg_objects.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29
30 /*******************************************************************
31  connect to a registry hive root (open a registry policy)
32 *******************************************************************/
33
34 static NTSTATUS rpccli_winreg_Connect(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
35                                       uint32_t reg_type, uint32_t access_mask,
36                                       struct policy_handle *reg_hnd)
37 {
38         ZERO_STRUCTP(reg_hnd);
39
40         switch (reg_type)
41         {
42         case HKEY_CLASSES_ROOT:
43                 return rpccli_winreg_OpenHKCR( cli, mem_ctx, NULL,
44                         access_mask, reg_hnd, NULL);
45
46         case HKEY_LOCAL_MACHINE:
47                 return rpccli_winreg_OpenHKLM( cli, mem_ctx, NULL,
48                         access_mask, reg_hnd, NULL);
49
50         case HKEY_USERS:
51                 return rpccli_winreg_OpenHKU( cli, mem_ctx, NULL,
52                         access_mask, reg_hnd, NULL);
53
54         case HKEY_CURRENT_USER:
55                 return rpccli_winreg_OpenHKCU( cli, mem_ctx, NULL,
56                         access_mask, reg_hnd, NULL);
57
58         case HKEY_PERFORMANCE_DATA:
59                 return rpccli_winreg_OpenHKPD( cli, mem_ctx, NULL,
60                         access_mask, reg_hnd, NULL);
61
62         default:
63                 /* fall through to end of function */
64                 break;
65         }
66
67         return NT_STATUS_INVALID_PARAMETER;
68 }
69
70 static bool reg_hive_key(TALLOC_CTX *ctx, const char *fullname,
71                          uint32 *reg_type, const char **key_name)
72 {
73         WERROR werr;
74         char *hivename = NULL;
75         char *tmp_keyname = NULL;
76         bool ret = false;
77         TALLOC_CTX *tmp_ctx = talloc_stackframe();
78
79         werr = split_hive_key(tmp_ctx, fullname, &hivename, &tmp_keyname);
80         if (!W_ERROR_IS_OK(werr)) {
81                 goto done;
82         }
83
84         *key_name = talloc_strdup(ctx, tmp_keyname);
85         if (*key_name == NULL) {
86                 goto done;
87         }
88
89         if (strequal(hivename, "HKLM") ||
90             strequal(hivename, "HKEY_LOCAL_MACHINE"))
91         {
92                 (*reg_type) = HKEY_LOCAL_MACHINE;
93         } else if (strequal(hivename, "HKCR") ||
94                    strequal(hivename, "HKEY_CLASSES_ROOT"))
95         {
96                 (*reg_type) = HKEY_CLASSES_ROOT;
97         } else if (strequal(hivename, "HKU") ||
98                    strequal(hivename, "HKEY_USERS"))
99         {
100                 (*reg_type) = HKEY_USERS;
101         } else if (strequal(hivename, "HKCU") ||
102                    strequal(hivename, "HKEY_CURRENT_USER"))
103         {
104                 (*reg_type) = HKEY_CURRENT_USER;
105         } else if (strequal(hivename, "HKPD") ||
106                    strequal(hivename, "HKEY_PERFORMANCE_DATA"))
107         {
108                 (*reg_type) = HKEY_PERFORMANCE_DATA;
109         } else {
110                 DEBUG(10,("reg_hive_key: unrecognised hive key %s\n",
111                           fullname));
112                 goto done;
113         }
114
115         ret = true;
116
117 done:
118         TALLOC_FREE(tmp_ctx);
119         return ret;
120 }
121
122 static NTSTATUS registry_openkey(TALLOC_CTX *mem_ctx,
123                                  struct rpc_pipe_client *pipe_hnd,
124                                  const char *name, uint32 access_mask,
125                                  struct policy_handle *hive_hnd,
126                                  struct policy_handle *key_hnd)
127 {
128         uint32 hive;
129         NTSTATUS status;
130         struct winreg_String key;
131
132         ZERO_STRUCT(key);
133
134         if (!reg_hive_key(mem_ctx, name, &hive, &key.name)) {
135                 return NT_STATUS_INVALID_PARAMETER;
136         }
137
138         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, access_mask,
139                                        hive_hnd);
140         if (!(NT_STATUS_IS_OK(status))) {
141                 return status;
142         }
143
144         status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, hive_hnd, key, 0,
145                                        access_mask, key_hnd, NULL);
146         if (!(NT_STATUS_IS_OK(status))) {
147                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, hive_hnd, NULL);
148                 return status;
149         }
150
151         return NT_STATUS_OK;
152 }
153
154 static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
155                                   struct rpc_pipe_client *pipe_hnd,
156                                   struct policy_handle *key_hnd,
157                                   uint32 *pnum_keys, char ***pnames,
158                                   char ***pclasses, NTTIME ***pmodtimes)
159 {
160         TALLOC_CTX *mem_ctx;
161         NTSTATUS status;
162         uint32 num_subkeys, max_subkeylen, max_classlen;
163         uint32 num_values, max_valnamelen, max_valbufsize;
164         uint32 i;
165         NTTIME last_changed_time;
166         uint32 secdescsize;
167         struct winreg_String classname;
168         char **names, **classes;
169         NTTIME **modtimes;
170
171         if (!(mem_ctx = talloc_new(ctx))) {
172                 return NT_STATUS_NO_MEMORY;
173         }
174
175         ZERO_STRUCT(classname);
176         status = rpccli_winreg_QueryInfoKey(
177                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
178                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
179                 &max_valbufsize, &secdescsize, &last_changed_time, NULL );
180
181         if (!NT_STATUS_IS_OK(status)) {
182                 goto error;
183         }
184
185         if (num_subkeys == 0) {
186                 *pnum_keys = 0;
187                 TALLOC_FREE(mem_ctx);
188                 return NT_STATUS_OK;
189         }
190
191         if ((!(names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
192             (!(classes = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
193             (!(modtimes = TALLOC_ZERO_ARRAY(mem_ctx, NTTIME *,
194                                             num_subkeys)))) {
195                 status = NT_STATUS_NO_MEMORY;
196                 goto error;
197         }
198
199         for (i=0; i<num_subkeys; i++) {
200                 char c, n;
201                 struct winreg_StringBuf class_buf;
202                 struct winreg_StringBuf name_buf;
203                 NTTIME modtime;
204                 WERROR werr;
205
206                 c = '\0';
207                 class_buf.name = &c;
208                 class_buf.size = max_classlen+2;
209
210                 n = '\0';
211                 name_buf.name = &n;
212                 name_buf.size = max_subkeylen+2;
213
214                 ZERO_STRUCT(modtime);
215
216                 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key_hnd,
217                                                i, &name_buf, &class_buf,
218                                                &modtime, &werr);
219
220                 if (W_ERROR_EQUAL(werr,
221                                   WERR_NO_MORE_ITEMS) ) {
222                         status = NT_STATUS_OK;
223                         break;
224                 }
225                 if (!NT_STATUS_IS_OK(status)) {
226                         goto error;
227                 }
228
229                 classes[i] = NULL;
230
231                 if (class_buf.name &&
232                     (!(classes[i] = talloc_strdup(classes, class_buf.name)))) {
233                         status = NT_STATUS_NO_MEMORY;
234                         goto error;
235                 }
236
237                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
238                         status = NT_STATUS_NO_MEMORY;
239                         goto error;
240                 }
241
242                 if ((!(modtimes[i] = (NTTIME *)talloc_memdup(
243                                modtimes, &modtime, sizeof(modtime))))) {
244                         status = NT_STATUS_NO_MEMORY;
245                         goto error;
246                 }
247         }
248
249         *pnum_keys = num_subkeys;
250
251         if (pnames) {
252                 *pnames = talloc_move(ctx, &names);
253         }
254         if (pclasses) {
255                 *pclasses = talloc_move(ctx, &classes);
256         }
257         if (pmodtimes) {
258                 *pmodtimes = talloc_move(ctx, &modtimes);
259         }
260
261         status = NT_STATUS_OK;
262
263  error:
264         TALLOC_FREE(mem_ctx);
265         return status;
266 }
267
268 static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
269                                     struct rpc_pipe_client *pipe_hnd,
270                                     struct policy_handle *key_hnd,
271                                     uint32 *pnum_values, char ***pvalnames,
272                                     struct registry_value ***pvalues)
273 {
274         TALLOC_CTX *mem_ctx;
275         NTSTATUS status;
276         uint32 num_subkeys, max_subkeylen, max_classlen;
277         uint32 num_values, max_valnamelen, max_valbufsize;
278         uint32 i;
279         NTTIME last_changed_time;
280         uint32 secdescsize;
281         struct winreg_String classname;
282         struct registry_value **values;
283         char **names;
284
285         if (!(mem_ctx = talloc_new(ctx))) {
286                 return NT_STATUS_NO_MEMORY;
287         }
288
289         ZERO_STRUCT(classname);
290         status = rpccli_winreg_QueryInfoKey(
291                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
292                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
293                 &max_valbufsize, &secdescsize, &last_changed_time, NULL );
294
295         if (!NT_STATUS_IS_OK(status)) {
296                 goto error;
297         }
298
299         if (num_values == 0) {
300                 *pnum_values = 0;
301                 TALLOC_FREE(mem_ctx);
302                 return NT_STATUS_OK;
303         }
304
305         if ((!(names = TALLOC_ARRAY(mem_ctx, char *, num_values))) ||
306             (!(values = TALLOC_ARRAY(mem_ctx, struct registry_value *,
307                                      num_values)))) {
308                 status = NT_STATUS_NO_MEMORY;
309                 goto error;
310         }
311
312         for (i=0; i<num_values; i++) {
313                 enum winreg_Type type = REG_NONE;
314                 uint8 *data = NULL;
315                 uint32 data_size;
316                 uint32 value_length;
317
318                 char n;
319                 struct winreg_ValNameBuf name_buf;
320                 WERROR err;
321
322                 n = '\0';
323                 name_buf.name = &n;
324                 name_buf.size = max_valnamelen + 2;
325
326                 data_size = max_valbufsize;
327                 data = (uint8 *)TALLOC(mem_ctx, data_size);
328                 value_length = 0;
329
330                 status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, key_hnd,
331                                                  i, &name_buf, &type,
332                                                  data, &data_size,
333                                                  &value_length, &err);
334
335                 if ( W_ERROR_EQUAL(err,
336                                    WERR_NO_MORE_ITEMS) ) {
337                         status = NT_STATUS_OK;
338                         break;
339                 }
340
341                 if (!(NT_STATUS_IS_OK(status))) {
342                         goto error;
343                 }
344
345                 if (name_buf.name == NULL) {
346                         status = NT_STATUS_INVALID_PARAMETER;
347                         goto error;
348                 }
349
350                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
351                         status = NT_STATUS_NO_MEMORY;
352                         goto error;
353                 }
354
355                 values[i] = talloc_zero(values, struct registry_value);
356                 if (values[i] == NULL) {
357                         status = NT_STATUS_NO_MEMORY;
358                         goto error;
359                 }
360
361                 values[i]->type = type;
362                 values[i]->data = data_blob_talloc(values[i], data, data_size);
363         }
364
365         *pnum_values = num_values;
366
367         if (pvalnames) {
368                 *pvalnames = talloc_move(ctx, &names);
369         }
370         if (pvalues) {
371                 *pvalues = talloc_move(ctx, &values);
372         }
373
374         status = NT_STATUS_OK;
375
376  error:
377         TALLOC_FREE(mem_ctx);
378         return status;
379 }
380
381 static NTSTATUS registry_getsd(TALLOC_CTX *mem_ctx,
382                                struct rpc_pipe_client *pipe_hnd,
383                                struct policy_handle *key_hnd,
384                                uint32_t sec_info,
385                                struct KeySecurityData *sd)
386 {
387         return rpccli_winreg_GetKeySecurity(pipe_hnd, mem_ctx, key_hnd,
388                                             sec_info, sd, NULL);
389 }
390
391
392 static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
393                                   struct rpc_pipe_client *pipe_hnd,
394                                   struct policy_handle *key_hnd,
395                                   const char *name,
396                                   const struct registry_value *value)
397 {
398         struct winreg_String name_string;
399         NTSTATUS result;
400
401         ZERO_STRUCT(name_string);
402
403         name_string.name = name;
404         result = rpccli_winreg_SetValue(pipe_hnd, mem_ctx, key_hnd,
405                                         name_string, value->type,
406                                         value->data.data, value->data.length, NULL);
407         return result;
408 }
409
410 static NTSTATUS rpc_registry_setvalue_internal(struct net_context *c,
411                                                const struct dom_sid *domain_sid,
412                                                const char *domain_name,
413                                                struct cli_state *cli,
414                                                struct rpc_pipe_client *pipe_hnd,
415                                                TALLOC_CTX *mem_ctx,
416                                                int argc,
417                                                const char **argv )
418 {
419         struct policy_handle hive_hnd, key_hnd;
420         NTSTATUS status;
421         struct registry_value value;
422
423         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
424                                   SEC_FLAG_MAXIMUM_ALLOWED,
425                                   &hive_hnd, &key_hnd);
426         if (!NT_STATUS_IS_OK(status)) {
427                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
428                           nt_errstr(status));
429                 return status;
430         }
431
432         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
433                 d_fprintf(stderr, _("Too many args for type %s\n"), argv[2]);
434                 return NT_STATUS_NOT_IMPLEMENTED;
435         }
436
437         if (strequal(argv[2], "dword")) {
438                 uint32_t v = strtoul(argv[3], NULL, 10);
439                 value.type = REG_DWORD;
440                 value.data = data_blob_talloc(mem_ctx, NULL, 4);
441                 SIVAL(value.data.data, 0, v);
442         }
443         else if (strequal(argv[2], "sz")) {
444                 value.type = REG_SZ;
445                 if (!push_reg_sz(mem_ctx, &value.data, argv[3])) {
446                         status = NT_STATUS_NO_MEMORY;
447                         goto error;
448                 }
449         }
450         else {
451                 d_fprintf(stderr, _("type \"%s\" not implemented\n"), argv[2]);
452                 status = NT_STATUS_NOT_IMPLEMENTED;
453                 goto error;
454         }
455
456         status = registry_setvalue(mem_ctx, pipe_hnd, &key_hnd,
457                                    argv[1], &value);
458
459         if (!NT_STATUS_IS_OK(status)) {
460                 d_fprintf(stderr, _("registry_setvalue failed: %s\n"),
461                           nt_errstr(status));
462         }
463
464  error:
465         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
466         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
467
468         return NT_STATUS_OK;
469 }
470
471 static int rpc_registry_setvalue(struct net_context *c, int argc,
472                                  const char **argv )
473 {
474         if (argc < 4 || c->display_usage) {
475                 d_fprintf(stderr, "%s\n%s",
476                           _("Usage:"),
477                           _("net rpc registry setvalue <key> <valuename> "
478                             "<type> [<val>]+\n"));
479                 return -1;
480         }
481
482         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
483                 rpc_registry_setvalue_internal, argc, argv );
484 }
485
486 static NTSTATUS rpc_registry_deletevalue_internal(struct net_context *c,
487                                                   const struct dom_sid *domain_sid,
488                                                   const char *domain_name,
489                                                   struct cli_state *cli,
490                                                   struct rpc_pipe_client *pipe_hnd,
491                                                   TALLOC_CTX *mem_ctx,
492                                                   int argc,
493                                                   const char **argv )
494 {
495         struct policy_handle hive_hnd, key_hnd;
496         NTSTATUS status;
497         struct winreg_String valuename;
498
499         ZERO_STRUCT(valuename);
500
501         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
502                                   SEC_FLAG_MAXIMUM_ALLOWED,
503                                   &hive_hnd, &key_hnd);
504         if (!NT_STATUS_IS_OK(status)) {
505                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
506                           nt_errstr(status));
507                 return status;
508         }
509
510         valuename.name = argv[1];
511
512         status = rpccli_winreg_DeleteValue(pipe_hnd, mem_ctx, &key_hnd,
513                                            valuename, NULL);
514
515         if (!NT_STATUS_IS_OK(status)) {
516                 d_fprintf(stderr, _("registry_deletevalue failed: %s\n"),
517                           nt_errstr(status));
518         }
519
520         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
521         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
522
523         return status;
524 }
525
526 static int rpc_registry_deletevalue(struct net_context *c, int argc,
527                                     const char **argv )
528 {
529         if (argc != 2 || c->display_usage) {
530                 d_fprintf(stderr, "%s\n%s",
531                           _("Usage:"),
532                           _("net rpc registry deletevalue <key> <valuename>\n"));
533                 return -1;
534         }
535
536         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
537                 rpc_registry_deletevalue_internal, argc, argv );
538 }
539
540 static NTSTATUS rpc_registry_getvalue_internal(struct net_context *c,
541                                                const struct dom_sid *domain_sid,
542                                                const char *domain_name,
543                                                struct cli_state *cli,
544                                                struct rpc_pipe_client *pipe_hnd,
545                                                TALLOC_CTX *mem_ctx,
546                                                bool raw,
547                                                int argc,
548                                                const char **argv)
549 {
550         struct policy_handle hive_hnd, key_hnd;
551         NTSTATUS status;
552         struct winreg_String valuename;
553         struct registry_value *value = NULL;
554         enum winreg_Type type = REG_NONE;
555         uint32_t data_size = 0;
556         uint32_t value_length = 0;
557         TALLOC_CTX *tmp_ctx = talloc_stackframe();
558
559         ZERO_STRUCT(valuename);
560
561         status = registry_openkey(tmp_ctx, pipe_hnd, argv[0],
562                                   SEC_FLAG_MAXIMUM_ALLOWED,
563                                   &hive_hnd, &key_hnd);
564         if (!NT_STATUS_IS_OK(status)) {
565                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
566                           nt_errstr(status));
567                 return status;
568         }
569
570         valuename.name = argv[1];
571
572         value = talloc_zero(tmp_ctx, struct registry_value);
573         if (value == NULL) {
574                 return NT_STATUS_NO_MEMORY;
575         }
576
577         /*
578          * call QueryValue once with data == NULL to get the
579          * needed memory size to be allocated, then allocate
580          * data buffer and call again.
581          */
582         status = rpccli_winreg_QueryValue(pipe_hnd, tmp_ctx, &key_hnd,
583                                           &valuename,
584                                           &type,
585                                           NULL,
586                                           &data_size,
587                                           &value_length,
588                                           NULL);
589
590         if (!NT_STATUS_IS_OK(status)) {
591                 d_fprintf(stderr, _("registry_queryvalue failed: %s\n"),
592                           nt_errstr(status));
593                 goto done;
594         }
595
596         value->data = data_blob_talloc(tmp_ctx, NULL, data_size);
597
598         status = rpccli_winreg_QueryValue(pipe_hnd, tmp_ctx, &key_hnd,
599                                           &valuename,
600                                           &type,
601                                           value->data.data,
602                                           &data_size,
603                                           &value_length,
604                                           NULL);
605
606         if (!NT_STATUS_IS_OK(status)) {
607                 d_fprintf(stderr, _("registry_queryvalue failed: %s\n"),
608                           nt_errstr(status));
609                 goto done;
610         }
611
612         print_registry_value(value, raw);
613
614 done:
615         rpccli_winreg_CloseKey(pipe_hnd, tmp_ctx, &key_hnd, NULL);
616         rpccli_winreg_CloseKey(pipe_hnd, tmp_ctx, &hive_hnd, NULL);
617
618         TALLOC_FREE(tmp_ctx);
619
620         return status;
621 }
622
623 static NTSTATUS rpc_registry_getvalue_full(struct net_context *c,
624                                            const struct dom_sid *domain_sid,
625                                            const char *domain_name,
626                                            struct cli_state *cli,
627                                            struct rpc_pipe_client *pipe_hnd,
628                                            TALLOC_CTX *mem_ctx,
629                                            int argc,
630                                            const char **argv)
631 {
632         return rpc_registry_getvalue_internal(c, domain_sid, domain_name,
633                                               cli, pipe_hnd, mem_ctx, false,
634                                               argc, argv);
635 }
636
637 static int rpc_registry_getvalue(struct net_context *c, int argc,
638                                  const char **argv)
639 {
640         if (argc != 2 || c->display_usage) {
641                 d_fprintf(stderr, "%s\n%s",
642                           _("Usage:"),
643                           _("net rpc registry getvalue <key> <valuename>\n"));
644                 return -1;
645         }
646
647         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
648                 rpc_registry_getvalue_full, argc, argv);
649 }
650
651 static NTSTATUS rpc_registry_getvalue_raw(struct net_context *c,
652                                           const struct dom_sid *domain_sid,
653                                           const char *domain_name,
654                                           struct cli_state *cli,
655                                           struct rpc_pipe_client *pipe_hnd,
656                                           TALLOC_CTX *mem_ctx,
657                                           int argc,
658                                           const char **argv)
659 {
660         return rpc_registry_getvalue_internal(c, domain_sid, domain_name,
661                                               cli, pipe_hnd, mem_ctx, true,
662                                               argc, argv);
663 }
664
665 static int rpc_registry_getvalueraw(struct net_context *c, int argc,
666                                     const char **argv)
667 {
668         if (argc != 2 || c->display_usage) {
669                 d_fprintf(stderr, "%s\n%s",
670                           _("Usage:"),
671                           _("net rpc registry getvalue <key> <valuename>\n"));
672                 return -1;
673         }
674
675         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
676                 rpc_registry_getvalue_raw, argc, argv);
677 }
678
679 static NTSTATUS rpc_registry_createkey_internal(struct net_context *c,
680                                                 const struct dom_sid *domain_sid,
681                                                 const char *domain_name,
682                                                 struct cli_state *cli,
683                                                 struct rpc_pipe_client *pipe_hnd,
684                                                 TALLOC_CTX *mem_ctx,
685                                                 int argc,
686                                                 const char **argv )
687 {
688         uint32 hive;
689         struct policy_handle hive_hnd, key_hnd;
690         struct winreg_String key, keyclass;
691         enum winreg_CreateAction action;
692         NTSTATUS status;
693
694         ZERO_STRUCT(key);
695         ZERO_STRUCT(keyclass);
696
697         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
698                 return NT_STATUS_INVALID_PARAMETER;
699         }
700
701         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
702                                        SEC_FLAG_MAXIMUM_ALLOWED,
703                                        &hive_hnd);
704         if (!(NT_STATUS_IS_OK(status))) {
705                 return status;
706         }
707
708         action = REG_ACTION_NONE;
709         keyclass.name = "";
710
711         status = rpccli_winreg_CreateKey(pipe_hnd, mem_ctx, &hive_hnd, key,
712                                          keyclass, 0, REG_KEY_READ, NULL,
713                                          &key_hnd, &action, NULL);
714         if (!NT_STATUS_IS_OK(status)) {
715                 d_fprintf(stderr, _("createkey returned %s\n"),
716                           nt_errstr(status));
717                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
718                 return status;
719         }
720
721         switch (action) {
722                 case REG_ACTION_NONE:
723                         d_printf(_("createkey did nothing -- huh?\n"));
724                         break;
725                 case REG_CREATED_NEW_KEY:
726                         d_printf(_("createkey created %s\n"), argv[0]);
727                         break;
728                 case REG_OPENED_EXISTING_KEY:
729                         d_printf(_("createkey opened existing %s\n"), argv[0]);
730                         break;
731         }
732
733         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
734         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
735
736         return status;
737 }
738
739 static int rpc_registry_createkey(struct net_context *c, int argc,
740                                   const char **argv )
741 {
742         if (argc != 1 || c->display_usage) {
743                 d_fprintf(stderr, "%s\n%s",
744                           _("Usage:"),
745                           _("net rpc registry createkey <key>\n"));
746                 return -1;
747         }
748
749         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
750                 rpc_registry_createkey_internal, argc, argv );
751 }
752
753 static NTSTATUS rpc_registry_deletekey_internal(struct net_context *c,
754                                                 const struct dom_sid *domain_sid,
755                                                 const char *domain_name,
756                                                 struct cli_state *cli,
757                                                 struct rpc_pipe_client *pipe_hnd,
758                                                 TALLOC_CTX *mem_ctx,
759                                                 int argc,
760                                                 const char **argv )
761 {
762         uint32 hive;
763         struct policy_handle hive_hnd;
764         struct winreg_String key;
765         NTSTATUS status;
766
767         ZERO_STRUCT(key);
768
769         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
770                 return NT_STATUS_INVALID_PARAMETER;
771         }
772
773         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
774                                        SEC_FLAG_MAXIMUM_ALLOWED,
775                                        &hive_hnd);
776         if (!(NT_STATUS_IS_OK(status))) {
777                 return status;
778         }
779
780         status = rpccli_winreg_DeleteKey(pipe_hnd, mem_ctx, &hive_hnd, key, NULL);
781         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
782
783         if (!NT_STATUS_IS_OK(status)) {
784                 d_fprintf(stderr, _("deletekey returned %s\n"),
785                           nt_errstr(status));
786         }
787
788         return status;
789 }
790
791 static int rpc_registry_deletekey(struct net_context *c, int argc, const char **argv )
792 {
793         if (argc != 1 || c->display_usage) {
794                 d_fprintf(stderr, "%s\n%s",
795                           _("Usage:"),
796                           _("net rpc registry deletekey <key>\n"));
797                 return -1;
798         }
799
800         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
801                 rpc_registry_deletekey_internal, argc, argv );
802 }
803
804 /********************************************************************
805 ********************************************************************/
806
807 static NTSTATUS rpc_registry_enumerate_internal(struct net_context *c,
808                                                 const struct dom_sid *domain_sid,
809                                                 const char *domain_name,
810                                                 struct cli_state *cli,
811                                                 struct rpc_pipe_client *pipe_hnd,
812                                                 TALLOC_CTX *mem_ctx,
813                                                 int argc,
814                                                 const char **argv )
815 {
816         struct policy_handle pol_hive, pol_key;
817         NTSTATUS status;
818         uint32 num_subkeys = 0;
819         uint32 num_values = 0;
820         char **names = NULL, **classes = NULL;
821         NTTIME **modtimes = NULL;
822         uint32 i;
823         struct registry_value **values = NULL;
824
825         if (argc != 1 || c->display_usage) {
826                 d_printf("%s\n%s",
827                          _("Usage:"),
828                          _("net rpc registry enumerate <path>\n"));
829                 d_printf("%s  net rpc registry enumerate "
830                          "'HKLM\\Software\\Samba'\n", _("Example:"));
831                 return NT_STATUS_INVALID_PARAMETER;
832         }
833
834         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
835                                   &pol_hive, &pol_key);
836         if (!NT_STATUS_IS_OK(status)) {
837                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
838                           nt_errstr(status));
839                 return status;
840         }
841
842         status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
843                                    &names, &classes, &modtimes);
844         if (!NT_STATUS_IS_OK(status)) {
845                 d_fprintf(stderr, _("enumerating keys failed: %s\n"),
846                           nt_errstr(status));
847                 return status;
848         }
849
850         for (i=0; i<num_subkeys; i++) {
851                 print_registry_key(names[i], modtimes[i]);
852         }
853
854         status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
855                                      &names, &values);
856         if (!NT_STATUS_IS_OK(status)) {
857                 d_fprintf(stderr, _("enumerating values failed: %s\n"),
858                           nt_errstr(status));
859                 return status;
860         }
861
862         for (i=0; i<num_values; i++) {
863                 print_registry_value_with_name(names[i], values[i]);
864         }
865
866         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
867         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
868
869         return status;
870 }
871
872 /********************************************************************
873 ********************************************************************/
874
875 static int rpc_registry_enumerate(struct net_context *c, int argc,
876                                   const char **argv )
877 {
878         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
879                 rpc_registry_enumerate_internal, argc, argv );
880 }
881
882 /********************************************************************
883 ********************************************************************/
884
885 static NTSTATUS rpc_registry_save_internal(struct net_context *c,
886                                         const struct dom_sid *domain_sid,
887                                         const char *domain_name,
888                                         struct cli_state *cli,
889                                         struct rpc_pipe_client *pipe_hnd,
890                                         TALLOC_CTX *mem_ctx,
891                                         int argc,
892                                         const char **argv )
893 {
894         WERROR result = WERR_GENERAL_FAILURE;
895         struct policy_handle pol_hive, pol_key;
896         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
897         struct winreg_String filename;
898
899         if (argc != 2 || c->display_usage) {
900                 d_printf("%s\n%s",
901                          _("Usage:"),
902                          _("net rpc registry backup <path> <file> \n"));
903                 return NT_STATUS_INVALID_PARAMETER;
904         }
905
906         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
907                                   &pol_hive, &pol_key);
908         if (!NT_STATUS_IS_OK(status)) {
909                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
910                           nt_errstr(status));
911                 return status;
912         }
913
914         filename.name = argv[1];
915         status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL, NULL);
916         if ( !W_ERROR_IS_OK(result) ) {
917                 d_fprintf(stderr, _("Unable to save [%s] to %s:%s\n"), argv[0],
918                           cli->desthost, argv[1]);
919         }
920
921         /* cleanup */
922
923         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
924         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
925
926         return status;
927 }
928
929 /********************************************************************
930 ********************************************************************/
931
932 static int rpc_registry_save(struct net_context *c, int argc, const char **argv )
933 {
934         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
935                 rpc_registry_save_internal, argc, argv );
936 }
937
938
939 /********************************************************************
940 ********************************************************************/
941
942 static void dump_values( REGF_NK_REC *nk )
943 {
944         int i, j;
945         const char *data_str = NULL;
946         uint32 data_size, data;
947         DATA_BLOB blob;
948
949         if ( !nk->values )
950                 return;
951
952         for ( i=0; i<nk->num_values; i++ ) {
953                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
954                 d_printf( "(%s) ", str_regtype( nk->values[i].type ) );
955
956                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
957                 switch ( nk->values[i].type ) {
958                         case REG_SZ:
959                                 blob = data_blob_const(nk->values[i].data, data_size);
960                                 pull_reg_sz(talloc_tos(), &blob, &data_str);
961                                 if (!data_str) {
962                                         break;
963                                 }
964                                 d_printf( "%s", data_str );
965                                 break;
966                         case REG_MULTI_SZ:
967                         case REG_EXPAND_SZ:
968                                 for ( j=0; j<data_size; j++ ) {
969                                         d_printf( "%c", nk->values[i].data[j] );
970                                 }
971                                 break;
972                         case REG_DWORD:
973                                 data = IVAL( nk->values[i].data, 0 );
974                                 d_printf("0x%x", data );
975                                 break;
976                         case REG_BINARY:
977                                 for ( j=0; j<data_size; j++ ) {
978                                         d_printf( "%x", nk->values[i].data[j] );
979                                 }
980                                 break;
981                         default:
982                                 d_printf(_("unknown"));
983                                 break;
984                 }
985
986                 d_printf( "\n" );
987         }
988
989 }
990
991 /********************************************************************
992 ********************************************************************/
993
994 static bool dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
995 {
996         REGF_NK_REC *key;
997
998         /* depth first dump of the registry tree */
999
1000         while ( (key = regfio_fetch_subkey( file, nk )) ) {
1001                 char *regpath;
1002                 if (asprintf(&regpath, "%s\\%s", parent, key->keyname) < 0) {
1003                         break;
1004                 }
1005                 d_printf("[%s]\n", regpath );
1006                 dump_values( key );
1007                 d_printf("\n");
1008                 dump_registry_tree( file, key, regpath );
1009                 SAFE_FREE(regpath);
1010         }
1011
1012         return true;
1013 }
1014
1015 /********************************************************************
1016 ********************************************************************/
1017
1018 static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
1019                                  REGF_NK_REC *parent, REGF_FILE *outfile,
1020                                  const char *parentpath )
1021 {
1022         REGF_NK_REC *key, *subkey;
1023         struct regval_ctr *values = NULL;
1024         struct regsubkey_ctr *subkeys = NULL;
1025         int i;
1026         char *path = NULL;
1027         WERROR werr;
1028
1029         werr = regsubkey_ctr_init(infile->mem_ctx, &subkeys);
1030         if (!W_ERROR_IS_OK(werr)) {
1031                 DEBUG(0, ("write_registry_tree: regsubkey_ctr_init failed: "
1032                           "%s\n", win_errstr(werr)));
1033                 return false;
1034         }
1035
1036         werr = regval_ctr_init(subkeys, &values);
1037         if (!W_ERROR_IS_OK(werr)) {
1038                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
1039                 TALLOC_FREE(subkeys);
1040                 return false;
1041         }
1042
1043         /* copy values into the struct regval_ctr */
1044
1045         for ( i=0; i<nk->num_values; i++ ) {
1046                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
1047                         nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
1048         }
1049
1050         /* copy subkeys into the struct regsubkey_ctr */
1051
1052         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1053                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
1054         }
1055
1056         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
1057
1058         /* write each one of the subkeys out */
1059
1060         path = talloc_asprintf(subkeys,
1061                         "%s%s%s",
1062                         parentpath,
1063                         parent ? "\\" : "",
1064                         nk->keyname);
1065         if (!path) {
1066                 TALLOC_FREE(subkeys);
1067                 return false;
1068         }
1069
1070         nk->subkey_index = 0;
1071         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1072                 write_registry_tree( infile, subkey, key, outfile, path );
1073         }
1074
1075         d_printf("[%s]\n", path );
1076         TALLOC_FREE(subkeys);
1077
1078         return true;
1079 }
1080
1081 /********************************************************************
1082 ********************************************************************/
1083
1084 static int rpc_registry_dump(struct net_context *c, int argc, const char **argv)
1085 {
1086         REGF_FILE   *registry;
1087         REGF_NK_REC *nk;
1088
1089         if (argc != 1 || c->display_usage) {
1090                 d_printf("%s\n%s",
1091                          _("Usage:"),
1092                          _("net rpc registry dump <file> \n"));
1093                 return -1;
1094         }
1095
1096         d_printf(_("Opening %s...."), argv[0]);
1097         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
1098                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
1099                 return 1;
1100         }
1101         d_printf(_("ok\n"));
1102
1103         /* get the root of the registry file */
1104
1105         if ((nk = regfio_rootkey( registry )) == NULL) {
1106                 d_fprintf(stderr, _("Could not get rootkey\n"));
1107                 regfio_close( registry );
1108                 return 1;
1109         }
1110         d_printf("[%s]\n", nk->keyname);
1111         dump_values( nk );
1112         d_printf("\n");
1113
1114         dump_registry_tree( registry, nk, nk->keyname );
1115
1116 #if 0
1117         talloc_report_full( registry->mem_ctx, stderr );
1118 #endif
1119         d_printf(_("Closing registry..."));
1120         regfio_close( registry );
1121         d_printf(_("ok\n"));
1122
1123         return 0;
1124 }
1125
1126 /********************************************************************
1127 ********************************************************************/
1128
1129 static int rpc_registry_copy(struct net_context *c, int argc, const char **argv )
1130 {
1131         REGF_FILE   *infile = NULL, *outfile = NULL;
1132         REGF_NK_REC *nk;
1133         int result = 1;
1134
1135         if (argc != 2 || c->display_usage) {
1136                 d_printf("%s\n%s",
1137                          _("Usage:"),
1138                          _("net rpc registry copy <srcfile> <newfile>\n"));
1139                 return -1;
1140         }
1141
1142         d_printf(_("Opening %s...."), argv[0]);
1143         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
1144                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
1145                 return 1;
1146         }
1147         d_printf(_("ok\n"));
1148
1149         d_printf(_("Opening %s...."), argv[1]);
1150         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
1151                 d_fprintf(stderr, _("Failed to open %s for writing\n"),argv[1]);
1152                 goto out;
1153         }
1154         d_printf(_("ok\n"));
1155
1156         /* get the root of the registry file */
1157
1158         if ((nk = regfio_rootkey( infile )) == NULL) {
1159                 d_fprintf(stderr, _("Could not get rootkey\n"));
1160                 goto out;
1161         }
1162         d_printf(_("RootKey: [%s]\n"), nk->keyname);
1163
1164         write_registry_tree( infile, nk, NULL, outfile, "" );
1165
1166         result = 0;
1167
1168 out:
1169
1170         d_printf(_("Closing %s..."), argv[1]);
1171         if (outfile) {
1172                 regfio_close( outfile );
1173         }
1174         d_printf(_("ok\n"));
1175
1176         d_printf(_("Closing %s..."), argv[0]);
1177         if (infile) {
1178                 regfio_close( infile );
1179         }
1180         d_printf(_("ok\n"));
1181
1182         return( result);
1183 }
1184
1185 /********************************************************************
1186 ********************************************************************/
1187
1188 static NTSTATUS rpc_registry_getsd_internal(struct net_context *c,
1189                                             const struct dom_sid *domain_sid,
1190                                             const char *domain_name,
1191                                             struct cli_state *cli,
1192                                             struct rpc_pipe_client *pipe_hnd,
1193                                             TALLOC_CTX *mem_ctx,
1194                                             int argc,
1195                                             const char **argv)
1196 {
1197         struct policy_handle pol_hive, pol_key;
1198         NTSTATUS status;
1199         enum ndr_err_code ndr_err;
1200         struct KeySecurityData *sd = NULL;
1201         uint32_t sec_info;
1202         DATA_BLOB blob;
1203         struct security_descriptor sec_desc;
1204         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED |
1205                                SEC_FLAG_SYSTEM_SECURITY;
1206
1207         if (argc <1 || argc > 2 || c->display_usage) {
1208                 d_printf("%s\n%s",
1209                          _("Usage:"),
1210                          _("net rpc registry getsd <path> <secinfo>\n"));
1211                 d_printf("%s  net rpc registry getsd "
1212                            "'HKLM\\Software\\Samba'\n", _("Example:"));
1213                 return NT_STATUS_INVALID_PARAMETER;
1214         }
1215
1216         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
1217                                   access_mask,
1218                                   &pol_hive, &pol_key);
1219         if (!NT_STATUS_IS_OK(status)) {
1220                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
1221                           nt_errstr(status));
1222                 return status;
1223         }
1224
1225         sd = TALLOC_ZERO_P(mem_ctx, struct KeySecurityData);
1226         if (!sd) {
1227                 status = NT_STATUS_NO_MEMORY;
1228                 goto out;
1229         }
1230
1231         sd->size = 0x1000;
1232
1233         if (argc >= 2) {
1234                 sscanf(argv[1], "%x", &sec_info);
1235         } else {
1236                 sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
1237         }
1238
1239         status = registry_getsd(mem_ctx, pipe_hnd, &pol_key, sec_info, sd);
1240         if (!NT_STATUS_IS_OK(status)) {
1241                 d_fprintf(stderr, _("getting sd failed: %s\n"),
1242                           nt_errstr(status));
1243                 goto out;
1244         }
1245
1246         blob.data = sd->data;
1247         blob.length = sd->size;
1248
1249         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &sec_desc,
1250                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1251         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1252                 status = ndr_map_error2ntstatus(ndr_err);
1253                 goto out;
1254         }
1255         status = NT_STATUS_OK;
1256
1257         display_sec_desc(&sec_desc);
1258
1259  out:
1260         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
1261         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
1262
1263         return status;
1264 }
1265
1266
1267 static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv)
1268 {
1269         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
1270                 rpc_registry_getsd_internal, argc, argv);
1271 }
1272
1273 /********************************************************************
1274 ********************************************************************/
1275
1276 int net_rpc_registry(struct net_context *c, int argc, const char **argv)
1277 {
1278         struct functable func[] = {
1279                 {
1280                         "enumerate",
1281                         rpc_registry_enumerate,
1282                         NET_TRANSPORT_RPC,
1283                         N_("Enumerate registry keys and values"),
1284                         N_("net rpc registry enumerate\n"
1285                            "    Enumerate registry keys and values")
1286                 },
1287                 {
1288                         "createkey",
1289                         rpc_registry_createkey,
1290                         NET_TRANSPORT_RPC,
1291                         N_("Create a new registry key"),
1292                         N_("net rpc registry createkey\n"
1293                            "    Create a new registry key")
1294                 },
1295                 {
1296                         "deletekey",
1297                         rpc_registry_deletekey,
1298                         NET_TRANSPORT_RPC,
1299                         N_("Delete a registry key"),
1300                         N_("net rpc registry deletekey\n"
1301                            "    Delete a registry key")
1302                 },
1303                 {
1304                         "getvalue",
1305                         rpc_registry_getvalue,
1306                         NET_TRANSPORT_RPC,
1307                         N_("Print a registry value"),
1308                         N_("net rpc registry getvalue\n"
1309                            "    Print a registry value")
1310                 },
1311                 {
1312                         "getvalueraw",
1313                         rpc_registry_getvalueraw,
1314                         NET_TRANSPORT_RPC,
1315                         N_("Print a registry value"),
1316                         N_("net rpc registry getvalueraw\n"
1317                            "    Print a registry value (raw version)")
1318                 },
1319                 {
1320                         "setvalue",
1321                         rpc_registry_setvalue,
1322                         NET_TRANSPORT_RPC,
1323                         N_("Set a new registry value"),
1324                         N_("net rpc registry setvalue\n"
1325                            "    Set a new registry value")
1326                 },
1327                 {
1328                         "deletevalue",
1329                         rpc_registry_deletevalue,
1330                         NET_TRANSPORT_RPC,
1331                         N_("Delete a registry value"),
1332                         N_("net rpc registry deletevalue\n"
1333                            "    Delete a registry value")
1334                 },
1335                 {
1336                         "save",
1337                         rpc_registry_save,
1338                         NET_TRANSPORT_RPC,
1339                         N_("Save a registry file"),
1340                         N_("net rpc registry save\n"
1341                            "    Save a registry file")
1342                 },
1343                 {
1344                         "dump",
1345                         rpc_registry_dump,
1346                         NET_TRANSPORT_RPC,
1347                         N_("Dump a registry file"),
1348                         N_("net rpc registry dump\n"
1349                            "    Dump a registry file")
1350                 },
1351                 {
1352                         "copy",
1353                         rpc_registry_copy,
1354                         NET_TRANSPORT_RPC,
1355                         N_("Copy a registry file"),
1356                         N_("net rpc registry copy\n"
1357                            "    Copy a registry file")
1358                 },
1359                 {
1360                         "getsd",
1361                         rpc_registry_getsd,
1362                         NET_TRANSPORT_RPC,
1363                         N_("Get security descriptor"),
1364                         N_("net rpc registry getsd\n"
1365                            "    Get security descriptior")
1366                 },
1367                 {NULL, NULL, 0, NULL, NULL}
1368         };
1369
1370         return net_run_function(c, argc, argv, "net rpc registry", func);
1371 }