s3-spoolss: fixes for _spoolss_EnumPrinterKey client and server.
[vlendec/samba-autobuild/.git] / source3 / rpc_client / cli_spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Gerald Carter                2001-2005,
6    Copyright (C) Tim Potter                   2000-2002,
7    Copyright (C) Andrew Tridgell              1994-2000,
8    Copyright (C) Jean-Francois Micouleau      1999-2000.
9    Copyright (C) Jeremy Allison                         2005.
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "rpc_client.h"
27
28 /**********************************************************************
29  convencience wrapper around rpccli_spoolss_OpenPrinterEx
30 **********************************************************************/
31
32 WERROR rpccli_spoolss_openprinter_ex(struct rpc_pipe_client *cli,
33                                      TALLOC_CTX *mem_ctx,
34                                      const char *printername,
35                                      uint32_t access_desired,
36                                      struct policy_handle *handle)
37 {
38         NTSTATUS status;
39         WERROR werror;
40         struct spoolss_DevmodeContainer devmode_ctr;
41         union spoolss_UserLevel userlevel;
42         struct spoolss_UserLevel1 level1;
43
44         ZERO_STRUCT(devmode_ctr);
45
46         level1.size     = 28;
47         level1.client   = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
48         W_ERROR_HAVE_NO_MEMORY(level1.client);
49         level1.user     = cli->auth->user_name;
50         level1.build    = 1381;
51         level1.major    = 2;
52         level1.minor    = 0;
53         level1.processor = 0;
54
55         userlevel.level1 = &level1;
56
57         status = rpccli_spoolss_OpenPrinterEx(cli, mem_ctx,
58                                               printername,
59                                               NULL,
60                                               devmode_ctr,
61                                               access_desired,
62                                               1, /* level */
63                                               userlevel,
64                                               handle,
65                                               &werror);
66
67         if (!W_ERROR_IS_OK(werror)) {
68                 return werror;
69         }
70
71         if (!NT_STATUS_IS_OK(status)) {
72                 return ntstatus_to_werror(status);
73         }
74
75         return WERR_OK;
76 }
77
78 /**********************************************************************
79  convencience wrapper around rpccli_spoolss_GetPrinterDriver
80 **********************************************************************/
81
82 WERROR rpccli_spoolss_getprinterdriver(struct rpc_pipe_client *cli,
83                                        TALLOC_CTX *mem_ctx,
84                                        struct policy_handle *handle,
85                                        const char *architecture,
86                                        uint32_t level,
87                                        uint32_t offered,
88                                        union spoolss_DriverInfo *info)
89 {
90         NTSTATUS status;
91         WERROR werror;
92         uint32_t needed;
93         DATA_BLOB buffer;
94
95         if (offered > 0) {
96                 buffer = data_blob_talloc_zero(mem_ctx, offered);
97                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
98         }
99
100         status = rpccli_spoolss_GetPrinterDriver(cli, mem_ctx,
101                                                  handle,
102                                                  architecture,
103                                                  level,
104                                                  (offered > 0) ? &buffer : NULL,
105                                                  offered,
106                                                  info,
107                                                  &needed,
108                                                  &werror);
109         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
110                 offered = needed;
111                 buffer = data_blob_talloc_zero(mem_ctx, needed);
112                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
113
114                 status = rpccli_spoolss_GetPrinterDriver(cli, mem_ctx,
115                                                          handle,
116                                                          architecture,
117                                                          level,
118                                                          &buffer,
119                                                          offered,
120                                                          info,
121                                                          &needed,
122                                                          &werror);
123         }
124
125         return werror;
126 }
127
128 /**********************************************************************
129  convencience wrapper around rpccli_spoolss_GetPrinterDriver2
130 **********************************************************************/
131
132 WERROR rpccli_spoolss_getprinterdriver2(struct rpc_pipe_client *cli,
133                                         TALLOC_CTX *mem_ctx,
134                                         struct policy_handle *handle,
135                                         const char *architecture,
136                                         uint32_t level,
137                                         uint32_t offered,
138                                         uint32_t client_major_version,
139                                         uint32_t client_minor_version,
140                                         union spoolss_DriverInfo *info,
141                                         uint32_t *server_major_version,
142                                         uint32_t *server_minor_version)
143 {
144         NTSTATUS status;
145         WERROR werror;
146         uint32_t needed;
147         DATA_BLOB buffer;
148
149         if (offered > 0) {
150                 buffer = data_blob_talloc_zero(mem_ctx, offered);
151                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
152         }
153
154         status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
155                                                   handle,
156                                                   architecture,
157                                                   level,
158                                                   (offered > 0) ? &buffer : NULL,
159                                                   offered,
160                                                   client_major_version,
161                                                   client_minor_version,
162                                                   info,
163                                                   &needed,
164                                                   server_major_version,
165                                                   server_minor_version,
166                                                   &werror);
167         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
168                 offered = needed;
169                 buffer = data_blob_talloc_zero(mem_ctx, needed);
170                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
171
172                 status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
173                                                           handle,
174                                                           architecture,
175                                                           level,
176                                                           &buffer,
177                                                           offered,
178                                                           client_major_version,
179                                                           client_minor_version,
180                                                           info,
181                                                           &needed,
182                                                           server_major_version,
183                                                           server_minor_version,
184                                                           &werror);
185         }
186
187         return werror;
188 }
189
190 /**********************************************************************
191  convencience wrapper around rpccli_spoolss_AddPrinterEx
192 **********************************************************************/
193
194 WERROR rpccli_spoolss_addprinterex(struct rpc_pipe_client *cli,
195                                    TALLOC_CTX *mem_ctx,
196                                    struct spoolss_SetPrinterInfoCtr *info_ctr)
197 {
198         WERROR result;
199         NTSTATUS status;
200         struct spoolss_DevmodeContainer devmode_ctr;
201         struct sec_desc_buf secdesc_ctr;
202         struct spoolss_UserLevelCtr userlevel_ctr;
203         struct spoolss_UserLevel1 level1;
204         struct policy_handle handle;
205
206         ZERO_STRUCT(devmode_ctr);
207         ZERO_STRUCT(secdesc_ctr);
208
209         level1.size             = 28;
210         level1.build            = 1381;
211         level1.major            = 2;
212         level1.minor            = 0;
213         level1.processor        = 0;
214         level1.client           = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
215         W_ERROR_HAVE_NO_MEMORY(level1.client);
216         level1.user             = cli->auth->user_name;
217
218         userlevel_ctr.level = 1;
219         userlevel_ctr.user_info.level1 = &level1;
220
221         status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx,
222                                              cli->srv_name_slash,
223                                              info_ctr,
224                                              &devmode_ctr,
225                                              &secdesc_ctr,
226                                              &userlevel_ctr,
227                                              &handle,
228                                              &result);
229         return result;
230 }
231
232 /**********************************************************************
233  convencience wrapper around rpccli_spoolss_GetPrinter
234 **********************************************************************/
235
236 WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli,
237                                  TALLOC_CTX *mem_ctx,
238                                  struct policy_handle *handle,
239                                  uint32_t level,
240                                  uint32_t offered,
241                                  union spoolss_PrinterInfo *info)
242 {
243         NTSTATUS status;
244         WERROR werror;
245         DATA_BLOB buffer;
246         uint32_t needed;
247
248         if (offered > 0) {
249                 buffer = data_blob_talloc_zero(mem_ctx, offered);
250                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
251         }
252
253         status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
254                                            handle,
255                                            level,
256                                            (offered > 0) ? &buffer : NULL,
257                                            offered,
258                                            info,
259                                            &needed,
260                                            &werror);
261
262         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
263
264                 offered = needed;
265                 buffer = data_blob_talloc_zero(mem_ctx, offered);
266                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
267
268                 status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
269                                                    handle,
270                                                    level,
271                                                    &buffer,
272                                                    offered,
273                                                    info,
274                                                    &needed,
275                                                    &werror);
276         }
277
278         return werror;
279 }
280
281 /**********************************************************************
282  convencience wrapper around rpccli_spoolss_GetJob
283 **********************************************************************/
284
285 WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli,
286                              TALLOC_CTX *mem_ctx,
287                              struct policy_handle *handle,
288                              uint32_t job_id,
289                              uint32_t level,
290                              uint32_t offered,
291                              union spoolss_JobInfo *info)
292 {
293         NTSTATUS status;
294         WERROR werror;
295         uint32_t needed;
296         DATA_BLOB buffer;
297
298         if (offered > 0) {
299                 buffer = data_blob_talloc_zero(mem_ctx, offered);
300                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
301         }
302
303         status = rpccli_spoolss_GetJob(cli, mem_ctx,
304                                        handle,
305                                        job_id,
306                                        level,
307                                        (offered > 0) ? &buffer : NULL,
308                                        offered,
309                                        info,
310                                        &needed,
311                                        &werror);
312
313         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
314                 offered = needed;
315                 buffer = data_blob_talloc_zero(mem_ctx, needed);
316                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
317
318                 status = rpccli_spoolss_GetJob(cli, mem_ctx,
319                                                handle,
320                                                job_id,
321                                                level,
322                                                &buffer,
323                                                offered,
324                                                info,
325                                                &needed,
326                                                &werror);
327         }
328
329         return werror;
330 }
331
332 /**********************************************************************
333  convencience wrapper around rpccli_spoolss_EnumForms
334 **********************************************************************/
335
336 WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli,
337                                 TALLOC_CTX *mem_ctx,
338                                 struct policy_handle *handle,
339                                 uint32_t level,
340                                 uint32_t offered,
341                                 uint32_t *count,
342                                 union spoolss_FormInfo **info)
343 {
344         NTSTATUS status;
345         WERROR werror;
346         uint32_t needed;
347         DATA_BLOB buffer;
348
349         if (offered > 0) {
350                 buffer = data_blob_talloc_zero(mem_ctx, offered);
351                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
352         }
353
354         status = rpccli_spoolss_EnumForms(cli, mem_ctx,
355                                           handle,
356                                           level,
357                                           (offered > 0) ? &buffer : NULL,
358                                           offered,
359                                           count,
360                                           info,
361                                           &needed,
362                                           &werror);
363
364         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
365                 offered = needed;
366                 buffer = data_blob_talloc_zero(mem_ctx, needed);
367                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
368
369                 status = rpccli_spoolss_EnumForms(cli, mem_ctx,
370                                                   handle,
371                                                   level,
372                                                   (offered > 0) ? &buffer : NULL,
373                                                   offered,
374                                                   count,
375                                                   info,
376                                                   &needed,
377                                                   &werror);
378         }
379
380         return werror;
381 }
382
383 /**********************************************************************
384  convencience wrapper around rpccli_spoolss_EnumPrintProcessors
385 **********************************************************************/
386
387 WERROR rpccli_spoolss_enumprintprocessors(struct rpc_pipe_client *cli,
388                                           TALLOC_CTX *mem_ctx,
389                                           const char *servername,
390                                           const char *environment,
391                                           uint32_t level,
392                                           uint32_t offered,
393                                           uint32_t *count,
394                                           union spoolss_PrintProcessorInfo **info)
395 {
396         NTSTATUS status;
397         WERROR werror;
398         uint32_t needed;
399         DATA_BLOB buffer;
400
401         if (offered > 0) {
402                 buffer = data_blob_talloc_zero(mem_ctx, offered);
403                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
404         }
405
406         status = rpccli_spoolss_EnumPrintProcessors(cli, mem_ctx,
407                                                     servername,
408                                                     environment,
409                                                     level,
410                                                     (offered > 0) ? &buffer : NULL,
411                                                     offered,
412                                                     count,
413                                                     info,
414                                                     &needed,
415                                                     &werror);
416
417         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
418                 offered = needed;
419                 buffer = data_blob_talloc_zero(mem_ctx, needed);
420                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
421
422                 status = rpccli_spoolss_EnumPrintProcessors(cli, mem_ctx,
423                                                             servername,
424                                                             environment,
425                                                             level,
426                                                             (offered > 0) ? &buffer : NULL,
427                                                             offered,
428                                                             count,
429                                                             info,
430                                                             &needed,
431                                                             &werror);
432         }
433
434         return werror;
435 }
436
437 /**********************************************************************
438  convencience wrapper around rpccli_spoolss_EnumPrintProcDataTypes
439 **********************************************************************/
440
441 WERROR rpccli_spoolss_enumprintprocessordatatypes(struct rpc_pipe_client *cli,
442                                                   TALLOC_CTX *mem_ctx,
443                                                   const char *servername,
444                                                   const char *print_processor_name,
445                                                   uint32_t level,
446                                                   uint32_t offered,
447                                                   uint32_t *count,
448                                                   union spoolss_PrintProcDataTypesInfo **info)
449 {
450         NTSTATUS status;
451         WERROR werror;
452         uint32_t needed;
453         DATA_BLOB buffer;
454
455         if (offered > 0) {
456                 buffer = data_blob_talloc_zero(mem_ctx, offered);
457                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
458         }
459
460         status = rpccli_spoolss_EnumPrintProcDataTypes(cli, mem_ctx,
461                                                        servername,
462                                                        print_processor_name,
463                                                        level,
464                                                        (offered > 0) ? &buffer : NULL,
465                                                        offered,
466                                                        count,
467                                                        info,
468                                                        &needed,
469                                                        &werror);
470
471         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
472                 offered = needed;
473                 buffer = data_blob_talloc_zero(mem_ctx, needed);
474                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
475
476                 status = rpccli_spoolss_EnumPrintProcDataTypes(cli, mem_ctx,
477                                                                servername,
478                                                                print_processor_name,
479                                                                level,
480                                                                (offered > 0) ? &buffer : NULL,
481                                                                offered,
482                                                                count,
483                                                                info,
484                                                                &needed,
485                                                                &werror);
486         }
487
488         return werror;
489 }
490
491 /**********************************************************************
492  convencience wrapper around rpccli_spoolss_EnumPorts
493 **********************************************************************/
494
495 WERROR rpccli_spoolss_enumports(struct rpc_pipe_client *cli,
496                                 TALLOC_CTX *mem_ctx,
497                                 const char *servername,
498                                 uint32_t level,
499                                 uint32_t offered,
500                                 uint32_t *count,
501                                 union spoolss_PortInfo **info)
502 {
503         NTSTATUS status;
504         WERROR werror;
505         uint32_t needed;
506         DATA_BLOB buffer;
507
508         if (offered > 0) {
509                 buffer = data_blob_talloc_zero(mem_ctx, offered);
510                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
511         }
512
513         status = rpccli_spoolss_EnumPorts(cli, mem_ctx,
514                                           servername,
515                                           level,
516                                           (offered > 0) ? &buffer : NULL,
517                                           offered,
518                                           count,
519                                           info,
520                                           &needed,
521                                           &werror);
522
523         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
524                 offered = needed;
525                 buffer = data_blob_talloc_zero(mem_ctx, needed);
526                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
527
528                 status = rpccli_spoolss_EnumPorts(cli, mem_ctx,
529                                                   servername,
530                                                   level,
531                                                   (offered > 0) ? &buffer : NULL,
532                                                   offered,
533                                                   count,
534                                                   info,
535                                                   &needed,
536                                                   &werror);
537         }
538
539         return werror;
540 }
541
542 /**********************************************************************
543  convencience wrapper around rpccli_spoolss_EnumMonitors
544 **********************************************************************/
545
546 WERROR rpccli_spoolss_enummonitors(struct rpc_pipe_client *cli,
547                                    TALLOC_CTX *mem_ctx,
548                                    const char *servername,
549                                    uint32_t level,
550                                    uint32_t offered,
551                                    uint32_t *count,
552                                    union spoolss_MonitorInfo **info)
553 {
554         NTSTATUS status;
555         WERROR werror;
556         uint32_t needed;
557         DATA_BLOB buffer;
558
559         if (offered > 0) {
560                 buffer = data_blob_talloc_zero(mem_ctx, offered);
561                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
562         }
563
564         status = rpccli_spoolss_EnumMonitors(cli, mem_ctx,
565                                              servername,
566                                              level,
567                                              (offered > 0) ? &buffer : NULL,
568                                              offered,
569                                              count,
570                                              info,
571                                              &needed,
572                                              &werror);
573
574         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
575                 offered = needed;
576                 buffer = data_blob_talloc_zero(mem_ctx, needed);
577                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
578
579                 status = rpccli_spoolss_EnumMonitors(cli, mem_ctx,
580                                                      servername,
581                                                      level,
582                                                      (offered > 0) ? &buffer : NULL,
583                                                      offered,
584                                                      count,
585                                                      info,
586                                                      &needed,
587                                                      &werror);
588         }
589
590         return werror;
591 }
592
593 /**********************************************************************
594  convencience wrapper around rpccli_spoolss_EnumJobs
595 **********************************************************************/
596
597 WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli,
598                                TALLOC_CTX *mem_ctx,
599                                struct policy_handle *handle,
600                                uint32_t firstjob,
601                                uint32_t numjobs,
602                                uint32_t level,
603                                uint32_t offered,
604                                uint32_t *count,
605                                union spoolss_JobInfo **info)
606 {
607         NTSTATUS status;
608         WERROR werror;
609         uint32_t needed;
610         DATA_BLOB buffer;
611
612         if (offered > 0) {
613                 buffer = data_blob_talloc_zero(mem_ctx, offered);
614                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
615         }
616
617         status = rpccli_spoolss_EnumJobs(cli, mem_ctx,
618                                          handle,
619                                          firstjob,
620                                          numjobs,
621                                          level,
622                                          (offered > 0) ? &buffer : NULL,
623                                          offered,
624                                          count,
625                                          info,
626                                          &needed,
627                                          &werror);
628
629         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
630                 offered = needed;
631                 buffer = data_blob_talloc_zero(mem_ctx, needed);
632                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
633
634                 status = rpccli_spoolss_EnumJobs(cli, mem_ctx,
635                                                  handle,
636                                                  firstjob,
637                                                  numjobs,
638                                                  level,
639                                                  (offered > 0) ? &buffer : NULL,
640                                                  offered,
641                                                  count,
642                                                  info,
643                                                  &needed,
644                                                  &werror);
645         }
646
647         return werror;
648 }
649
650 /**********************************************************************
651  convencience wrapper around rpccli_spoolss_EnumPrinterDrivers
652 **********************************************************************/
653
654 WERROR rpccli_spoolss_enumprinterdrivers(struct rpc_pipe_client *cli,
655                                          TALLOC_CTX *mem_ctx,
656                                          const char *server,
657                                          const char *environment,
658                                          uint32_t level,
659                                          uint32_t offered,
660                                          uint32_t *count,
661                                          union spoolss_DriverInfo **info)
662 {
663         NTSTATUS status;
664         WERROR werror;
665         uint32_t needed;
666         DATA_BLOB buffer;
667
668         if (offered > 0) {
669                 buffer = data_blob_talloc_zero(mem_ctx, offered);
670                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
671         }
672
673         status = rpccli_spoolss_EnumPrinterDrivers(cli, mem_ctx,
674                                                    server,
675                                                    environment,
676                                                    level,
677                                                    (offered > 0) ? &buffer : NULL,
678                                                    offered,
679                                                    count,
680                                                    info,
681                                                    &needed,
682                                                    &werror);
683
684         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
685                 offered = needed;
686                 buffer = data_blob_talloc_zero(mem_ctx, needed);
687                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
688
689                 status = rpccli_spoolss_EnumPrinterDrivers(cli, mem_ctx,
690                                                    server,
691                                                    environment,
692                                                    level,
693                                                    (offered > 0) ? &buffer : NULL,
694                                                    offered,
695                                                    count,
696                                                    info,
697                                                    &needed,
698                                                    &werror);
699         }
700
701         return werror;
702 }
703
704 /**********************************************************************
705  convencience wrapper around rpccli_spoolss_EnumPrinters
706 **********************************************************************/
707
708 WERROR rpccli_spoolss_enumprinters(struct rpc_pipe_client *cli,
709                                    TALLOC_CTX *mem_ctx,
710                                    uint32_t flags,
711                                    const char *server,
712                                    uint32_t level,
713                                    uint32_t offered,
714                                    uint32_t *count,
715                                    union spoolss_PrinterInfo **info)
716 {
717         NTSTATUS status;
718         WERROR werror;
719         uint32_t needed;
720         DATA_BLOB buffer;
721
722         if (offered > 0) {
723                 buffer = data_blob_talloc_zero(mem_ctx, offered);
724                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
725         }
726
727         status = rpccli_spoolss_EnumPrinters(cli, mem_ctx,
728                                              flags,
729                                              server,
730                                              level,
731                                              (offered > 0) ? &buffer : NULL,
732                                              offered,
733                                              count,
734                                              info,
735                                              &needed,
736                                              &werror);
737
738         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
739                 offered = needed;
740                 buffer = data_blob_talloc_zero(mem_ctx, needed);
741                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
742
743                 status = rpccli_spoolss_EnumPrinters(cli, mem_ctx,
744                                                      flags,
745                                                      server,
746                                                      level,
747                                                      (offered > 0) ? &buffer : NULL,
748                                                      offered,
749                                                      count,
750                                                      info,
751                                                      &needed,
752                                                      &werror);
753         }
754
755         return werror;
756 }
757
758 /**********************************************************************
759  convencience wrapper around rpccli_spoolss_GetPrinterData
760 **********************************************************************/
761
762 WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli,
763                                      TALLOC_CTX *mem_ctx,
764                                      struct policy_handle *handle,
765                                      const char *value_name,
766                                      uint32_t offered,
767                                      enum winreg_Type *type,
768                                      union spoolss_PrinterData *data)
769 {
770         NTSTATUS status;
771         WERROR werror;
772         uint32_t needed;
773
774         status = rpccli_spoolss_GetPrinterData(cli, mem_ctx,
775                                                handle,
776                                                value_name,
777                                                offered,
778                                                type,
779                                                data,
780                                                &needed,
781                                                &werror);
782
783         if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) {
784                 offered = needed;
785
786                 status = rpccli_spoolss_GetPrinterData(cli, mem_ctx,
787                                                        handle,
788                                                        value_name,
789                                                        offered,
790                                                        type,
791                                                        data,
792                                                        &needed,
793                                                        &werror);
794         }
795
796         return werror;
797 }
798
799 /**********************************************************************
800  convencience wrapper around rpccli_spoolss_EnumPrinterKey
801 **********************************************************************/
802
803 WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli,
804                                      TALLOC_CTX *mem_ctx,
805                                      struct policy_handle *handle,
806                                      const char *key_name,
807                                      const char ***key_buffer,
808                                      uint32_t offered)
809 {
810         NTSTATUS status;
811         WERROR werror;
812         uint32_t needed;
813         uint16_t *buffer = NULL;
814
815         *key_buffer = NULL;
816
817         if (offered) {
818                 buffer = talloc_array(mem_ctx, uint16_t, offered/2);
819                 W_ERROR_HAVE_NO_MEMORY(buffer);
820         }
821
822         status = rpccli_spoolss_EnumPrinterKey(cli, mem_ctx,
823                                                handle,
824                                                key_name,
825                                                buffer,
826                                                offered,
827                                                &needed,
828                                                &werror);
829
830         if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) {
831                 offered = needed;
832                 buffer = talloc_realloc(mem_ctx, buffer, uint16_t, needed/2);
833                 W_ERROR_HAVE_NO_MEMORY(buffer);
834                 status = rpccli_spoolss_EnumPrinterKey(cli, mem_ctx,
835                                                        handle,
836                                                        key_name,
837                                                        buffer,
838                                                        offered,
839                                                        &needed,
840                                                        &werror);
841         }
842
843         if (W_ERROR_IS_OK(werror)) {
844                 const char **array;
845                 DATA_BLOB blob = data_blob_const((uint8_t *)buffer, offered);
846                 if (!pull_reg_multi_sz(mem_ctx, &blob, &array)) {
847                         return WERR_NOMEM;
848                 }
849                 *key_buffer = array;
850         }
851
852         return werror;
853 }
854
855 /**********************************************************************
856  convencience wrapper around rpccli_spoolss_EnumPrinterDataEx
857 **********************************************************************/
858
859 WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli,
860                                         TALLOC_CTX *mem_ctx,
861                                         struct policy_handle *handle,
862                                         const char *key_name,
863                                         uint32_t offered,
864                                         uint32_t *count,
865                                         struct spoolss_PrinterEnumValues **info)
866 {
867         NTSTATUS status;
868         WERROR werror;
869         uint32_t needed;
870
871         status = rpccli_spoolss_EnumPrinterDataEx(cli, mem_ctx,
872                                                   handle,
873                                                   key_name,
874                                                   offered,
875                                                   count,
876                                                   info,
877                                                   &needed,
878                                                   &werror);
879
880         if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) {
881                 offered = needed;
882
883                 status = rpccli_spoolss_EnumPrinterDataEx(cli, mem_ctx,
884                                                           handle,
885                                                           key_name,
886                                                           offered,
887                                                           count,
888                                                           info,
889                                                           &needed,
890                                                           &werror);
891         }
892
893         return werror;
894 }