dns: Use new DNS debugclass in DNS server
[kai/samba.git] / source3 / rpc_client / cli_winreg.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  WINREG client routines
5  *
6  *  Copyright (c) 2011      Andreas Schneider <asn@samba.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "../librpc/gen_ndr/ndr_winreg_c.h"
24 #include "../librpc/gen_ndr/ndr_security.h"
25 #include "rpc_client/cli_winreg.h"
26 #include "../libcli/registry/util_reg.h"
27
28 NTSTATUS dcerpc_winreg_query_dword(TALLOC_CTX *mem_ctx,
29                                    struct dcerpc_binding_handle *h,
30                                    struct policy_handle *key_handle,
31                                    const char *value,
32                                    uint32_t *data,
33                                    WERROR *pwerr)
34 {
35         struct winreg_String wvalue;
36         enum winreg_Type type = REG_NONE;
37         uint32_t value_len = 0;
38         uint32_t data_size = 0;
39         NTSTATUS status;
40         DATA_BLOB blob;
41
42         wvalue.name = value;
43
44         status = dcerpc_winreg_QueryValue(h,
45                                           mem_ctx,
46                                           key_handle,
47                                           &wvalue,
48                                           &type,
49                                           NULL,
50                                           &data_size,
51                                           &value_len,
52                                           pwerr);
53         if (!NT_STATUS_IS_OK(status)) {
54                 return status;
55         }
56         if (!W_ERROR_IS_OK(*pwerr)) {
57                 return status;
58         }
59
60         if (type != REG_DWORD) {
61                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
62         }
63
64         if (data_size != 4) {
65                 return NT_STATUS_INVALID_PARAMETER;
66         }
67
68         blob = data_blob_talloc_zero(mem_ctx, data_size);
69         if (blob.data == NULL) {
70                 return NT_STATUS_NO_MEMORY;
71         }
72         value_len = 0;
73
74         status = dcerpc_winreg_QueryValue(h,
75                                           mem_ctx,
76                                           key_handle,
77                                           &wvalue,
78                                           &type,
79                                           blob.data,
80                                           &data_size,
81                                           &value_len,
82                                           pwerr);
83         if (!NT_STATUS_IS_OK(status)) {
84                 return status;
85         }
86         if (!W_ERROR_IS_OK(*pwerr)) {
87                 return status;
88         }
89
90         if (data) {
91                 *data = IVAL(blob.data, 0);
92         }
93
94         return status;
95 }
96
97 NTSTATUS dcerpc_winreg_query_binary(TALLOC_CTX *mem_ctx,
98                                     struct dcerpc_binding_handle *h,
99                                     struct policy_handle *key_handle,
100                                     const char *value,
101                                     DATA_BLOB *data,
102                                     WERROR *pwerr)
103 {
104         struct winreg_String wvalue;
105         enum winreg_Type type = REG_NONE;
106         uint32_t value_len = 0;
107         uint32_t data_size = 0;
108         NTSTATUS status;
109         DATA_BLOB blob;
110
111         ZERO_STRUCT(wvalue);
112         wvalue.name = value;
113
114         status = dcerpc_winreg_QueryValue(h,
115                                           mem_ctx,
116                                           key_handle,
117                                           &wvalue,
118                                           &type,
119                                           NULL,
120                                           &data_size,
121                                           &value_len,
122                                           pwerr);
123         if (!NT_STATUS_IS_OK(status)) {
124                 return status;
125         }
126         if (!W_ERROR_IS_OK(*pwerr)) {
127                 return status;
128         }
129
130         if (type != REG_BINARY) {
131                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
132         }
133
134         blob = data_blob_talloc_zero(mem_ctx, data_size);
135         if (blob.data == NULL) {
136                 return NT_STATUS_NO_MEMORY;
137         }
138         value_len = 0;
139
140         status = dcerpc_winreg_QueryValue(h,
141                                           mem_ctx,
142                                           key_handle,
143                                           &wvalue,
144                                           &type,
145                                           blob.data,
146                                           &data_size,
147                                           &value_len,
148                                           pwerr);
149         if (!NT_STATUS_IS_OK(status)) {
150                 return status;
151         }
152         if (!W_ERROR_IS_OK(*pwerr)) {
153                 return status;
154         }
155
156         if (data) {
157                 data->data = blob.data;
158                 data->length = blob.length;
159         }
160
161         return status;
162 }
163
164 NTSTATUS dcerpc_winreg_query_multi_sz(TALLOC_CTX *mem_ctx,
165                                       struct dcerpc_binding_handle *h,
166                                       struct policy_handle *key_handle,
167                                       const char *value,
168                                       const char ***data,
169                                       WERROR *pwerr)
170 {
171         struct winreg_String wvalue;
172         enum winreg_Type type = REG_NONE;
173         uint32_t value_len = 0;
174         uint32_t data_size = 0;
175         NTSTATUS status;
176         DATA_BLOB blob;
177
178         wvalue.name = value;
179
180         status = dcerpc_winreg_QueryValue(h,
181                                           mem_ctx,
182                                           key_handle,
183                                           &wvalue,
184                                           &type,
185                                           NULL,
186                                           &data_size,
187                                           &value_len,
188                                           pwerr);
189         if (!NT_STATUS_IS_OK(status)) {
190                 return status;
191         }
192         if (!W_ERROR_IS_OK(*pwerr)) {
193                 return status;
194         }
195
196         if (type != REG_MULTI_SZ) {
197                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
198         }
199
200         blob = data_blob_talloc_zero(mem_ctx, data_size);
201         if (blob.data == NULL) {
202                 return NT_STATUS_NO_MEMORY;
203         }
204         value_len = 0;
205
206         status = dcerpc_winreg_QueryValue(h,
207                                           mem_ctx,
208                                           key_handle,
209                                           &wvalue,
210                                           &type,
211                                           blob.data,
212                                           &data_size,
213                                           &value_len,
214                                           pwerr);
215         if (!NT_STATUS_IS_OK(status)) {
216                 return status;
217         }
218         if (!W_ERROR_IS_OK(*pwerr)) {
219                 return status;
220         }
221
222         if (data) {
223                 bool ok;
224
225                 ok = pull_reg_multi_sz(mem_ctx, &blob, data);
226                 if (!ok) {
227                         status = NT_STATUS_NO_MEMORY;
228                 }
229         }
230
231         return status;
232 }
233
234 NTSTATUS dcerpc_winreg_query_sz(TALLOC_CTX *mem_ctx,
235                                       struct dcerpc_binding_handle *h,
236                                       struct policy_handle *key_handle,
237                                       const char *value,
238                                       const char **data,
239                                       WERROR *pwerr)
240 {
241         struct winreg_String wvalue;
242         enum winreg_Type type = REG_NONE;
243         uint32_t value_len = 0;
244         uint32_t data_size = 0;
245         NTSTATUS status;
246         DATA_BLOB blob;
247
248         wvalue.name = value;
249
250         status = dcerpc_winreg_QueryValue(h,
251                                           mem_ctx,
252                                           key_handle,
253                                           &wvalue,
254                                           &type,
255                                           NULL,
256                                           &data_size,
257                                           &value_len,
258                                           pwerr);
259         if (!NT_STATUS_IS_OK(status)) {
260                 return status;
261         }
262         if (!W_ERROR_IS_OK(*pwerr)) {
263                 return status;
264         }
265
266         if (type != REG_SZ) {
267                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
268         }
269
270         blob = data_blob_talloc_zero(mem_ctx, data_size);
271         if (blob.data == NULL) {
272                 return NT_STATUS_NO_MEMORY;
273         }
274         value_len = 0;
275
276         status = dcerpc_winreg_QueryValue(h,
277                                           mem_ctx,
278                                           key_handle,
279                                           &wvalue,
280                                           &type,
281                                           blob.data,
282                                           &data_size,
283                                           &value_len,
284                                           pwerr);
285         if (!NT_STATUS_IS_OK(status)) {
286                 return status;
287         }
288         if (!W_ERROR_IS_OK(*pwerr)) {
289                 return status;
290         }
291
292         if (data) {
293                 bool ok;
294
295                 ok = pull_reg_sz(mem_ctx, &blob, data);
296                 if (!ok) {
297                         status = NT_STATUS_NO_MEMORY;
298                 }
299         }
300
301         return status;
302 }
303
304 NTSTATUS dcerpc_winreg_query_sd(TALLOC_CTX *mem_ctx,
305                                 struct dcerpc_binding_handle *h,
306                                 struct policy_handle *key_handle,
307                                 const char *value,
308                                 struct security_descriptor **data,
309                                 WERROR *pwerr)
310 {
311         NTSTATUS status;
312         DATA_BLOB blob;
313
314         status = dcerpc_winreg_query_binary(mem_ctx,
315                                             h,
316                                             key_handle,
317                                             value,
318                                             &blob,
319                                             pwerr);
320         if (!NT_STATUS_IS_OK(status)) {
321                 return status;
322         }
323         if (!W_ERROR_IS_OK(*pwerr)) {
324                 return status;
325         }
326
327         if (data) {
328                 struct security_descriptor *sd;
329                 enum ndr_err_code ndr_err;
330
331                 sd = talloc_zero(mem_ctx, struct security_descriptor);
332                 if (sd == NULL) {
333                         return NT_STATUS_NO_MEMORY;
334                 }
335
336                 ndr_err = ndr_pull_struct_blob(&blob,
337                                                sd,
338                                                sd,
339                                                (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
340                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341                         DEBUG(2, ("dcerpc_winreg_query_sd: Failed to marshall "
342                                   "security descriptor\n"));
343                         return NT_STATUS_NO_MEMORY;
344                 }
345
346                 *data = sd;
347         }
348
349         return status;
350 }
351
352 NTSTATUS dcerpc_winreg_set_dword(TALLOC_CTX *mem_ctx,
353                                  struct dcerpc_binding_handle *h,
354                                  struct policy_handle *key_handle,
355                                  const char *value,
356                                  uint32_t data,
357                                  WERROR *pwerr)
358 {
359         struct winreg_String wvalue;
360         DATA_BLOB blob;
361         NTSTATUS status;
362
363         ZERO_STRUCT(wvalue);
364         wvalue.name = value;
365         blob = data_blob_talloc_zero(mem_ctx, 4);
366         SIVAL(blob.data, 0, data);
367
368         status = dcerpc_winreg_SetValue(h,
369                                         mem_ctx,
370                                         key_handle,
371                                         wvalue,
372                                         REG_DWORD,
373                                         blob.data,
374                                         blob.length,
375                                         pwerr);
376
377         return status;
378 }
379
380 NTSTATUS dcerpc_winreg_set_sz(TALLOC_CTX *mem_ctx,
381                               struct dcerpc_binding_handle *h,
382                               struct policy_handle *key_handle,
383                               const char *value,
384                               const char *data,
385                               WERROR *pwerr)
386 {
387         struct winreg_String wvalue = { 0, };
388         DATA_BLOB blob;
389         NTSTATUS status;
390
391         wvalue.name = value;
392         if (data == NULL) {
393                 blob = data_blob_string_const("");
394         } else {
395                 if (!push_reg_sz(mem_ctx, &blob, data)) {
396                         DEBUG(2, ("dcerpc_winreg_set_sz: Could not marshall "
397                                   "string %s for %s\n",
398                                   data, wvalue.name));
399                         return NT_STATUS_NO_MEMORY;
400                 }
401         }
402
403         status = dcerpc_winreg_SetValue(h,
404                                         mem_ctx,
405                                         key_handle,
406                                         wvalue,
407                                         REG_SZ,
408                                         blob.data,
409                                         blob.length,
410                                         pwerr);
411
412         return status;
413 }
414
415 NTSTATUS dcerpc_winreg_set_expand_sz(TALLOC_CTX *mem_ctx,
416                                      struct dcerpc_binding_handle *h,
417                                      struct policy_handle *key_handle,
418                                      const char *value,
419                                      const char *data,
420                                      WERROR *pwerr)
421 {
422         struct winreg_String wvalue = { 0, };
423         DATA_BLOB blob;
424         NTSTATUS status;
425
426         wvalue.name = value;
427         if (data == NULL) {
428                 blob = data_blob_string_const("");
429         } else {
430                 if (!push_reg_sz(mem_ctx, &blob, data)) {
431                         DEBUG(2, ("dcerpc_winreg_set_expand_sz: Could not marshall "
432                                   "string %s for %s\n",
433                                   data, wvalue.name));
434                         return NT_STATUS_NO_MEMORY;
435                 }
436         }
437
438         status = dcerpc_winreg_SetValue(h,
439                                         mem_ctx,
440                                         key_handle,
441                                         wvalue,
442                                         REG_EXPAND_SZ,
443                                         blob.data,
444                                         blob.length,
445                                         pwerr);
446
447         return status;
448 }
449
450 NTSTATUS dcerpc_winreg_set_multi_sz(TALLOC_CTX *mem_ctx,
451                                     struct dcerpc_binding_handle *h,
452                                     struct policy_handle *key_handle,
453                                     const char *value,
454                                     const char **data,
455                                     WERROR *pwerr)
456 {
457         struct winreg_String wvalue = { 0, };
458         DATA_BLOB blob;
459         NTSTATUS status;
460
461         wvalue.name = value;
462         if (!push_reg_multi_sz(mem_ctx, &blob, data)) {
463                 DEBUG(2, ("dcerpc_winreg_set_multi_sz: Could not marshall "
464                           "string multi sz for %s\n",
465                           wvalue.name));
466                 return NT_STATUS_NO_MEMORY;
467         }
468
469         status = dcerpc_winreg_SetValue(h,
470                                         mem_ctx,
471                                         key_handle,
472                                         wvalue,
473                                         REG_MULTI_SZ,
474                                         blob.data,
475                                         blob.length,
476                                         pwerr);
477
478         return status;
479 }
480
481 NTSTATUS dcerpc_winreg_set_binary(TALLOC_CTX *mem_ctx,
482                                   struct dcerpc_binding_handle *h,
483                                   struct policy_handle *key_handle,
484                                   const char *value,
485                                   DATA_BLOB *data,
486                                   WERROR *pwerr)
487 {
488         struct winreg_String wvalue = { 0, };
489         NTSTATUS status;
490
491         wvalue.name = value;
492
493         status = dcerpc_winreg_SetValue(h,
494                                         mem_ctx,
495                                         key_handle,
496                                         wvalue,
497                                         REG_BINARY,
498                                         data->data,
499                                         data->length,
500                                         pwerr);
501
502         return status;
503 }
504
505 NTSTATUS dcerpc_winreg_set_sd(TALLOC_CTX *mem_ctx,
506                               struct dcerpc_binding_handle *h,
507                               struct policy_handle *key_handle,
508                               const char *value,
509                               const struct security_descriptor *data,
510                               WERROR *pwerr)
511 {
512         enum ndr_err_code ndr_err;
513         DATA_BLOB blob;
514
515         ndr_err = ndr_push_struct_blob(&blob,
516                                        mem_ctx,
517                                        data,
518                                        (ndr_push_flags_fn_t) ndr_push_security_descriptor);
519         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
520                 DEBUG(2, ("dcerpc_winreg_set_sd: Failed to marshall security "
521                           "descriptor\n"));
522                 return NT_STATUS_NO_MEMORY;
523         }
524
525         return dcerpc_winreg_set_binary(mem_ctx,
526                                         h,
527                                         key_handle,
528                                         value,
529                                         &blob,
530                                         pwerr);
531 }
532
533 NTSTATUS dcerpc_winreg_add_multi_sz(TALLOC_CTX *mem_ctx,
534                                     struct dcerpc_binding_handle *h,
535                                     struct policy_handle *key_handle,
536                                     const char *value,
537                                     const char *data,
538                                     WERROR *pwerr)
539 {
540         const char **a = NULL;
541         const char **p;
542         uint32_t i;
543         NTSTATUS status;
544
545         status = dcerpc_winreg_query_multi_sz(mem_ctx,
546                                               h,
547                                               key_handle,
548                                               value,
549                                               &a,
550                                               pwerr);
551
552         /* count the elements */
553         for (p = a, i = 0; p && *p; p++, i++);
554
555         p = talloc_realloc(mem_ctx, a, const char *, i + 2);
556         if (p == NULL) {
557                 return NT_STATUS_NO_MEMORY;
558         }
559
560         p[i] = data;
561         p[i + 1] = NULL;
562
563         status = dcerpc_winreg_set_multi_sz(mem_ctx,
564                                             h,
565                                             key_handle,
566                                             value,
567                                             p,
568                                             pwerr);
569
570         return status;
571 }
572
573 NTSTATUS dcerpc_winreg_enum_keys(TALLOC_CTX *mem_ctx,
574                                  struct dcerpc_binding_handle *h,
575                                  struct policy_handle *key_hnd,
576                                  uint32_t *pnum_subkeys,
577                                  const char ***psubkeys,
578                                  WERROR *pwerr)
579 {
580         const char **subkeys;
581         uint32_t num_subkeys, max_subkeylen, max_classlen;
582         uint32_t num_values, max_valnamelen, max_valbufsize;
583         uint32_t i;
584         NTTIME last_changed_time;
585         uint32_t secdescsize;
586         struct winreg_String classname;
587         NTSTATUS status;
588         TALLOC_CTX *tmp_ctx;
589
590         tmp_ctx = talloc_stackframe();
591         if (tmp_ctx == NULL) {
592                 return NT_STATUS_NO_MEMORY;
593         }
594
595         ZERO_STRUCT(classname);
596
597         status = dcerpc_winreg_QueryInfoKey(h,
598                                             tmp_ctx,
599                                             key_hnd,
600                                             &classname,
601                                             &num_subkeys,
602                                             &max_subkeylen,
603                                             &max_classlen,
604                                             &num_values,
605                                             &max_valnamelen,
606                                             &max_valbufsize,
607                                             &secdescsize,
608                                             &last_changed_time,
609                                             pwerr);
610         if (!NT_STATUS_IS_OK(status)) {
611                 goto error;
612         }
613         if (!W_ERROR_IS_OK(*pwerr)) {
614                 goto error;
615         }
616
617         subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
618         if (subkeys == NULL) {
619                 status = NT_STATUS_NO_MEMORY;
620                 goto error;
621         }
622
623         if (num_subkeys == 0) {
624                 subkeys[0] = talloc_strdup(subkeys, "");
625                 if (subkeys[0] == NULL) {
626                         status = NT_STATUS_NO_MEMORY;
627                         goto error;
628                 }
629                 *pnum_subkeys = 0;
630                 if (psubkeys) {
631                         *psubkeys = talloc_move(mem_ctx, &subkeys);
632                 }
633
634                 TALLOC_FREE(tmp_ctx);
635                 return NT_STATUS_OK;
636         }
637
638         for (i = 0; i < num_subkeys; i++) {
639                 char c = '\0';
640                 char n = '\0';
641                 char *name = NULL;
642                 struct winreg_StringBuf class_buf;
643                 struct winreg_StringBuf name_buf;
644                 NTTIME modtime;
645
646                 class_buf.name = &c;
647                 class_buf.size = max_classlen + 2;
648                 class_buf.length = 0;
649
650                 name_buf.name = &n;
651                 name_buf.size = max_subkeylen + 2;
652                 name_buf.length = 0;
653
654                 ZERO_STRUCT(modtime);
655
656                 status = dcerpc_winreg_EnumKey(h,
657                                                tmp_ctx,
658                                                key_hnd,
659                                                i,
660                                                &name_buf,
661                                                &class_buf,
662                                                &modtime,
663                                                pwerr);
664                 if (!NT_STATUS_IS_OK(status)) {
665                         DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
666                                   nt_errstr(status)));
667                         goto error;
668                 }
669
670                 if (W_ERROR_EQUAL(*pwerr, WERR_NO_MORE_ITEMS)) {
671                         *pwerr = WERR_OK;
672                         break;
673                 }
674                 if (!W_ERROR_IS_OK(*pwerr)) {
675                         DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
676                                   win_errstr(*pwerr)));
677                         goto error;
678                 }
679
680                 if (name_buf.name == NULL) {
681                         *pwerr = WERR_INVALID_PARAMETER;
682                         goto error;
683                 }
684
685                 name = talloc_strdup(subkeys, name_buf.name);
686                 if (name == NULL) {
687                         status = NT_STATUS_NO_MEMORY;
688                         goto error;
689                 }
690
691                 subkeys[i] = name;
692         }
693
694         *pnum_subkeys = num_subkeys;
695         if (psubkeys) {
696                 *psubkeys = talloc_move(mem_ctx, &subkeys);
697         }
698
699  error:
700         TALLOC_FREE(tmp_ctx);
701
702         return status;
703 }
704
705 NTSTATUS dcerpc_winreg_enumvals(TALLOC_CTX *mem_ctx,
706                                         struct dcerpc_binding_handle *h,
707                                         struct policy_handle *key_hnd,
708                                         uint32_t *pnum_values,
709                                         const char ***pnames,
710                                         enum winreg_Type **_type,
711                                         DATA_BLOB **pdata,
712                                         WERROR *pwerr)
713 {
714         TALLOC_CTX *tmp_ctx;
715         uint32_t num_subkeys = 0, max_subkeylen = 0, max_classlen = 0;
716         uint32_t num_values = 0, max_valnamelen = 0, max_valbufsize = 0;
717         uint32_t secdescsize = 0;
718         uint32_t i;
719         NTTIME last_changed_time = 0;
720         struct winreg_String classname;
721
722         const char **enum_names = NULL;
723         enum winreg_Type *enum_types = NULL;
724         DATA_BLOB *enum_data_blobs = NULL;
725
726
727         WERROR result = WERR_OK;
728         NTSTATUS status = NT_STATUS_OK;
729
730         tmp_ctx = talloc_stackframe();
731         if (tmp_ctx == NULL) {
732
733                 status = NT_STATUS_NO_MEMORY;
734                 *pwerr = ntstatus_to_werror(status);
735                 return status;
736         }
737
738         ZERO_STRUCT(classname);
739
740         status = dcerpc_winreg_QueryInfoKey(h,
741                                             tmp_ctx,
742                                             key_hnd,
743                                             &classname,
744                                             &num_subkeys,
745                                             &max_subkeylen,
746                                             &max_classlen,
747                                             &num_values,
748                                             &max_valnamelen,
749                                             &max_valbufsize,
750                                             &secdescsize,
751                                             &last_changed_time,
752                                             &result);
753         if (!NT_STATUS_IS_OK(status)) {
754                 DEBUG(0, ("dcerpc_winreg_enumvals: Could not query info: %s\n",
755                           nt_errstr(status)));
756                 goto error;
757         }
758         if (!W_ERROR_IS_OK(result)) {
759                 DEBUG(0, ("dcerpc_winreg_enumvals: Could not query info: %s\n",
760                           win_errstr(result)));
761                 *pwerr = result;
762                 goto error;
763         }
764
765         if (num_values == 0) {
766                 *pnum_values = 0;
767                 TALLOC_FREE(tmp_ctx);
768                 *pwerr = WERR_OK;
769                 return status;
770         }
771
772         enum_names = talloc_zero_array(tmp_ctx, const char *, num_values);
773
774         if (enum_names == NULL) {
775                 *pwerr = WERR_NOMEM;
776                 goto error;
777         }
778
779         enum_types = talloc_zero_array(tmp_ctx, enum winreg_Type, num_values);
780
781         if (enum_types == NULL) {
782                 *pwerr = WERR_NOMEM;
783                 goto error;
784         }
785
786         enum_data_blobs = talloc_zero_array(tmp_ctx, DATA_BLOB, num_values);
787
788         if (enum_data_blobs == NULL) {
789                 *pwerr = WERR_NOMEM;
790                 goto error;
791         }
792
793         for (i = 0; i < num_values; i++) {
794                 const char *name;
795                 struct winreg_ValNameBuf name_buf;
796                 enum winreg_Type type = REG_NONE;
797                 uint8_t *data;
798                 uint32_t data_size;
799                 uint32_t length;
800                 char n = '\0';
801
802
803                 name_buf.name = &n;
804                 name_buf.size = max_valnamelen + 2;
805                 name_buf.length = 0;
806
807                 data_size = max_valbufsize;
808                 data = NULL;
809                 if (data_size) {
810                         data = (uint8_t *) TALLOC(tmp_ctx, data_size);
811                 }
812                 length = 0;
813
814                 status = dcerpc_winreg_EnumValue(h,
815                                                  tmp_ctx,
816                                                  key_hnd,
817                                                  i,
818                                                  &name_buf,
819                                                  &type,
820                                                  data,
821                                                  data_size ? &data_size : NULL,
822                                                  &length,
823                                                  &result);
824                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
825                         result = WERR_OK;
826                         status = NT_STATUS_OK;
827                         break;
828                 }
829
830                 if (!NT_STATUS_IS_OK(status)) {
831                         DEBUG(0, ("dcerpc_winreg_enumvals: Could not enumerate values: %s\n",
832                                   nt_errstr(status)));
833                         goto error;
834                 }
835                 if (!W_ERROR_IS_OK(result)) {
836                         DEBUG(0, ("dcerpc_winreg_enumvals: Could not enumerate values: %s\n",
837                                   win_errstr(result)));
838                         *pwerr = result;
839                         goto error;
840                 }
841
842                 if (name_buf.name == NULL) {
843                         result = WERR_INVALID_PARAMETER;
844                         *pwerr = result;
845                         goto error;
846                 }
847
848                 name = talloc_strdup(enum_names, name_buf.name);
849                 if (name == NULL) {
850                         result = WERR_NOMEM;
851                         *pwerr = result;
852                         goto error;
853                 }
854         /* place name, type and datablob in the enum return params */
855
856                 enum_data_blobs[i] = data_blob_talloc(enum_data_blobs, data, length);
857                 enum_names[i] = name;
858                 enum_types[i] = type;
859
860         }
861         /* move to the main mem context */
862         *pnum_values = num_values;
863         if (pnames) {
864                 *pnames = talloc_move(mem_ctx, &enum_names);
865         }
866         /* can this fail in any way? */
867         if (_type) {
868                 *_type = talloc_move(mem_ctx, &enum_types);
869         }
870
871         if (pdata){
872                 *pdata = talloc_move(mem_ctx, &enum_data_blobs);
873         }
874
875
876         result = WERR_OK;
877
878  error:
879         TALLOC_FREE(tmp_ctx);
880         *pwerr = result;
881
882         return status;
883 }
884
885 NTSTATUS dcerpc_winreg_delete_subkeys_recursive(TALLOC_CTX *mem_ctx,
886                                                 struct dcerpc_binding_handle *h,
887                                                 struct policy_handle *hive_handle,
888                                                 uint32_t access_mask,
889                                                 const char *key,
890                                                 WERROR *pwerr)
891 {
892         const char **subkeys = NULL;
893         uint32_t num_subkeys = 0;
894         struct policy_handle key_hnd;
895         struct winreg_String wkey = { 0, };
896         WERROR result = WERR_OK;
897         NTSTATUS status = NT_STATUS_OK;
898         uint32_t i;
899
900         ZERO_STRUCT(key_hnd);
901         wkey.name = key;
902
903         DEBUG(2, ("dcerpc_winreg_delete_subkeys_recursive: delete key %s\n", key));
904         /* open the key */
905         status = dcerpc_winreg_OpenKey(h,
906                                        mem_ctx,
907                                        hive_handle,
908                                        wkey,
909                                        0,
910                                        access_mask,
911                                        &key_hnd,
912                                        &result);
913         if (!NT_STATUS_IS_OK(status)) {
914                 DEBUG(0, ("dcerpc_winreg_delete_subkeys_recursive: Could not open key %s: %s\n",
915                           wkey.name, nt_errstr(status)));
916                 goto done;
917         }
918         if (!W_ERROR_IS_OK(result)) {
919                 DEBUG(0, ("dcerpc_winreg_delete_subkeys_recursive: Could not open key %s: %s\n",
920                           wkey.name, win_errstr(result)));
921                 *pwerr = result;
922                 goto done;
923         }
924
925         status = dcerpc_winreg_enum_keys(mem_ctx,
926                                          h,
927                                          &key_hnd,
928                                          &num_subkeys,
929                                          &subkeys,
930                                          &result);
931         if (!NT_STATUS_IS_OK(status)) {
932                 goto done;
933         }
934         if (!W_ERROR_IS_OK(result)) {
935                 goto done;
936         }
937
938         for (i = 0; i < num_subkeys; i++) {
939                 /* create key + subkey */
940                 char *subkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkeys[i]);
941                 if (subkey == NULL) {
942                         goto done;
943                 }
944
945                 DEBUG(2, ("dcerpc_winreg_delete_subkeys_recursive: delete subkey %s\n", subkey));
946                 status = dcerpc_winreg_delete_subkeys_recursive(mem_ctx,
947                                                                 h,
948                                                                 hive_handle,
949                                                                 access_mask,
950                                                                 subkey,
951                                                                 &result);
952                 if (!W_ERROR_IS_OK(result)) {
953                         goto done;
954                 }
955         }
956
957         if (is_valid_policy_hnd(&key_hnd)) {
958                 WERROR ignore;
959                 dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &ignore);
960         }
961
962         wkey.name = key;
963
964         status = dcerpc_winreg_DeleteKey(h,
965                                          mem_ctx,
966                                          hive_handle,
967                                          wkey,
968                                          &result);
969         if (!NT_STATUS_IS_OK(status)) {
970                 *pwerr = result;
971                 goto done;
972         }
973
974 done:
975         if (is_valid_policy_hnd(&key_hnd)) {
976                 WERROR ignore;
977
978                 dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &ignore);
979         }
980
981         *pwerr = result;
982         return status;
983 }
984
985 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */