r24005: Attempt to fix the build on host deckchair
[amitay/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 "utils/net.h"
22 #include "regfio.h"
23 #include "reg_objects.h"
24
25 static BOOL reg_hive_key(const char *fullname, uint32 *reg_type,
26                          const char **key_name)
27 {
28         const char *sep;
29         ptrdiff_t len;
30
31         sep = strchr_m(fullname, '\\');
32
33         if (sep != NULL) {
34                 len = sep - fullname;
35                 *key_name = sep+1;
36         }
37         else {
38                 len = strlen(fullname);
39                 *key_name = "";
40         }
41
42         if (strnequal(fullname, "HKLM", len) ||
43             strnequal(fullname, "HKEY_LOCAL_MACHINE", len))
44                 (*reg_type) = HKEY_LOCAL_MACHINE;
45         else if (strnequal(fullname, "HKCR", len) ||
46                  strnequal(fullname, "HKEY_CLASSES_ROOT", len))
47                 (*reg_type) = HKEY_CLASSES_ROOT;
48         else if (strnequal(fullname, "HKU", len) ||
49                  strnequal(fullname, "HKEY_USERS", len))
50                 (*reg_type) = HKEY_USERS;
51         else if (strnequal(fullname, "HKPD", len) ||
52                  strnequal(fullname, "HKEY_PERFORMANCE_DATA", len))
53                 (*reg_type) = HKEY_PERFORMANCE_DATA;
54         else {
55                 DEBUG(10,("reg_hive_key: unrecognised hive key %s\n",
56                           fullname));
57                 return False;
58         }
59
60         return True;
61 }
62
63 static NTSTATUS registry_openkey(TALLOC_CTX *mem_ctx,
64                                  struct rpc_pipe_client *pipe_hnd,
65                                  const char *name, uint32 access_mask,
66                                  struct policy_handle *hive_hnd,
67                                  struct policy_handle *key_hnd)
68 {
69         uint32 hive;
70         NTSTATUS status;
71         struct winreg_String key;
72
73         if (!reg_hive_key(name, &hive, &key.name)) {
74                 return NT_STATUS_INVALID_PARAMETER;
75         }
76
77         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, access_mask,
78                                        hive_hnd);
79         if (!(NT_STATUS_IS_OK(status))) {
80                 return status;
81         }
82
83         status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, hive_hnd, key, 0,
84                                        access_mask, key_hnd);
85         if (!(NT_STATUS_IS_OK(status))) {
86                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, hive_hnd);
87                 return status;
88         }
89
90         return NT_STATUS_OK;
91 }
92
93 static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
94                                   struct rpc_pipe_client *pipe_hnd,
95                                   struct policy_handle *key_hnd,
96                                   uint32 *pnum_keys, char ***pnames,
97                                   char ***pclasses, NTTIME ***pmodtimes)
98 {
99         TALLOC_CTX *mem_ctx;
100         NTSTATUS status;
101         uint32 num_subkeys, max_subkeylen, max_classlen;
102         uint32 num_values, max_valnamelen, max_valbufsize;
103         uint32 i;
104         NTTIME last_changed_time;
105         uint32 secdescsize;
106         struct winreg_String classname;
107         char **names, **classes;
108         NTTIME **modtimes;
109
110         if (!(mem_ctx = talloc_new(ctx))) {
111                 return NT_STATUS_NO_MEMORY;
112         }
113
114         ZERO_STRUCT(classname);
115         status = rpccli_winreg_QueryInfoKey(
116                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
117                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
118                 &max_valbufsize, &secdescsize, &last_changed_time );
119
120         if (!NT_STATUS_IS_OK(status)) {
121                 goto error;
122         }
123
124         if (num_subkeys == 0) {
125                 *pnum_keys = 0;
126                 TALLOC_FREE(mem_ctx);
127                 return NT_STATUS_OK;
128         }
129
130         if ((!(names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
131             (!(classes = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
132             (!(modtimes = TALLOC_ZERO_ARRAY(mem_ctx, NTTIME *,
133                                             num_subkeys)))) {
134                 status = NT_STATUS_NO_MEMORY;
135                 goto error;
136         }
137
138         for (i=0; i<num_subkeys; i++) {
139                 char c, n;
140                 struct winreg_StringBuf class_buf;
141                 struct winreg_StringBuf name_buf;
142                 NTTIME modtime;
143
144                 c = '\0';
145                 class_buf.name = &c;
146                 class_buf.size = max_classlen+2;
147
148                 n = '\0';
149                 name_buf.name = &n;
150                 name_buf.size = max_subkeylen+2;
151
152                 ZERO_STRUCT(modtime);
153
154                 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key_hnd,
155                                                i, &name_buf, &class_buf,
156                                                &modtime);
157                 
158                 if (W_ERROR_EQUAL(ntstatus_to_werror(status),
159                                   WERR_NO_MORE_ITEMS) ) {
160                         status = NT_STATUS_OK;
161                         break;
162                 }
163                 if (!NT_STATUS_IS_OK(status)) {
164                         goto error;
165                 }
166
167                 classes[i] = NULL;
168
169                 if (class_buf.name &&
170                     (!(classes[i] = talloc_strdup(classes, class_buf.name)))) {
171                         status = NT_STATUS_NO_MEMORY;
172                         goto error;
173                 }
174
175                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
176                         status = NT_STATUS_NO_MEMORY;
177                         goto error;
178                 }
179
180                 if ((!(modtimes[i] = (NTTIME *)talloc_memdup(
181                                modtimes, &modtime, sizeof(modtime))))) {
182                         status = NT_STATUS_NO_MEMORY;
183                         goto error;
184                 }
185         }
186
187         *pnum_keys = num_subkeys;
188
189         if (pnames) {
190                 *pnames = talloc_move(ctx, &names);
191         }
192         if (pclasses) {
193                 *pclasses = talloc_move(ctx, &classes);
194         }
195         if (pmodtimes) {
196                 *pmodtimes = talloc_move(ctx, &modtimes);
197         }
198
199         status = NT_STATUS_OK;
200
201  error:
202         TALLOC_FREE(mem_ctx);
203         return status;
204 }
205
206 static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
207                                     struct rpc_pipe_client *pipe_hnd,
208                                     struct policy_handle *key_hnd,
209                                     uint32 *pnum_values, char ***pvalnames,
210                                     struct registry_value ***pvalues)
211 {
212         TALLOC_CTX *mem_ctx;
213         NTSTATUS status;
214         uint32 num_subkeys, max_subkeylen, max_classlen;
215         uint32 num_values, max_valnamelen, max_valbufsize;
216         uint32 i;
217         NTTIME last_changed_time;
218         uint32 secdescsize;
219         struct winreg_String classname;
220         struct registry_value **values;
221         char **names;
222
223         if (!(mem_ctx = talloc_new(ctx))) {
224                 return NT_STATUS_NO_MEMORY;
225         }
226
227         ZERO_STRUCT(classname);
228         status = rpccli_winreg_QueryInfoKey(
229                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
230                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
231                 &max_valbufsize, &secdescsize, &last_changed_time );
232
233         if (!NT_STATUS_IS_OK(status)) {
234                 goto error;
235         }
236
237         if (num_values == 0) {
238                 *pnum_values = 0;
239                 TALLOC_FREE(mem_ctx);
240                 return NT_STATUS_OK;
241         }
242
243         if ((!(names = TALLOC_ARRAY(mem_ctx, char *, num_values))) ||
244             (!(values = TALLOC_ARRAY(mem_ctx, struct registry_value *,
245                                      num_values)))) {
246                 status = NT_STATUS_NO_MEMORY;
247                 goto error;
248         }
249
250         for (i=0; i<num_values; i++) {
251                 enum winreg_Type type = REG_NONE;
252                 uint8 *data = NULL;
253                 uint32 data_size;
254                 uint32 value_length;
255
256                 char n;
257                 struct winreg_ValNameBuf name_buf;
258                 WERROR err;
259
260                 n = '\0';
261                 name_buf.name = &n;
262                 name_buf.size = max_valnamelen + 2;
263
264                 data_size = max_valbufsize;
265                 data = (uint8 *)TALLOC(mem_ctx, data_size);
266                 value_length = 0;
267
268                 status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, key_hnd,
269                                                  i, &name_buf, &type,
270                                                  data, &data_size,
271                                                  &value_length );
272
273                 if ( W_ERROR_EQUAL(ntstatus_to_werror(status),
274                                    WERR_NO_MORE_ITEMS) ) {
275                         status = NT_STATUS_OK;
276                         break;
277                 }
278
279                 if (!(NT_STATUS_IS_OK(status))) {
280                         goto error;
281                 }
282
283                 if (name_buf.name == NULL) {
284                         status = NT_STATUS_INVALID_PARAMETER;
285                         goto error;
286                 }
287
288                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
289                         status = NT_STATUS_NO_MEMORY;
290                         goto error;
291                 }
292
293                 err = registry_pull_value(values, &values[i], type, data,
294                                           data_size, value_length);
295                 if (!W_ERROR_IS_OK(err)) {
296                         status = werror_to_ntstatus(err);
297                         goto error;
298                 }
299         }
300
301         *pnum_values = num_values;
302
303         if (pvalnames) {
304                 *pvalnames = talloc_move(ctx, &names);
305         }
306         if (pvalues) {
307                 *pvalues = talloc_move(ctx, &values);
308         }
309
310         status = NT_STATUS_OK;
311
312  error:
313         TALLOC_FREE(mem_ctx);
314         return status;
315 }
316
317 static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
318                                   struct rpc_pipe_client *pipe_hnd,
319                                   struct policy_handle *key_hnd,
320                                   const char *name,
321                                   const struct registry_value *value)
322 {
323         struct winreg_String name_string;
324         DATA_BLOB blob;
325         NTSTATUS result;
326         WERROR err;
327
328         err = registry_push_value(mem_ctx, value, &blob);
329         if (!W_ERROR_IS_OK(err)) {
330                 return werror_to_ntstatus(err);
331         }
332
333         name_string.name = name;
334         result = rpccli_winreg_SetValue(pipe_hnd, blob.data, key_hnd,
335                                         name_string, value->type,
336                                         blob.data, blob.length);
337         TALLOC_FREE(blob.data);
338         return result;
339 }
340
341 static NTSTATUS rpc_registry_setvalue_internal(const DOM_SID *domain_sid,
342                                                const char *domain_name, 
343                                                struct cli_state *cli,
344                                                struct rpc_pipe_client *pipe_hnd,
345                                                TALLOC_CTX *mem_ctx, 
346                                                int argc,
347                                                const char **argv )
348 {
349         struct policy_handle hive_hnd, key_hnd;
350         NTSTATUS status;
351         struct registry_value value;
352
353         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_WRITE,
354                                   &hive_hnd, &key_hnd);
355         if (!NT_STATUS_IS_OK(status)) {
356                 d_fprintf(stderr, "registry_openkey failed: %s\n",
357                           nt_errstr(status));
358                 return status;
359         }
360
361         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
362                 d_fprintf(stderr, "Too many args for type %s\n", argv[2]);
363                 return NT_STATUS_NOT_IMPLEMENTED;
364         }
365
366         if (strequal(argv[2], "dword")) {
367                 value.type = REG_DWORD;
368                 value.v.dword = strtoul(argv[3], NULL, 10);
369         }
370         else if (strequal(argv[2], "sz")) {
371                 value.type = REG_SZ;
372                 value.v.sz.len = strlen(argv[3])+1;
373                 value.v.sz.str = CONST_DISCARD(char *, argv[3]);
374         }
375         else {
376                 d_fprintf(stderr, "type \"%s\" not implemented\n", argv[2]);
377                 status = NT_STATUS_NOT_IMPLEMENTED;
378                 goto error;
379         }
380
381         status = registry_setvalue(mem_ctx, pipe_hnd, &key_hnd,
382                                    argv[1], &value);
383
384         if (!NT_STATUS_IS_OK(status)) {
385                 d_fprintf(stderr, "registry_setvalue failed: %s\n",
386                           nt_errstr(status));
387         }
388
389  error:
390         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
391         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
392
393         return NT_STATUS_OK;
394 }
395
396 static int rpc_registry_setvalue( int argc, const char **argv )
397 {
398         if (argc < 4) {
399                 d_fprintf(stderr, "usage: net rpc registry setvalue <key> "
400                           "<valuename> <type> [<val>]+\n");
401                 return -1;
402         }
403
404         return run_rpc_command( NULL, PI_WINREG, 0, 
405                 rpc_registry_setvalue_internal, argc, argv );
406 }
407
408 static NTSTATUS rpc_registry_deletevalue_internal(const DOM_SID *domain_sid,
409                                                   const char *domain_name, 
410                                                   struct cli_state *cli,
411                                                   struct rpc_pipe_client *pipe_hnd,
412                                                   TALLOC_CTX *mem_ctx, 
413                                                   int argc,
414                                                   const char **argv )
415 {
416         struct policy_handle hive_hnd, key_hnd;
417         NTSTATUS status;
418         struct winreg_String valuename;
419
420         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_WRITE,
421                                   &hive_hnd, &key_hnd);
422         if (!NT_STATUS_IS_OK(status)) {
423                 d_fprintf(stderr, "registry_openkey failed: %s\n",
424                           nt_errstr(status));
425                 return status;
426         }
427
428         valuename.name = argv[1];
429
430         status = rpccli_winreg_DeleteValue(pipe_hnd, mem_ctx, &key_hnd,
431                                            valuename);
432
433         if (!NT_STATUS_IS_OK(status)) {
434                 d_fprintf(stderr, "registry_deletevalue failed: %s\n",
435                           nt_errstr(status));
436         }
437
438         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
439         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
440
441         return NT_STATUS_OK;
442 }
443
444 static int rpc_registry_deletevalue( int argc, const char **argv )
445 {
446         if (argc != 2) {
447                 d_fprintf(stderr, "usage: net rpc registry deletevalue <key> "
448                           "<valuename>\n");
449                 return -1;
450         }
451
452         return run_rpc_command( NULL, PI_WINREG, 0, 
453                 rpc_registry_deletevalue_internal, argc, argv );
454 }
455
456 static NTSTATUS rpc_registry_createkey_internal(const DOM_SID *domain_sid,
457                                                 const char *domain_name, 
458                                                 struct cli_state *cli,
459                                                 struct rpc_pipe_client *pipe_hnd,
460                                                 TALLOC_CTX *mem_ctx, 
461                                                 int argc,
462                                                 const char **argv )
463 {
464         uint32 hive;
465         struct policy_handle hive_hnd, key_hnd;
466         struct winreg_String key, keyclass;
467         enum winreg_CreateAction action;
468         NTSTATUS status;
469
470         if (!reg_hive_key(argv[0], &hive, &key.name)) {
471                 return NT_STATUS_INVALID_PARAMETER;
472         }
473
474         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
475                                        REG_KEY_READ|REG_KEY_WRITE,
476                                        &hive_hnd);
477         if (!(NT_STATUS_IS_OK(status))) {
478                 return status;
479         }
480
481         action = REG_ACTION_NONE;
482         keyclass.name = "";
483
484         status = rpccli_winreg_CreateKey(pipe_hnd, mem_ctx, &hive_hnd, key,
485                                          keyclass, 0, REG_KEY_READ, NULL,
486                                          &key_hnd, &action);
487         if (!NT_STATUS_IS_OK(status)) {
488                 d_fprintf(stderr, "createkey returned %s\n",
489                           nt_errstr(status));
490                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
491                 return status;
492         }
493
494         switch (action) {
495                 case REG_ACTION_NONE:
496                         d_printf("createkey did nothing -- huh?\n");
497                         break;
498                 case REG_CREATED_NEW_KEY:
499                         d_printf("createkey created %s\n", argv[0]);
500                         break;
501                 case REG_OPENED_EXISTING_KEY:
502                         d_printf("createkey opened existing %s\n", argv[0]);
503                         break;
504         }
505
506         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
507         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
508
509         return status;
510 }
511
512 static int rpc_registry_createkey( int argc, const char **argv )
513 {
514         if (argc != 1) {
515                 d_fprintf(stderr, "usage: net rpc registry createkey <key>\n");
516                 return -1;
517         }
518
519         return run_rpc_command( NULL, PI_WINREG, 0, 
520                 rpc_registry_createkey_internal, argc, argv );
521 }
522
523 static NTSTATUS rpc_registry_deletekey_internal(const DOM_SID *domain_sid,
524                                                 const char *domain_name, 
525                                                 struct cli_state *cli,
526                                                 struct rpc_pipe_client *pipe_hnd,
527                                                 TALLOC_CTX *mem_ctx, 
528                                                 int argc,
529                                                 const char **argv )
530 {
531         uint32 hive;
532         struct policy_handle hive_hnd;
533         struct winreg_String key;
534         NTSTATUS status;
535
536         if (!reg_hive_key(argv[0], &hive, &key.name)) {
537                 return NT_STATUS_INVALID_PARAMETER;
538         }
539
540         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, REG_KEY_WRITE,
541                                        &hive_hnd);
542         if (!(NT_STATUS_IS_OK(status))) {
543                 return status;
544         }
545
546         status = rpccli_winreg_DeleteKey(pipe_hnd, mem_ctx, &hive_hnd, key);
547         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
548
549         if (!NT_STATUS_IS_OK(status)) {
550                 d_fprintf(stderr, "deletekey returned %s\n",
551                           nt_errstr(status));
552         }
553
554         return status;
555 }
556
557 static int rpc_registry_deletekey( int argc, const char **argv )
558 {
559         if (argc != 1) {
560                 d_fprintf(stderr, "usage: net rpc registry deletekey <key>\n");
561                 return -1;
562         }
563
564         return run_rpc_command( NULL, PI_WINREG, 0, 
565                 rpc_registry_deletekey_internal, argc, argv );
566 }
567
568 /********************************************************************
569 ********************************************************************/
570
571 static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
572                                                 const char *domain_name, 
573                                                 struct cli_state *cli,
574                                                 struct rpc_pipe_client *pipe_hnd,
575                                                 TALLOC_CTX *mem_ctx, 
576                                                 int argc,
577                                                 const char **argv )
578 {
579         POLICY_HND pol_hive, pol_key; 
580         NTSTATUS status;
581         uint32 num_subkeys = 0;
582         uint32 num_values = 0;
583         char **names = NULL, **classes = NULL;
584         NTTIME **modtimes = NULL;
585         uint32 i;
586         struct registry_value **values = NULL;
587         
588         if (argc != 1 ) {
589                 d_printf("Usage:    net rpc enumerate <path> [recurse]\n");
590                 d_printf("Example:  net rpc enumerate 'HKLM\\Software\\Samba'\n");
591                 return NT_STATUS_OK;
592         }
593
594         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
595                                   &pol_hive, &pol_key);
596         if (!NT_STATUS_IS_OK(status)) {
597                 d_fprintf(stderr, "registry_openkey failed: %s\n",
598                           nt_errstr(status));
599                 return status;
600         }
601
602         status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
603                                    &names, &classes, &modtimes);
604         if (!NT_STATUS_IS_OK(status)) {
605                 d_fprintf(stderr, "enumerating keys failed: %s\n",
606                           nt_errstr(status));
607                 return status;
608         }
609
610         for (i=0; i<num_subkeys; i++) {
611                 d_printf("Keyname   = %s\n", names[i]);
612                 d_printf("Modtime   = %s\n", modtimes[i]
613                          ? http_timestring(nt_time_to_unix(*modtimes[i]))
614                          : "None");
615                 d_printf("\n" );
616         }
617
618         status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
619                                      &names, &values);
620         if (!NT_STATUS_IS_OK(status)) {
621                 d_fprintf(stderr, "enumerating values failed: %s\n",
622                           nt_errstr(status));
623                 return status;
624         }
625
626         for (i=0; i<num_values; i++) {
627                 struct registry_value *v = values[i];
628                 d_printf("Valuename  = %s\n", names[i]);
629                 d_printf("Type       = %s\n",
630                          reg_type_lookup(v->type));
631                 switch(v->type) {
632                 case REG_DWORD:
633                         d_printf("Value      = %d\n", v->v.dword);
634                         break;
635                 case REG_SZ:
636                 case REG_EXPAND_SZ:
637                         d_printf("Value      = \"%s\"\n", v->v.sz.str);
638                         break;
639                 case REG_MULTI_SZ: {
640                         uint32 j;
641                         for (j = 0; j < v->v.multi_sz.num_strings; j++) {
642                                 d_printf("Value[%3.3d] = \"%s\"\n", j,
643                                          v->v.multi_sz.strings[j]);
644                         }
645                         break;
646                 }
647                 case REG_BINARY:
648                         d_printf("Value      = %d bytes\n",
649                                  (int)v->v.binary.length);
650                         break;
651                 default:
652                         d_printf("Value      = <unprintable>\n");
653                         break;
654                 }
655                         
656                 d_printf("\n");
657         }
658
659         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key );
660         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive );
661
662         return status;
663 }
664
665 /********************************************************************
666 ********************************************************************/
667
668 static int rpc_registry_enumerate( int argc, const char **argv )
669 {
670         return run_rpc_command( NULL, PI_WINREG, 0, 
671                 rpc_registry_enumerate_internal, argc, argv );
672 }
673
674 /********************************************************************
675 ********************************************************************/
676
677 static NTSTATUS rpc_registry_save_internal(const DOM_SID *domain_sid,
678                                         const char *domain_name, 
679                                         struct cli_state *cli,
680                                         struct rpc_pipe_client *pipe_hnd,
681                                         TALLOC_CTX *mem_ctx, 
682                                         int argc,
683                                         const char **argv )
684 {
685         WERROR result = WERR_GENERAL_FAILURE;
686         POLICY_HND pol_hive, pol_key; 
687         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
688         struct winreg_String filename;
689         
690         if (argc != 2 ) {
691                 d_printf("Usage:    net rpc backup <path> <file> \n");
692                 return NT_STATUS_OK;
693         }
694         
695         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
696                                   &pol_hive, &pol_key);
697         if (!NT_STATUS_IS_OK(status)) {
698                 d_fprintf(stderr, "registry_openkey failed: %s\n",
699                           nt_errstr(status));
700                 return status;
701         }
702
703         filename.name = argv[1];
704         status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL  );
705         if ( !W_ERROR_IS_OK(result) ) {
706                 d_fprintf(stderr, "Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]);
707         }
708         
709         /* cleanup */
710         
711         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key );
712         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive );
713
714         return status;
715 }
716
717 /********************************************************************
718 ********************************************************************/
719
720 static int rpc_registry_save( int argc, const char **argv )
721 {
722         return run_rpc_command( NULL, PI_WINREG, 0, 
723                 rpc_registry_save_internal, argc, argv );
724 }
725
726
727 /********************************************************************
728 ********************************************************************/
729
730 static void dump_values( REGF_NK_REC *nk )
731 {
732         int i, j;
733         pstring data_str;
734         uint32 data_size, data;
735
736         if ( !nk->values )
737                 return;
738
739         for ( i=0; i<nk->num_values; i++ ) {
740                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
741                 d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
742
743                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
744                 switch ( nk->values[i].type ) {
745                         case REG_SZ:
746                                 rpcstr_pull( data_str, nk->values[i].data, sizeof(data_str), -1, STR_TERMINATE );
747                                 d_printf( "%s", data_str );
748                                 break;
749                         case REG_MULTI_SZ:
750                         case REG_EXPAND_SZ:
751                                 for ( j=0; j<data_size; j++ ) {
752                                         d_printf( "%c", nk->values[i].data[j] );
753                                 }
754                                 break;
755                         case REG_DWORD:
756                                 data = IVAL( nk->values[i].data, 0 );
757                                 d_printf("0x%x", data );
758                                 break;
759                         case REG_BINARY:
760                                 for ( j=0; j<data_size; j++ ) {
761                                         d_printf( "%x", nk->values[i].data[j] );
762                                 }
763                                 break;
764                         default:
765                                 d_printf("unknown");
766                                 break;
767                 }
768
769                 d_printf( "\n" );
770         }
771
772 }
773
774 /********************************************************************
775 ********************************************************************/
776
777 static BOOL dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
778 {
779         REGF_NK_REC *key;
780         pstring regpath;
781
782         /* depth first dump of the registry tree */
783
784         while ( (key = regfio_fetch_subkey( file, nk )) ) {
785                 pstr_sprintf( regpath, "%s\\%s", parent, key->keyname );
786                 d_printf("[%s]\n", regpath );
787                 dump_values( key );
788                 d_printf("\n");
789                 dump_registry_tree( file, key, regpath );
790         }
791
792         return True;
793 }
794
795 /********************************************************************
796 ********************************************************************/
797
798 static BOOL write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk, 
799                                  REGF_NK_REC *parent, REGF_FILE *outfile,
800                                  const char *parentpath )
801 {
802         REGF_NK_REC *key, *subkey;
803         REGVAL_CTR *values;
804         REGSUBKEY_CTR *subkeys;
805         int i;
806         pstring path;
807
808         if ( !( subkeys = TALLOC_ZERO_P( infile->mem_ctx, REGSUBKEY_CTR )) ) {
809                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
810                 return False;
811         }
812
813         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) ) {
814                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
815                 return False;
816         }
817
818         /* copy values into the REGVAL_CTR */
819         
820         for ( i=0; i<nk->num_values; i++ ) {
821                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
822                         (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
823         }
824
825         /* copy subkeys into the REGSUBKEY_CTR */
826         
827         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
828                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
829         }
830         
831         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
832
833         /* write each one of the subkeys out */
834
835         pstr_sprintf( path, "%s%s%s", parentpath, parent ? "\\" : "", nk->keyname );
836         nk->subkey_index = 0;
837         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
838                 write_registry_tree( infile, subkey, key, outfile, path );
839         }
840
841         TALLOC_FREE( subkeys );
842
843         d_printf("[%s]\n", path );
844         
845         return True;
846 }
847
848 /********************************************************************
849 ********************************************************************/
850
851 static int rpc_registry_dump( int argc, const char **argv )
852 {
853         REGF_FILE   *registry;
854         REGF_NK_REC *nk;
855         
856         if (argc != 1 ) {
857                 d_printf("Usage:    net rpc dump <file> \n");
858                 return 0;
859         }
860         
861         d_printf("Opening %s....", argv[0]);
862         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
863                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
864                 return 1;
865         }
866         d_printf("ok\n");
867         
868         /* get the root of the registry file */
869         
870         if ((nk = regfio_rootkey( registry )) == NULL) {
871                 d_fprintf(stderr, "Could not get rootkey\n");
872                 regfio_close( registry );
873                 return 1;
874         }
875         d_printf("[%s]\n", nk->keyname);
876         dump_values( nk );
877         d_printf("\n");
878
879         dump_registry_tree( registry, nk, nk->keyname );
880
881 #if 0
882         talloc_report_full( registry->mem_ctx, stderr );
883 #endif  
884         d_printf("Closing registry...");
885         regfio_close( registry );
886         d_printf("ok\n");
887
888         return 0;
889 }
890
891 /********************************************************************
892 ********************************************************************/
893
894 static int rpc_registry_copy( int argc, const char **argv )
895 {
896         REGF_FILE   *infile = NULL, *outfile = NULL;
897         REGF_NK_REC *nk;
898         int result = 1;
899         
900         if (argc != 2 ) {
901                 d_printf("Usage:    net rpc copy <srcfile> <newfile>\n");
902                 return 0;
903         }
904         
905         d_printf("Opening %s....", argv[0]);
906         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
907                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
908                 return 1;
909         }
910         d_printf("ok\n");
911
912         d_printf("Opening %s....", argv[1]);
913         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
914                 d_fprintf(stderr, "Failed to open %s for writing\n", argv[1]);
915                 goto out;
916         }
917         d_printf("ok\n");
918         
919         /* get the root of the registry file */
920         
921         if ((nk = regfio_rootkey( infile )) == NULL) {
922                 d_fprintf(stderr, "Could not get rootkey\n");
923                 goto out;
924         }
925         d_printf("RootKey: [%s]\n", nk->keyname);
926
927         write_registry_tree( infile, nk, NULL, outfile, "" );
928
929         result = 0;
930
931 out:
932
933         d_printf("Closing %s...", argv[1]);
934         if (outfile) {
935                 regfio_close( outfile );
936         }
937         d_printf("ok\n");
938
939         d_printf("Closing %s...", argv[0]);
940         if (infile) {
941                 regfio_close( infile );
942         }
943         d_printf("ok\n");
944
945         return( result);
946 }
947
948 /********************************************************************
949 ********************************************************************/
950
951 int net_rpc_registry(int argc, const char **argv) 
952 {
953         struct functable2 func[] = {
954                 { "enumerate", rpc_registry_enumerate,
955                   "Enumerate registry keys and values" },
956                 { "createkey",  rpc_registry_createkey,
957                   "Create a new registry key" },
958                 { "deletekey",  rpc_registry_deletekey,
959                   "Delete a registry key" },
960                 { "setvalue",  rpc_registry_setvalue,
961                   "Set a new registry value" },
962                 { "deletevalue",  rpc_registry_deletevalue,
963                   "Delete a registry value" },
964                 { "save", rpc_registry_save,
965                   "Save a registry file" },
966                 { "dump", rpc_registry_dump,
967                   "Dump a registry file" },
968                 { "copy", rpc_registry_copy,
969                   "Copy a registry file" },
970                 {NULL, NULL, NULL}
971         };
972         
973         return net_run_function2(argc, argv, "net rpc registry", func);
974 }