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