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