Merge branch 'master' of ssh://git.samba.org/data/git/samba into displaysec
[kai/samba.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_GetPrinterDriver2
80 **********************************************************************/
81
82 WERROR rpccli_spoolss_getprinterdriver2(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                                         uint32_t client_major_version,
89                                         uint32_t client_minor_version,
90                                         union spoolss_DriverInfo *info,
91                                         uint32_t *server_major_version,
92                                         uint32_t *server_minor_version)
93 {
94         NTSTATUS status;
95         WERROR werror;
96         uint32_t needed;
97         DATA_BLOB buffer;
98
99         if (offered > 0) {
100                 buffer = data_blob_talloc_zero(mem_ctx, offered);
101                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
102         }
103
104         status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
105                                                   handle,
106                                                   architecture,
107                                                   level,
108                                                   (offered > 0) ? &buffer : NULL,
109                                                   offered,
110                                                   client_major_version,
111                                                   client_minor_version,
112                                                   info,
113                                                   &needed,
114                                                   server_major_version,
115                                                   server_minor_version,
116                                                   &werror);
117         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
118                 offered = needed;
119                 buffer = data_blob_talloc_zero(mem_ctx, needed);
120                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
121
122                 status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
123                                                           handle,
124                                                           architecture,
125                                                           level,
126                                                           &buffer,
127                                                           offered,
128                                                           client_major_version,
129                                                           client_minor_version,
130                                                           info,
131                                                           &needed,
132                                                           server_major_version,
133                                                           server_minor_version,
134                                                           &werror);
135         }
136
137         return werror;
138 }
139
140 /**********************************************************************
141  convencience wrapper around rpccli_spoolss_AddPrinterEx
142 **********************************************************************/
143
144 WERROR rpccli_spoolss_addprinterex(struct rpc_pipe_client *cli,
145                                    TALLOC_CTX *mem_ctx,
146                                    struct spoolss_SetPrinterInfoCtr *info_ctr)
147 {
148         WERROR result;
149         NTSTATUS status;
150         struct spoolss_DevmodeContainer devmode_ctr;
151         struct sec_desc_buf secdesc_ctr;
152         struct spoolss_UserLevelCtr userlevel_ctr;
153         struct spoolss_UserLevel1 level1;
154         struct policy_handle handle;
155
156         ZERO_STRUCT(devmode_ctr);
157         ZERO_STRUCT(secdesc_ctr);
158
159         level1.size             = 28;
160         level1.build            = 1381;
161         level1.major            = 2;
162         level1.minor            = 0;
163         level1.processor        = 0;
164         level1.client           = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
165         W_ERROR_HAVE_NO_MEMORY(level1.client);
166         level1.user             = cli->auth->user_name;
167
168         userlevel_ctr.level = 1;
169         userlevel_ctr.user_info.level1 = &level1;
170
171         status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx,
172                                              cli->srv_name_slash,
173                                              info_ctr,
174                                              &devmode_ctr,
175                                              &secdesc_ctr,
176                                              &userlevel_ctr,
177                                              &handle,
178                                              &result);
179         return result;
180 }
181
182 /**********************************************************************
183  convencience wrapper around rpccli_spoolss_GetPrinter
184 **********************************************************************/
185
186 WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli,
187                                  TALLOC_CTX *mem_ctx,
188                                  struct policy_handle *handle,
189                                  uint32_t level,
190                                  uint32_t offered,
191                                  union spoolss_PrinterInfo *info)
192 {
193         NTSTATUS status;
194         WERROR werror;
195         DATA_BLOB buffer;
196         uint32_t needed;
197
198         if (offered > 0) {
199                 buffer = data_blob_talloc_zero(mem_ctx, offered);
200                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
201         }
202
203         status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
204                                            handle,
205                                            level,
206                                            (offered > 0) ? &buffer : NULL,
207                                            offered,
208                                            info,
209                                            &needed,
210                                            &werror);
211
212         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
213
214                 offered = needed;
215                 buffer = data_blob_talloc_zero(mem_ctx, offered);
216                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
217
218                 status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
219                                                    handle,
220                                                    level,
221                                                    &buffer,
222                                                    offered,
223                                                    info,
224                                                    &needed,
225                                                    &werror);
226         }
227
228         return werror;
229 }
230
231 /**********************************************************************
232  convencience wrapper around rpccli_spoolss_GetJob
233 **********************************************************************/
234
235 WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli,
236                              TALLOC_CTX *mem_ctx,
237                              struct policy_handle *handle,
238                              uint32_t job_id,
239                              uint32_t level,
240                              uint32_t offered,
241                              union spoolss_JobInfo *info)
242 {
243         NTSTATUS status;
244         WERROR werror;
245         uint32_t needed;
246         DATA_BLOB buffer;
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_GetJob(cli, mem_ctx,
254                                        handle,
255                                        job_id,
256                                        level,
257                                        (offered > 0) ? &buffer : NULL,
258                                        offered,
259                                        info,
260                                        &needed,
261                                        &werror);
262
263         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
264                 offered = needed;
265                 buffer = data_blob_talloc_zero(mem_ctx, needed);
266                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
267
268                 status = rpccli_spoolss_GetJob(cli, mem_ctx,
269                                                handle,
270                                                job_id,
271                                                level,
272                                                &buffer,
273                                                offered,
274                                                info,
275                                                &needed,
276                                                &werror);
277         }
278
279         return werror;
280 }
281
282 /**********************************************************************
283  convencience wrapper around rpccli_spoolss_EnumForms
284 **********************************************************************/
285
286 WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli,
287                                 TALLOC_CTX *mem_ctx,
288                                 struct policy_handle *handle,
289                                 uint32_t level,
290                                 uint32_t offered,
291                                 uint32_t *count,
292                                 union spoolss_FormInfo **info)
293 {
294         NTSTATUS status;
295         WERROR werror;
296         uint32_t needed;
297         DATA_BLOB buffer;
298
299         if (offered > 0) {
300                 buffer = data_blob_talloc_zero(mem_ctx, offered);
301                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
302         }
303
304         status = rpccli_spoolss_EnumForms(cli, mem_ctx,
305                                           handle,
306                                           level,
307                                           (offered > 0) ? &buffer : NULL,
308                                           offered,
309                                           count,
310                                           info,
311                                           &needed,
312                                           &werror);
313
314         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
315                 offered = needed;
316                 buffer = data_blob_talloc_zero(mem_ctx, needed);
317                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
318
319                 status = rpccli_spoolss_EnumForms(cli, mem_ctx,
320                                                   handle,
321                                                   level,
322                                                   (offered > 0) ? &buffer : NULL,
323                                                   offered,
324                                                   count,
325                                                   info,
326                                                   &needed,
327                                                   &werror);
328         }
329
330         return werror;
331 }
332
333 /**********************************************************************
334  convencience wrapper around rpccli_spoolss_EnumPrintProcessors
335 **********************************************************************/
336
337 WERROR rpccli_spoolss_enumprintprocessors(struct rpc_pipe_client *cli,
338                                           TALLOC_CTX *mem_ctx,
339                                           const char *servername,
340                                           const char *environment,
341                                           uint32_t level,
342                                           uint32_t offered,
343                                           uint32_t *count,
344                                           union spoolss_PrintProcessorInfo **info)
345 {
346         NTSTATUS status;
347         WERROR werror;
348         uint32_t needed;
349         DATA_BLOB buffer;
350
351         if (offered > 0) {
352                 buffer = data_blob_talloc_zero(mem_ctx, offered);
353                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
354         }
355
356         status = rpccli_spoolss_EnumPrintProcessors(cli, mem_ctx,
357                                                     servername,
358                                                     environment,
359                                                     level,
360                                                     (offered > 0) ? &buffer : NULL,
361                                                     offered,
362                                                     count,
363                                                     info,
364                                                     &needed,
365                                                     &werror);
366
367         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
368                 offered = needed;
369                 buffer = data_blob_talloc_zero(mem_ctx, needed);
370                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
371
372                 status = rpccli_spoolss_EnumPrintProcessors(cli, mem_ctx,
373                                                             servername,
374                                                             environment,
375                                                             level,
376                                                             (offered > 0) ? &buffer : NULL,
377                                                             offered,
378                                                             count,
379                                                             info,
380                                                             &needed,
381                                                             &werror);
382         }
383
384         return werror;
385 }
386
387 /**********************************************************************
388  convencience wrapper around rpccli_spoolss_EnumPrintProcDataTypes
389 **********************************************************************/
390
391 WERROR rpccli_spoolss_enumprintprocessordatatypes(struct rpc_pipe_client *cli,
392                                                   TALLOC_CTX *mem_ctx,
393                                                   const char *servername,
394                                                   const char *print_processor_name,
395                                                   uint32_t level,
396                                                   uint32_t offered,
397                                                   uint32_t *count,
398                                                   union spoolss_PrintProcDataTypesInfo **info)
399 {
400         NTSTATUS status;
401         WERROR werror;
402         uint32_t needed;
403         DATA_BLOB buffer;
404
405         if (offered > 0) {
406                 buffer = data_blob_talloc_zero(mem_ctx, offered);
407                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
408         }
409
410         status = rpccli_spoolss_EnumPrintProcDataTypes(cli, mem_ctx,
411                                                        servername,
412                                                        print_processor_name,
413                                                        level,
414                                                        (offered > 0) ? &buffer : NULL,
415                                                        offered,
416                                                        count,
417                                                        info,
418                                                        &needed,
419                                                        &werror);
420
421         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
422                 offered = needed;
423                 buffer = data_blob_talloc_zero(mem_ctx, needed);
424                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
425
426                 status = rpccli_spoolss_EnumPrintProcDataTypes(cli, mem_ctx,
427                                                                servername,
428                                                                print_processor_name,
429                                                                level,
430                                                                (offered > 0) ? &buffer : NULL,
431                                                                offered,
432                                                                count,
433                                                                info,
434                                                                &needed,
435                                                                &werror);
436         }
437
438         return werror;
439 }
440
441 /**********************************************************************
442  convencience wrapper around rpccli_spoolss_EnumPorts
443 **********************************************************************/
444
445 WERROR rpccli_spoolss_enumports(struct rpc_pipe_client *cli,
446                                 TALLOC_CTX *mem_ctx,
447                                 const char *servername,
448                                 uint32_t level,
449                                 uint32_t offered,
450                                 uint32_t *count,
451                                 union spoolss_PortInfo **info)
452 {
453         NTSTATUS status;
454         WERROR werror;
455         uint32_t needed;
456         DATA_BLOB buffer;
457
458         if (offered > 0) {
459                 buffer = data_blob_talloc_zero(mem_ctx, offered);
460                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
461         }
462
463         status = rpccli_spoolss_EnumPorts(cli, mem_ctx,
464                                           servername,
465                                           level,
466                                           (offered > 0) ? &buffer : NULL,
467                                           offered,
468                                           count,
469                                           info,
470                                           &needed,
471                                           &werror);
472
473         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
474                 offered = needed;
475                 buffer = data_blob_talloc_zero(mem_ctx, needed);
476                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
477
478                 status = rpccli_spoolss_EnumPorts(cli, mem_ctx,
479                                                   servername,
480                                                   level,
481                                                   (offered > 0) ? &buffer : NULL,
482                                                   offered,
483                                                   count,
484                                                   info,
485                                                   &needed,
486                                                   &werror);
487         }
488
489         return werror;
490 }
491
492 /**********************************************************************
493  convencience wrapper around rpccli_spoolss_EnumMonitors
494 **********************************************************************/
495
496 WERROR rpccli_spoolss_enummonitors(struct rpc_pipe_client *cli,
497                                    TALLOC_CTX *mem_ctx,
498                                    const char *servername,
499                                    uint32_t level,
500                                    uint32_t offered,
501                                    uint32_t *count,
502                                    union spoolss_MonitorInfo **info)
503 {
504         NTSTATUS status;
505         WERROR werror;
506         uint32_t needed;
507         DATA_BLOB buffer;
508
509         if (offered > 0) {
510                 buffer = data_blob_talloc_zero(mem_ctx, offered);
511                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
512         }
513
514         status = rpccli_spoolss_EnumMonitors(cli, mem_ctx,
515                                              servername,
516                                              level,
517                                              (offered > 0) ? &buffer : NULL,
518                                              offered,
519                                              count,
520                                              info,
521                                              &needed,
522                                              &werror);
523
524         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
525                 offered = needed;
526                 buffer = data_blob_talloc_zero(mem_ctx, needed);
527                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
528
529                 status = rpccli_spoolss_EnumMonitors(cli, mem_ctx,
530                                                      servername,
531                                                      level,
532                                                      (offered > 0) ? &buffer : NULL,
533                                                      offered,
534                                                      count,
535                                                      info,
536                                                      &needed,
537                                                      &werror);
538         }
539
540         return werror;
541 }
542
543 /**********************************************************************
544  convencience wrapper around rpccli_spoolss_EnumJobs
545 **********************************************************************/
546
547 WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli,
548                                TALLOC_CTX *mem_ctx,
549                                struct policy_handle *handle,
550                                uint32_t firstjob,
551                                uint32_t numjobs,
552                                uint32_t level,
553                                uint32_t offered,
554                                uint32_t *count,
555                                union spoolss_JobInfo **info)
556 {
557         NTSTATUS status;
558         WERROR werror;
559         uint32_t needed;
560         DATA_BLOB buffer;
561
562         if (offered > 0) {
563                 buffer = data_blob_talloc_zero(mem_ctx, offered);
564                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
565         }
566
567         status = rpccli_spoolss_EnumJobs(cli, mem_ctx,
568                                          handle,
569                                          firstjob,
570                                          numjobs,
571                                          level,
572                                          (offered > 0) ? &buffer : NULL,
573                                          offered,
574                                          count,
575                                          info,
576                                          &needed,
577                                          &werror);
578
579         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
580                 offered = needed;
581                 buffer = data_blob_talloc_zero(mem_ctx, needed);
582                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
583
584                 status = rpccli_spoolss_EnumJobs(cli, mem_ctx,
585                                                  handle,
586                                                  firstjob,
587                                                  numjobs,
588                                                  level,
589                                                  (offered > 0) ? &buffer : NULL,
590                                                  offered,
591                                                  count,
592                                                  info,
593                                                  &needed,
594                                                  &werror);
595         }
596
597         return werror;
598 }
599
600 /**********************************************************************
601  convencience wrapper around rpccli_spoolss_EnumPrinterDrivers
602 **********************************************************************/
603
604 WERROR rpccli_spoolss_enumprinterdrivers(struct rpc_pipe_client *cli,
605                                          TALLOC_CTX *mem_ctx,
606                                          const char *server,
607                                          const char *environment,
608                                          uint32_t level,
609                                          uint32_t offered,
610                                          uint32_t *count,
611                                          union spoolss_DriverInfo **info)
612 {
613         NTSTATUS status;
614         WERROR werror;
615         uint32_t needed;
616         DATA_BLOB buffer;
617
618         if (offered > 0) {
619                 buffer = data_blob_talloc_zero(mem_ctx, offered);
620                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
621         }
622
623         status = rpccli_spoolss_EnumPrinterDrivers(cli, mem_ctx,
624                                                    server,
625                                                    environment,
626                                                    level,
627                                                    (offered > 0) ? &buffer : NULL,
628                                                    offered,
629                                                    count,
630                                                    info,
631                                                    &needed,
632                                                    &werror);
633
634         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
635                 offered = needed;
636                 buffer = data_blob_talloc_zero(mem_ctx, needed);
637                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
638
639                 status = rpccli_spoolss_EnumPrinterDrivers(cli, mem_ctx,
640                                                    server,
641                                                    environment,
642                                                    level,
643                                                    (offered > 0) ? &buffer : NULL,
644                                                    offered,
645                                                    count,
646                                                    info,
647                                                    &needed,
648                                                    &werror);
649         }
650
651         return werror;
652 }
653
654 /**********************************************************************
655  convencience wrapper around rpccli_spoolss_EnumPrinters
656 **********************************************************************/
657
658 WERROR rpccli_spoolss_enumprinters(struct rpc_pipe_client *cli,
659                                    TALLOC_CTX *mem_ctx,
660                                    uint32_t flags,
661                                    const char *server,
662                                    uint32_t level,
663                                    uint32_t offered,
664                                    uint32_t *count,
665                                    union spoolss_PrinterInfo **info)
666 {
667         NTSTATUS status;
668         WERROR werror;
669         uint32_t needed;
670         DATA_BLOB buffer;
671
672         if (offered > 0) {
673                 buffer = data_blob_talloc_zero(mem_ctx, offered);
674                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
675         }
676
677         status = rpccli_spoolss_EnumPrinters(cli, mem_ctx,
678                                              flags,
679                                              server,
680                                              level,
681                                              (offered > 0) ? &buffer : NULL,
682                                              offered,
683                                              count,
684                                              info,
685                                              &needed,
686                                              &werror);
687
688         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
689                 offered = needed;
690                 buffer = data_blob_talloc_zero(mem_ctx, needed);
691                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
692
693                 status = rpccli_spoolss_EnumPrinters(cli, mem_ctx,
694                                                      flags,
695                                                      server,
696                                                      level,
697                                                      (offered > 0) ? &buffer : NULL,
698                                                      offered,
699                                                      count,
700                                                      info,
701                                                      &needed,
702                                                      &werror);
703         }
704
705         return werror;
706 }
707
708 /**********************************************************************
709  convencience wrapper around rpccli_spoolss_GetPrinterData
710 **********************************************************************/
711
712 WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli,
713                                      TALLOC_CTX *mem_ctx,
714                                      struct policy_handle *handle,
715                                      const char *value_name,
716                                      uint32_t offered,
717                                      enum winreg_Type *type,
718                                      union spoolss_PrinterData *data)
719 {
720         NTSTATUS status;
721         WERROR werror;
722         uint32_t needed;
723
724         status = rpccli_spoolss_GetPrinterData(cli, mem_ctx,
725                                                handle,
726                                                value_name,
727                                                offered,
728                                                type,
729                                                data,
730                                                &needed,
731                                                &werror);
732
733         if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) {
734                 offered = needed;
735
736                 status = rpccli_spoolss_GetPrinterData(cli, mem_ctx,
737                                                        handle,
738                                                        value_name,
739                                                        offered,
740                                                        type,
741                                                        data,
742                                                        &needed,
743                                                        &werror);
744         }
745
746         return werror;
747 }
748
749 /**********************************************************************
750  convencience wrapper around rpccli_spoolss_EnumPrinterKey
751 **********************************************************************/
752
753 WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli,
754                                      TALLOC_CTX *mem_ctx,
755                                      struct policy_handle *handle,
756                                      const char *key_name,
757                                      const char ***key_buffer,
758                                      uint32_t offered)
759 {
760         NTSTATUS status;
761         WERROR werror;
762         uint32_t needed;
763
764         status = rpccli_spoolss_EnumPrinterKey(cli, mem_ctx,
765                                                handle,
766                                                key_name,
767                                                key_buffer,
768                                                offered,
769                                                &needed,
770                                                &werror);
771
772         if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) {
773                 offered = needed;
774
775                 status = rpccli_spoolss_EnumPrinterKey(cli, mem_ctx,
776                                                        handle,
777                                                        key_name,
778                                                        key_buffer,
779                                                        offered,
780                                                        &needed,
781                                                        &werror);
782         }
783
784         return werror;
785 }
786
787 /**********************************************************************
788  convencience wrapper around rpccli_spoolss_EnumPrinterDataEx
789 **********************************************************************/
790
791 WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli,
792                                         TALLOC_CTX *mem_ctx,
793                                         struct policy_handle *handle,
794                                         const char *key_name,
795                                         uint32_t offered,
796                                         uint32_t *count,
797                                         struct spoolss_PrinterEnumValues **info)
798 {
799         NTSTATUS status;
800         WERROR werror;
801         uint32_t needed;
802
803         status = rpccli_spoolss_EnumPrinterDataEx(cli, mem_ctx,
804                                                   handle,
805                                                   key_name,
806                                                   offered,
807                                                   count,
808                                                   info,
809                                                   &needed,
810                                                   &werror);
811
812         if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) {
813                 offered = needed;
814
815                 status = rpccli_spoolss_EnumPrinterDataEx(cli, mem_ctx,
816                                                           handle,
817                                                           key_name,
818                                                           offered,
819                                                           count,
820                                                           info,
821                                                           &needed,
822                                                           &werror);
823         }
824
825         return werror;
826 }