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