Correct "heirarchy" typos.
[vlendec/samba-autobuild/.git] / source3 / rpc_server / spoolss / srv_spoolss_util.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  SPOOLSS RPC Pipe server / winreg client routines
5  *
6  *  Copyright (c) 2010      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 "rpc_server/rpc_ncacn_np.h"
24 #include "../lib/tsocket/tsocket.h"
25 #include "../librpc/gen_ndr/ndr_spoolss.h"
26 #include "../librpc/gen_ndr/ndr_winreg.h"
27 #include "srv_spoolss_util.h"
28 #include "rpc_client/cli_winreg_spoolss.h"
29
30 WERROR winreg_printer_binding_handle(TALLOC_CTX *mem_ctx,
31                                      const struct auth_session_info *session_info,
32                                      struct messaging_context *msg_ctx,
33                                      struct dcerpc_binding_handle **winreg_binding_handle)
34 {
35         struct tsocket_address *local;
36         NTSTATUS status;
37         int rc;
38
39         rc = tsocket_address_inet_from_strings(mem_ctx,
40                                                "ip",
41                                                "127.0.0.1",
42                                                0,
43                                                &local);
44         if (rc < 0) {
45                 return WERR_NOT_ENOUGH_MEMORY;
46         }
47
48         status = rpcint_binding_handle(mem_ctx,
49                                        &ndr_table_winreg,
50                                        local,
51                                        session_info,
52                                        msg_ctx,
53                                        winreg_binding_handle);
54         talloc_free(local);
55         if (!NT_STATUS_IS_OK(status)) {
56                 DEBUG(0, ("winreg_printer_binding_handle: Could not connect to winreg pipe: %s\n",
57                           nt_errstr(status)));
58                 return ntstatus_to_werror(status);
59         }
60
61         return WERR_OK;
62 }
63
64 WERROR winreg_delete_printer_key_internal(TALLOC_CTX *mem_ctx,
65                                           const struct auth_session_info *session_info,
66                                           struct messaging_context *msg_ctx,
67                                           const char *printer,
68                                           const char *key)
69 {
70         WERROR result;
71         struct dcerpc_binding_handle *b;
72         TALLOC_CTX *tmp_ctx;
73
74         tmp_ctx = talloc_stackframe();
75         if (tmp_ctx == NULL) {
76                 return WERR_NOT_ENOUGH_MEMORY;
77         }
78
79         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
80         if (!W_ERROR_IS_OK(result)) {
81                 talloc_free(tmp_ctx);
82                 return result;
83         }
84
85         result = winreg_delete_printer_key(tmp_ctx,
86                                            b,
87                                            printer,
88                                            key);
89
90         talloc_free(tmp_ctx);
91         return result;
92 }
93
94 WERROR winreg_printer_update_changeid_internal(TALLOC_CTX *mem_ctx,
95                                                const struct auth_session_info *session_info,
96                                                struct messaging_context *msg_ctx,
97                                                const char *printer)
98 {
99         WERROR result;
100         struct dcerpc_binding_handle *b;
101         TALLOC_CTX *tmp_ctx;
102
103         tmp_ctx = talloc_stackframe();
104         if (tmp_ctx == NULL) {
105                 return WERR_NOT_ENOUGH_MEMORY;
106         }
107
108         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
109         if (!W_ERROR_IS_OK(result)) {
110                 talloc_free(tmp_ctx);
111                 return result;
112         }
113
114         result = winreg_printer_update_changeid(mem_ctx,
115                                                 b,
116                                                 printer);
117
118         talloc_free(tmp_ctx);
119         return result;
120 }
121
122 WERROR winreg_printer_get_changeid_internal(TALLOC_CTX *mem_ctx,
123                                             const struct auth_session_info *session_info,
124                                             struct messaging_context *msg_ctx,
125                                             const char *printer,
126                                             uint32_t *pchangeid)
127 {
128         WERROR result;
129         struct dcerpc_binding_handle *b;
130         TALLOC_CTX *tmp_ctx;
131
132         tmp_ctx = talloc_stackframe();
133         if (tmp_ctx == NULL) {
134                 return WERR_NOT_ENOUGH_MEMORY;
135         }
136
137         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
138         if (!W_ERROR_IS_OK(result)) {
139                 talloc_free(tmp_ctx);
140                 return result;
141         }
142
143         result = winreg_printer_get_changeid(mem_ctx,
144                                              b,
145                                              printer,
146                                              pchangeid);
147
148         talloc_free(tmp_ctx);
149         return result;
150 }
151
152 WERROR winreg_get_printer_internal(TALLOC_CTX *mem_ctx,
153                                    const struct auth_session_info *session_info,
154                                    struct messaging_context *msg_ctx,
155                                    const char *printer,
156                                    struct spoolss_PrinterInfo2 **pinfo2)
157 {
158         WERROR result;
159         struct dcerpc_binding_handle *b;
160         TALLOC_CTX *tmp_ctx;
161
162         tmp_ctx = talloc_stackframe();
163         if (tmp_ctx == NULL) {
164                 return WERR_NOT_ENOUGH_MEMORY;
165         }
166
167         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
168         if (!W_ERROR_IS_OK(result)) {
169                 talloc_free(tmp_ctx);
170                 return result;
171         }
172
173         result = winreg_get_printer(mem_ctx,
174                                     b,
175                                     printer,
176                                     pinfo2);
177
178         talloc_free(tmp_ctx);
179         return result;
180 }
181
182 WERROR winreg_create_printer_internal(TALLOC_CTX *mem_ctx,
183                                       const struct auth_session_info *session_info,
184                                       struct messaging_context *msg_ctx,
185                                       const char *sharename)
186 {
187         WERROR result;
188         struct dcerpc_binding_handle *b;
189         TALLOC_CTX *tmp_ctx;
190
191         tmp_ctx = talloc_stackframe();
192         if (tmp_ctx == NULL) {
193                 return WERR_NOT_ENOUGH_MEMORY;
194         }
195
196         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
197         if (!W_ERROR_IS_OK(result)) {
198                 talloc_free(tmp_ctx);
199                 return result;
200         }
201
202         result = winreg_create_printer(mem_ctx,
203                                        b,
204                                        sharename);
205
206         talloc_free(tmp_ctx);
207         return result;
208 }
209
210 WERROR winreg_update_printer_internal(TALLOC_CTX *mem_ctx,
211                                       const struct auth_session_info *session_info,
212                                       struct messaging_context *msg_ctx,
213                                       const char *sharename,
214                                       uint32_t info2_mask,
215                                       struct spoolss_SetPrinterInfo2 *info2,
216                                       struct spoolss_DeviceMode *devmode,
217                                       struct security_descriptor *secdesc)
218 {
219         WERROR result;
220         struct dcerpc_binding_handle *b;
221         TALLOC_CTX *tmp_ctx;
222
223         tmp_ctx = talloc_stackframe();
224         if (tmp_ctx == NULL) {
225                 return WERR_NOT_ENOUGH_MEMORY;
226         }
227
228         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
229         if (!W_ERROR_IS_OK(result)) {
230                 talloc_free(tmp_ctx);
231                 return result;
232         }
233
234         result = winreg_update_printer(mem_ctx,
235                                        b,
236                                        sharename,
237                                        info2_mask,
238                                        info2,
239                                        devmode,
240                                        secdesc);
241
242         talloc_free(tmp_ctx);
243         return result;
244 }
245
246 WERROR winreg_set_printer_dataex_internal(TALLOC_CTX *mem_ctx,
247                                           const struct auth_session_info *session_info,
248                                           struct messaging_context *msg_ctx,
249                                           const char *printer,
250                                           const char *key,
251                                           const char *value,
252                                           enum winreg_Type type,
253                                           uint8_t *data,
254                                           uint32_t data_size)
255 {
256         WERROR result;
257         struct dcerpc_binding_handle *b;
258         TALLOC_CTX *tmp_ctx;
259
260         tmp_ctx = talloc_stackframe();
261         if (tmp_ctx == NULL) {
262                 return WERR_NOT_ENOUGH_MEMORY;
263         }
264
265         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
266         if (!W_ERROR_IS_OK(result)) {
267                 talloc_free(tmp_ctx);
268                 return result;
269         }
270
271         result = winreg_set_printer_dataex(mem_ctx,
272                                            b,
273                                            printer,
274                                            key,
275                                            value,
276                                            type,
277                                            data,
278                                            data_size);
279
280         talloc_free(tmp_ctx);
281         return result;
282 }
283
284 WERROR winreg_enum_printer_dataex_internal(TALLOC_CTX *mem_ctx,
285                                            const struct auth_session_info *session_info,
286                                            struct messaging_context *msg_ctx,
287                                            const char *printer,
288                                            const char *key,
289                                            uint32_t *pnum_values,
290                                            struct spoolss_PrinterEnumValues **penum_values)
291 {
292         WERROR result;
293         struct dcerpc_binding_handle *b;
294         TALLOC_CTX *tmp_ctx;
295
296         tmp_ctx = talloc_stackframe();
297         if (tmp_ctx == NULL) {
298                 return WERR_NOT_ENOUGH_MEMORY;
299         }
300
301         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
302         if (!W_ERROR_IS_OK(result)) {
303                 talloc_free(tmp_ctx);
304                 return result;
305         }
306
307         result = winreg_enum_printer_dataex(mem_ctx,
308                                             b,
309                                             printer,
310                                             key,
311                                             pnum_values,
312                                             penum_values);
313
314         talloc_free(tmp_ctx);
315         return result;
316 }
317
318 WERROR winreg_get_printer_dataex_internal(TALLOC_CTX *mem_ctx,
319                                           const struct auth_session_info *session_info,
320                                           struct messaging_context *msg_ctx,
321                                           const char *printer,
322                                           const char *key,
323                                           const char *value,
324                                           enum winreg_Type *type,
325                                           uint8_t **data,
326                                           uint32_t *data_size)
327 {
328         WERROR result;
329         struct dcerpc_binding_handle *b;
330         TALLOC_CTX *tmp_ctx;
331
332         tmp_ctx = talloc_stackframe();
333         if (tmp_ctx == NULL) {
334                 return WERR_NOT_ENOUGH_MEMORY;
335         }
336
337         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
338         if (!W_ERROR_IS_OK(result)) {
339                 talloc_free(tmp_ctx);
340                 return result;
341         }
342
343         result = winreg_get_printer_dataex(mem_ctx,
344                                            b,
345                                            printer,
346                                            key,
347                                            value,
348                                            type,
349                                            data,
350                                            data_size);
351
352         talloc_free(tmp_ctx);
353         return result;
354 }
355
356 WERROR winreg_delete_printer_dataex_internal(TALLOC_CTX *mem_ctx,
357                                              const struct auth_session_info *session_info,
358                                              struct messaging_context *msg_ctx,
359                                              const char *printer,
360                                              const char *key,
361                                              const char *value)
362 {
363         WERROR result;
364         struct dcerpc_binding_handle *b;
365         TALLOC_CTX *tmp_ctx;
366
367         tmp_ctx = talloc_stackframe();
368         if (tmp_ctx == NULL) {
369                 return WERR_NOT_ENOUGH_MEMORY;
370         }
371
372         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
373         if (!W_ERROR_IS_OK(result)) {
374                 talloc_free(tmp_ctx);
375                 return result;
376         }
377
378         result = winreg_delete_printer_dataex(mem_ctx,
379                                               b,
380                                               printer,
381                                               key,
382                                               value);
383
384         talloc_free(tmp_ctx);
385         return result;
386 }
387
388 WERROR winreg_get_driver_internal(TALLOC_CTX *mem_ctx,
389                                   const struct auth_session_info *session_info,
390                                   struct messaging_context *msg_ctx,
391                                   const char *architecture,
392                                   const char *driver_name,
393                                   uint32_t driver_version,
394                                   struct spoolss_DriverInfo8 **_info8)
395 {
396         WERROR result;
397         struct dcerpc_binding_handle *b;
398         TALLOC_CTX *tmp_ctx;
399
400         tmp_ctx = talloc_stackframe();
401         if (tmp_ctx == NULL) {
402                 return WERR_NOT_ENOUGH_MEMORY;
403         }
404
405         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
406         if (!W_ERROR_IS_OK(result)) {
407                 talloc_free(tmp_ctx);
408                 return result;
409         }
410
411         result = winreg_get_driver(mem_ctx,
412                                    b,
413                                    architecture,
414                                    driver_name,
415                                    driver_version,
416                                    _info8);
417
418         talloc_free(tmp_ctx);
419         return result;
420 }
421
422 WERROR winreg_get_driver_list_internal(TALLOC_CTX *mem_ctx,
423                                        const struct auth_session_info *session_info,
424                                        struct messaging_context *msg_ctx,
425                                        const char *architecture,
426                                        uint32_t version,
427                                        uint32_t *num_drivers,
428                                        const char ***drivers_p)
429 {
430         WERROR result;
431         struct dcerpc_binding_handle *b;
432         TALLOC_CTX *tmp_ctx;
433
434         tmp_ctx = talloc_stackframe();
435         if (tmp_ctx == NULL) {
436                 return WERR_NOT_ENOUGH_MEMORY;
437         }
438
439         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
440         if (!W_ERROR_IS_OK(result)) {
441                 talloc_free(tmp_ctx);
442                 return result;
443         }
444
445         result = winreg_get_driver_list(mem_ctx,
446                                         b,
447                                         architecture,
448                                         version,
449                                         num_drivers,
450                                         drivers_p);
451
452         talloc_free(tmp_ctx);
453         return result;
454 }
455
456 WERROR winreg_del_driver_internal(TALLOC_CTX *mem_ctx,
457                                   const struct auth_session_info *session_info,
458                                   struct messaging_context *msg_ctx,
459                                   struct spoolss_DriverInfo8 *info8,
460                                   uint32_t version)
461 {
462         WERROR result;
463         struct dcerpc_binding_handle *b;
464         TALLOC_CTX *tmp_ctx;
465
466         tmp_ctx = talloc_stackframe();
467         if (tmp_ctx == NULL) {
468                 return WERR_NOT_ENOUGH_MEMORY;
469         }
470
471         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
472         if (!W_ERROR_IS_OK(result)) {
473                 talloc_free(tmp_ctx);
474                 return result;
475         }
476
477         result = winreg_del_driver(mem_ctx,
478                                    b,
479                                    info8,
480                                    version);
481
482         talloc_free(tmp_ctx);
483         return result;
484 }
485
486 WERROR winreg_add_driver_internal(TALLOC_CTX *mem_ctx,
487                                   const struct auth_session_info *session_info,
488                                   struct messaging_context *msg_ctx,
489                                   struct spoolss_AddDriverInfoCtr *r,
490                                   const char **driver_name,
491                                   uint32_t *driver_version)
492 {
493         WERROR result;
494         struct dcerpc_binding_handle *b;
495         TALLOC_CTX *tmp_ctx;
496
497         tmp_ctx = talloc_stackframe();
498         if (tmp_ctx == NULL) {
499                 return WERR_NOT_ENOUGH_MEMORY;
500         }
501
502         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
503         if (!W_ERROR_IS_OK(result)) {
504                 talloc_free(tmp_ctx);
505                 return result;
506         }
507
508         result = winreg_add_driver(mem_ctx,
509                                    b,
510                                    r,
511                                    driver_name,
512                                    driver_version);
513
514         talloc_free(tmp_ctx);
515         return result;
516 }
517
518 WERROR winreg_get_printer_secdesc_internal(TALLOC_CTX *mem_ctx,
519                                            const struct auth_session_info *session_info,
520                                            struct messaging_context *msg_ctx,
521                                            const char *sharename,
522                                            struct spoolss_security_descriptor **psecdesc)
523 {
524         WERROR result;
525         struct dcerpc_binding_handle *b;
526         TALLOC_CTX *tmp_ctx;
527
528         tmp_ctx = talloc_stackframe();
529         if (tmp_ctx == NULL) {
530                 return WERR_NOT_ENOUGH_MEMORY;
531         }
532
533         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
534         if (!W_ERROR_IS_OK(result)) {
535                 talloc_free(tmp_ctx);
536                 return result;
537         }
538
539         result = winreg_get_printer_secdesc(mem_ctx,
540                                             b,
541                                             sharename,
542                                             psecdesc);
543
544         talloc_free(tmp_ctx);
545         return result;
546 }
547
548 WERROR winreg_set_printer_secdesc_internal(TALLOC_CTX *mem_ctx,
549                                            const struct auth_session_info *session_info,
550                                            struct messaging_context *msg_ctx,
551                                            const char *sharename,
552                                            const struct spoolss_security_descriptor *secdesc)
553 {
554         WERROR result;
555         struct dcerpc_binding_handle *b;
556         TALLOC_CTX *tmp_ctx;
557
558         tmp_ctx = talloc_stackframe();
559         if (tmp_ctx == NULL) {
560                 return WERR_NOT_ENOUGH_MEMORY;
561         }
562
563         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
564         if (!W_ERROR_IS_OK(result)) {
565                 talloc_free(tmp_ctx);
566                 return result;
567         }
568
569         result = winreg_set_printer_secdesc(mem_ctx,
570                                             b,
571                                             sharename,
572                                             secdesc);
573
574         talloc_free(tmp_ctx);
575         return result;
576 }
577
578 WERROR winreg_printer_enumforms1_internal(TALLOC_CTX *mem_ctx,
579                                           const struct auth_session_info *session_info,
580                                           struct messaging_context *msg_ctx,
581                                           uint32_t *pnum_info,
582                                           union spoolss_FormInfo **pinfo)
583 {
584         WERROR result;
585         struct dcerpc_binding_handle *b;
586         TALLOC_CTX *tmp_ctx;
587
588         tmp_ctx = talloc_stackframe();
589         if (tmp_ctx == NULL) {
590                 return WERR_NOT_ENOUGH_MEMORY;
591         }
592
593         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
594         if (!W_ERROR_IS_OK(result)) {
595                 talloc_free(tmp_ctx);
596                 return result;
597         }
598
599         result = winreg_printer_enumforms1(mem_ctx,
600                                            b,
601                                            pnum_info,
602                                            pinfo);
603
604         talloc_free(tmp_ctx);
605         return result;
606 }
607
608 WERROR winreg_printer_getform1_internal(TALLOC_CTX *mem_ctx,
609                                         const struct auth_session_info *session_info,
610                                         struct messaging_context *msg_ctx,
611                                         const char *form_name,
612                                         struct spoolss_FormInfo1 *r)
613 {
614         WERROR result;
615         struct dcerpc_binding_handle *b;
616         TALLOC_CTX *tmp_ctx;
617
618         tmp_ctx = talloc_stackframe();
619         if (tmp_ctx == NULL) {
620                 return WERR_NOT_ENOUGH_MEMORY;
621         }
622
623         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
624         if (!W_ERROR_IS_OK(result)) {
625                 talloc_free(tmp_ctx);
626                 return result;
627         }
628
629         result = winreg_printer_getform1(mem_ctx,
630                                          b,
631                                          form_name,
632                                          r);
633
634         talloc_free(tmp_ctx);
635         return result;
636 }
637
638 WERROR winreg_printer_addform1_internal(TALLOC_CTX *mem_ctx,
639                                         const struct auth_session_info *session_info,
640                                         struct messaging_context *msg_ctx,
641                                         struct spoolss_AddFormInfo1 *form)
642 {
643         WERROR result;
644         struct dcerpc_binding_handle *b;
645         TALLOC_CTX *tmp_ctx;
646
647         tmp_ctx = talloc_stackframe();
648         if (tmp_ctx == NULL) {
649                 return WERR_NOT_ENOUGH_MEMORY;
650         }
651
652         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
653         if (!W_ERROR_IS_OK(result)) {
654                 talloc_free(tmp_ctx);
655                 return result;
656         }
657
658         result = winreg_printer_addform1(mem_ctx,
659                                          b,
660                                          form);
661
662         talloc_free(tmp_ctx);
663         return result;
664 }
665
666 WERROR winreg_printer_setform1_internal(TALLOC_CTX *mem_ctx,
667                                         const struct auth_session_info *session_info,
668                                         struct messaging_context *msg_ctx,
669                                         const char *form_name,
670                                         struct spoolss_AddFormInfo1 *form)
671 {
672         WERROR result;
673         struct dcerpc_binding_handle *b;
674         TALLOC_CTX *tmp_ctx;
675
676         tmp_ctx = talloc_stackframe();
677         if (tmp_ctx == NULL) {
678                 return WERR_NOT_ENOUGH_MEMORY;
679         }
680
681         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
682         if (!W_ERROR_IS_OK(result)) {
683                 talloc_free(tmp_ctx);
684                 return result;
685         }
686
687         result = winreg_printer_setform1(mem_ctx,
688                                          b,
689                                          form_name,
690                                          form);
691
692         talloc_free(tmp_ctx);
693         return result;
694 }
695
696 WERROR winreg_printer_deleteform1_internal(TALLOC_CTX *mem_ctx,
697                                            const struct auth_session_info *session_info,
698                                            struct messaging_context *msg_ctx,
699                                            const char *form_name)
700 {
701         WERROR result;
702         struct dcerpc_binding_handle *b;
703         TALLOC_CTX *tmp_ctx;
704
705         tmp_ctx = talloc_stackframe();
706         if (tmp_ctx == NULL) {
707                 return WERR_NOT_ENOUGH_MEMORY;
708         }
709
710         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
711         if (!W_ERROR_IS_OK(result)) {
712                 talloc_free(tmp_ctx);
713                 return result;
714         }
715
716         result = winreg_printer_deleteform1(mem_ctx,
717                                             b,
718                                             form_name);
719
720         talloc_free(tmp_ctx);
721         return result;
722 }
723
724 WERROR winreg_enum_printer_key_internal(TALLOC_CTX *mem_ctx,
725                                         const struct auth_session_info *session_info,
726                                         struct messaging_context *msg_ctx,
727                                         const char *printer,
728                                         const char *key,
729                                         uint32_t *pnum_subkeys,
730                                         const char ***psubkeys)
731 {
732         WERROR result;
733         struct dcerpc_binding_handle *b;
734         TALLOC_CTX *tmp_ctx;
735
736         tmp_ctx = talloc_stackframe();
737         if (tmp_ctx == NULL) {
738                 return WERR_NOT_ENOUGH_MEMORY;
739         }
740
741         result = winreg_printer_binding_handle(tmp_ctx, session_info, msg_ctx, &b);
742         if (!W_ERROR_IS_OK(result)) {
743                 talloc_free(tmp_ctx);
744                 return result;
745         }
746
747         result = winreg_enum_printer_key(mem_ctx,
748                                          b,
749                                          printer,
750                                          key,
751                                          pnum_subkeys,
752                                          psubkeys);
753
754         talloc_free(tmp_ctx);
755         return result;
756 }