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