20599d12b6b166574280cac44ddc2b9b3ae062f0
[jra/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  Decode various spoolss rpc's and info levels
184  ********************************************************************/
185
186 /**********************************************************************
187 **********************************************************************/
188
189 static bool decode_printer_info_0(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
190                                 uint32 returned, PRINTER_INFO_0 **info)
191 {
192         uint32 i;
193         PRINTER_INFO_0  *inf;
194
195         if (returned) {
196                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_0, returned);
197                 if (!inf) {
198                         return False;
199                 }
200                 memset(inf, 0, returned*sizeof(PRINTER_INFO_0));
201         } else {
202                 inf = NULL;
203         }
204
205         prs_set_offset(&buffer->prs,0);
206
207         for (i=0; i<returned; i++) {
208                 if (!smb_io_printer_info_0("", buffer, &inf[i], 0)) {
209                         return False;
210                 }
211         }
212
213         *info=inf;
214         return True;
215 }
216
217 /**********************************************************************
218 **********************************************************************/
219
220 static bool decode_printer_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
221                                 uint32 returned, PRINTER_INFO_1 **info)
222 {
223         uint32 i;
224         PRINTER_INFO_1  *inf;
225
226         if (returned) {
227                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_1, returned);
228                 if (!inf) {
229                         return False;
230                 }
231                 memset(inf, 0, returned*sizeof(PRINTER_INFO_1));
232         } else {
233                 inf = NULL;
234         }
235
236         prs_set_offset(&buffer->prs,0);
237
238         for (i=0; i<returned; i++) {
239                 if (!smb_io_printer_info_1("", buffer, &inf[i], 0)) {
240                         return False;
241                 }
242         }
243
244         *info=inf;
245         return True;
246 }
247
248 /**********************************************************************
249 **********************************************************************/
250
251 static bool decode_printer_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
252                                 uint32 returned, PRINTER_INFO_2 **info)
253 {
254         uint32 i;
255         PRINTER_INFO_2  *inf;
256
257         if (returned) {
258                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_2, returned);
259                 if (!inf) {
260                         return False;
261                 }
262                 memset(inf, 0, returned*sizeof(PRINTER_INFO_2));
263         } else {
264                 inf = NULL;
265         }
266
267         prs_set_offset(&buffer->prs,0);
268
269         for (i=0; i<returned; i++) {
270                 /* a little initialization as we go */
271                 inf[i].secdesc = NULL;
272                 if (!smb_io_printer_info_2("", buffer, &inf[i], 0)) {
273                         return False;
274                 }
275         }
276
277         *info=inf;
278         return True;
279 }
280
281 /**********************************************************************
282 **********************************************************************/
283
284 static bool decode_printer_info_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
285                                 uint32 returned, PRINTER_INFO_3 **info)
286 {
287         uint32 i;
288         PRINTER_INFO_3  *inf;
289
290         if (returned) {
291                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_3, returned);
292                 if (!inf) {
293                         return False;
294                 }
295                 memset(inf, 0, returned*sizeof(PRINTER_INFO_3));
296         } else {
297                 inf = NULL;
298         }
299
300         prs_set_offset(&buffer->prs,0);
301
302         for (i=0; i<returned; i++) {
303                 inf[i].secdesc = NULL;
304                 if (!smb_io_printer_info_3("", buffer, &inf[i], 0)) {
305                         return False;
306                 }
307         }
308
309         *info=inf;
310         return True;
311 }
312
313 /**********************************************************************
314 **********************************************************************/
315
316 static bool decode_printer_info_7(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
317                                 uint32 returned, PRINTER_INFO_7 **info)
318 {
319         uint32 i;
320         PRINTER_INFO_7  *inf;
321
322         if (returned) {
323                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_7, returned);
324                 if (!inf) {
325                         return False;
326                 }
327                 memset(inf, 0, returned*sizeof(PRINTER_INFO_7));
328         } else {
329                 inf = NULL;
330         }
331
332         prs_set_offset(&buffer->prs,0);
333
334         for (i=0; i<returned; i++) {
335                 if (!smb_io_printer_info_7("", buffer, &inf[i], 0)) {
336                         return False;
337                 }
338         }
339
340         *info=inf;
341         return True;
342 }
343
344
345 /**********************************************************************
346 **********************************************************************/
347
348 static bool decode_port_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
349                         uint32 returned, PORT_INFO_1 **info)
350 {
351         uint32 i;
352         PORT_INFO_1 *inf;
353
354         if (returned) {
355                 inf=TALLOC_ARRAY(mem_ctx, PORT_INFO_1, returned);
356                 if (!inf) {
357                         return False;
358                 }
359                 memset(inf, 0, returned*sizeof(PORT_INFO_1));
360         } else {
361                 inf = NULL;
362         }
363
364         prs_set_offset(&buffer->prs, 0);
365
366         for (i=0; i<returned; i++) {
367                 if (!smb_io_port_info_1("", buffer, &(inf[i]), 0)) {
368                         return False;
369                 }
370         }
371
372         *info=inf;
373         return True;
374 }
375
376 /**********************************************************************
377 **********************************************************************/
378
379 static bool decode_port_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
380                         uint32 returned, PORT_INFO_2 **info)
381 {
382         uint32 i;
383         PORT_INFO_2 *inf;
384
385         if (returned) {
386                 inf=TALLOC_ARRAY(mem_ctx, PORT_INFO_2, returned);
387                 if (!inf) {
388                         return False;
389                 }
390                 memset(inf, 0, returned*sizeof(PORT_INFO_2));
391         } else {
392                 inf = NULL;
393         }
394
395         prs_set_offset(&buffer->prs, 0);
396
397         for (i=0; i<returned; i++) {
398                 if (!smb_io_port_info_2("", buffer, &(inf[i]), 0)) {
399                         return False;
400                 }
401         }
402
403         *info=inf;
404         return True;
405 }
406
407 /**********************************************************************
408 **********************************************************************/
409
410 static bool decode_printer_driver_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
411                         uint32 returned, DRIVER_INFO_1 **info)
412 {
413         uint32 i;
414         DRIVER_INFO_1 *inf;
415
416         if (returned) {
417                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_1, returned);
418                 if (!inf) {
419                         return False;
420                 }
421                 memset(inf, 0, returned*sizeof(DRIVER_INFO_1));
422         } else {
423                 inf = NULL;
424         }
425
426         prs_set_offset(&buffer->prs,0);
427
428         for (i=0; i<returned; i++) {
429                 if (!smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0)) {
430                         return False;
431                 }
432         }
433
434         *info=inf;
435         return True;
436 }
437
438 /**********************************************************************
439 **********************************************************************/
440
441 static bool decode_printer_driver_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
442                         uint32 returned, DRIVER_INFO_2 **info)
443 {
444         uint32 i;
445         DRIVER_INFO_2 *inf;
446
447         if (returned) {
448                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_2, returned);
449                 if (!inf) {
450                         return False;
451                 }
452                 memset(inf, 0, returned*sizeof(DRIVER_INFO_2));
453         } else {
454                 inf = NULL;
455         }
456
457         prs_set_offset(&buffer->prs,0);
458
459         for (i=0; i<returned; i++) {
460                 if (!smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0)) {
461                         return False;
462                 }
463         }
464
465         *info=inf;
466         return True;
467 }
468
469 /**********************************************************************
470 **********************************************************************/
471
472 static bool decode_printer_driver_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
473                         uint32 returned, DRIVER_INFO_3 **info)
474 {
475         uint32 i;
476         DRIVER_INFO_3 *inf;
477
478         if (returned) {
479                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_3, returned);
480                 if (!inf) {
481                         return False;
482                 }
483                 memset(inf, 0, returned*sizeof(DRIVER_INFO_3));
484         } else {
485                 inf = NULL;
486         }
487
488         prs_set_offset(&buffer->prs,0);
489
490         for (i=0; i<returned; i++) {
491                 if (!smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0)) {
492                         return False;
493                 }
494         }
495
496         *info=inf;
497         return True;
498 }
499
500 /**********************************************************************
501 **********************************************************************/
502
503 static bool decode_jobs_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
504                           uint32 num_jobs, JOB_INFO_1 **jobs)
505 {
506         uint32 i;
507
508         if (num_jobs) {
509                 *jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_1, num_jobs);
510                 if (*jobs == NULL) {
511                         return False;
512                 }
513         } else {
514                 *jobs = NULL;
515         }
516         prs_set_offset(&buffer->prs,0);
517
518         for (i = 0; i < num_jobs; i++) {
519                 if (!smb_io_job_info_1("", buffer, &((*jobs)[i]), 0)) {
520                         return False;
521                 }
522         }
523
524         return True;
525 }
526
527 /**********************************************************************
528 **********************************************************************/
529
530 static bool decode_jobs_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
531                           uint32 num_jobs, JOB_INFO_2 **jobs)
532 {
533         uint32 i;
534
535         if (num_jobs) {
536                 *jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_2, num_jobs);
537                 if (*jobs == NULL) {
538                         return False;
539                 }
540         } else {
541                 *jobs = NULL;
542         }
543         prs_set_offset(&buffer->prs,0);
544
545         for (i = 0; i < num_jobs; i++) {
546                 if (!smb_io_job_info_2("", buffer, &((*jobs)[i]), 0)) {
547                         return False;
548                 }
549         }
550
551         return True;
552 }
553
554 /**********************************************************************
555 **********************************************************************/
556
557 static bool decode_forms_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
558                            uint32 num_forms, FORM_1 **forms)
559 {
560         int i;
561
562         if (num_forms) {
563                 *forms = TALLOC_ARRAY(mem_ctx, FORM_1, num_forms);
564                 if (*forms == NULL) {
565                         return False;
566                 }
567         } else {
568                 *forms = NULL;
569         }
570
571         prs_set_offset(&buffer->prs,0);
572
573         for (i = 0; i < num_forms; i++) {
574                 if (!smb_io_form_1("", buffer, &((*forms)[i]), 0)) {
575                         return False;
576                 }
577         }
578
579         return True;
580 }
581
582 /**********************************************************************
583 **********************************************************************/
584
585 WERROR rpccli_spoolss_enum_printers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
586                                  char *name, uint32 flags, uint32 level,
587                                  uint32 *num_printers, PRINTER_INFO_CTR *ctr)
588 {
589         prs_struct qbuf, rbuf;
590         SPOOL_Q_ENUMPRINTERS in;
591         SPOOL_R_ENUMPRINTERS out;
592         RPC_BUFFER buffer;
593         uint32 offered;
594
595         ZERO_STRUCT(in);
596         ZERO_STRUCT(out);
597
598         offered = 0;
599         if (!rpcbuf_init(&buffer, offered, mem_ctx))
600                 return WERR_NOMEM;
601         make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
602
603         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERS,
604                     in, out, 
605                     qbuf, rbuf,
606                     spoolss_io_q_enumprinters,
607                     spoolss_io_r_enumprinters, 
608                     WERR_GENERAL_FAILURE );
609                     
610         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
611                 offered = out.needed;
612                 
613                 ZERO_STRUCT(in);
614                 ZERO_STRUCT(out);
615
616                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
617                         return WERR_NOMEM;
618                 make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
619
620                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERS,
621                             in, out, 
622                             qbuf, rbuf,
623                             spoolss_io_q_enumprinters,
624                             spoolss_io_r_enumprinters, 
625                             WERR_GENERAL_FAILURE );
626         }
627
628         if ( !W_ERROR_IS_OK(out.status) )
629                 return out.status;
630
631         switch (level) {
632         case 0:
633                 if (!decode_printer_info_0(mem_ctx, out.buffer, out.returned, &ctr->printers_0)) {
634                         return WERR_GENERAL_FAILURE;
635                 }
636                 break;
637         case 1:
638                 if (!decode_printer_info_1(mem_ctx, out.buffer, out.returned, &ctr->printers_1)) {
639                         return WERR_GENERAL_FAILURE;
640                 }
641                 break;
642         case 2:
643                 if (!decode_printer_info_2(mem_ctx, out.buffer, out.returned, &ctr->printers_2)) {
644                         return WERR_GENERAL_FAILURE;
645                 }
646                 break;
647         case 3:
648                 if (!decode_printer_info_3(mem_ctx, out.buffer, out.returned, &ctr->printers_3)) {
649                         return WERR_GENERAL_FAILURE;
650                 }
651                 break;
652         default:
653                 return WERR_UNKNOWN_LEVEL;
654         }                       
655
656         *num_printers = out.returned;
657
658         return out.status;
659 }
660
661 /**********************************************************************
662 **********************************************************************/
663
664 WERROR rpccli_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
665                               uint32 level, uint32 *num_ports, PORT_INFO_CTR *ctr)
666 {
667         prs_struct qbuf, rbuf;
668         SPOOL_Q_ENUMPORTS in;
669         SPOOL_R_ENUMPORTS out;
670         RPC_BUFFER buffer;
671         fstring server;
672         uint32 offered;
673
674         ZERO_STRUCT(in);
675         ZERO_STRUCT(out);
676
677         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
678         strupper_m(server);
679
680         offered = 0;
681         if (!rpcbuf_init(&buffer, offered, mem_ctx))
682                 return WERR_NOMEM;
683         make_spoolss_q_enumports( &in, server, level, &buffer, offered );
684         
685         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPORTS,
686                     in, out, 
687                     qbuf, rbuf,
688                     spoolss_io_q_enumports,
689                     spoolss_io_r_enumports, 
690                     WERR_GENERAL_FAILURE );
691                         
692         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
693                 offered = out.needed;
694                 
695                 ZERO_STRUCT(in);
696                 ZERO_STRUCT(out);
697                 
698                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
699                         return WERR_NOMEM;
700                 make_spoolss_q_enumports( &in, server, level, &buffer, offered );
701
702                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPORTS,
703                             in, out, 
704                             qbuf, rbuf,
705                             spoolss_io_q_enumports,
706                             spoolss_io_r_enumports, 
707                             WERR_GENERAL_FAILURE );
708         }
709         
710         if ( !W_ERROR_IS_OK(out.status) )
711                 return out.status;
712         
713         switch (level) {
714         case 1:
715                 if (!decode_port_info_1(mem_ctx, out.buffer, out.returned, &ctr->port.info_1)) {
716                         return WERR_GENERAL_FAILURE;
717                 }
718                 break;
719         case 2:
720                 if (!decode_port_info_2(mem_ctx, out.buffer, out.returned, &ctr->port.info_2)) {
721                         return WERR_GENERAL_FAILURE;
722                 }
723                 break;
724         default:
725                 return WERR_UNKNOWN_LEVEL;
726         }
727
728         *num_ports = out.returned;
729
730         return out.status;
731 }
732
733 /**********************************************************************
734 **********************************************************************/
735
736 WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
737                               POLICY_HND *pol, uint32 level, 
738                               PRINTER_INFO_CTR *ctr)
739 {
740         prs_struct qbuf, rbuf;
741         SPOOL_Q_GETPRINTER in;
742         SPOOL_R_GETPRINTER out;
743         RPC_BUFFER buffer;
744         uint32 offered;
745
746         ZERO_STRUCT(in);
747         ZERO_STRUCT(out);
748
749         /* Initialise input parameters */
750
751         offered = 0;
752         if (!rpcbuf_init(&buffer, offered, mem_ctx))
753                 return WERR_NOMEM;
754         make_spoolss_q_getprinter( mem_ctx, &in, pol, level, &buffer, offered );
755         
756         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTER,
757                     in, out, 
758                     qbuf, rbuf,
759                     spoolss_io_q_getprinter,
760                     spoolss_io_r_getprinter, 
761                     WERR_GENERAL_FAILURE );
762
763         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
764                 offered = out.needed;
765                 
766                 ZERO_STRUCT(in);
767                 ZERO_STRUCT(out);
768                 
769                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
770                         return WERR_NOMEM;
771                 make_spoolss_q_getprinter( mem_ctx, &in, pol, level, &buffer, offered );
772
773                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTER,
774                             in, out, 
775                             qbuf, rbuf,
776                             spoolss_io_q_getprinter,
777                             spoolss_io_r_getprinter, 
778                             WERR_GENERAL_FAILURE );
779         }
780         
781         if ( !W_ERROR_IS_OK(out.status) )
782                 return out.status;
783                 
784         switch (level) {
785         case 0:
786                 if (!decode_printer_info_0(mem_ctx, out.buffer, 1, &ctr->printers_0)) {
787                         return WERR_GENERAL_FAILURE;
788                 }
789                 break;
790         case 1:
791                 if (!decode_printer_info_1(mem_ctx, out.buffer, 1, &ctr->printers_1)) {
792                         return WERR_GENERAL_FAILURE;
793                 }
794                 break;
795         case 2:
796                 if (!decode_printer_info_2(mem_ctx, out.buffer, 1, &ctr->printers_2)) {
797                         return WERR_GENERAL_FAILURE;
798                 }
799                 break;
800         case 3:
801                 if (!decode_printer_info_3(mem_ctx, out.buffer, 1, &ctr->printers_3)) {
802                         return WERR_GENERAL_FAILURE;
803                 }
804                 break;
805         case 7:
806                 if (!decode_printer_info_7(mem_ctx, out.buffer, 1, &ctr->printers_7)) {
807                         return WERR_GENERAL_FAILURE;
808                 }
809                 break;
810         default:
811                 return WERR_UNKNOWN_LEVEL;
812         }
813
814         return out.status;
815 }
816
817 /**********************************************************************
818 **********************************************************************/
819
820 WERROR rpccli_spoolss_setprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
821                               POLICY_HND *pol, uint32 level, 
822                               PRINTER_INFO_CTR *ctr, uint32 command)
823 {
824         prs_struct qbuf, rbuf;
825         SPOOL_Q_SETPRINTER in;
826         SPOOL_R_SETPRINTER out;
827
828         ZERO_STRUCT(in);
829         ZERO_STRUCT(out);
830
831         make_spoolss_q_setprinter( mem_ctx, &in, pol, level, ctr, command );
832
833         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_SETPRINTER,
834                     in, out, 
835                     qbuf, rbuf,
836                     spoolss_io_q_setprinter,
837                     spoolss_io_r_setprinter, 
838                     WERR_GENERAL_FAILURE );
839
840         return out.status;
841 }
842
843 /**********************************************************************
844 **********************************************************************/
845
846 WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli, 
847                                        TALLOC_CTX *mem_ctx,
848                                        uint32 level, const char *env,
849                                        uint32 *num_drivers,
850                                        PRINTER_DRIVER_CTR *ctr)
851 {
852         prs_struct qbuf, rbuf;
853         SPOOL_Q_ENUMPRINTERDRIVERS in;
854         SPOOL_R_ENUMPRINTERDRIVERS out;
855         RPC_BUFFER buffer;
856         fstring server;
857         uint32 offered;
858
859         ZERO_STRUCT(in);
860         ZERO_STRUCT(out);
861
862         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
863         strupper_m(server);
864
865         offered = 0;
866         if (!rpcbuf_init(&buffer, offered, mem_ctx))
867                 return WERR_NOMEM;
868         make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
869                 &buffer, offered);
870         
871         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
872                     in, out, 
873                     qbuf, rbuf,
874                     spoolss_io_q_enumprinterdrivers,
875                     spoolss_io_r_enumprinterdrivers, 
876                     WERR_GENERAL_FAILURE );
877
878         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
879                 offered = out.needed;
880                 
881                 ZERO_STRUCT(in);
882                 ZERO_STRUCT(out);
883                 
884                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
885                         return WERR_NOMEM;
886                 make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
887                         &buffer, offered);
888         
889                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
890                             in, out, 
891                             qbuf, rbuf,
892                             spoolss_io_q_enumprinterdrivers,
893                             spoolss_io_r_enumprinterdrivers, 
894                             WERR_GENERAL_FAILURE );
895         }
896         
897         *num_drivers = out.returned;
898
899         if ( !W_ERROR_IS_OK(out.status) )
900                 return out.status;
901                 
902         if ( out.returned ) {
903
904                 switch (level) {
905                 case 1:
906                         if (!decode_printer_driver_1(mem_ctx, out.buffer, out.returned, &ctr->info1)) {
907                                 return WERR_GENERAL_FAILURE;
908                         }
909                         break;
910                 case 2:
911                         if (!decode_printer_driver_2(mem_ctx, out.buffer, out.returned, &ctr->info2)) {
912                                 return WERR_GENERAL_FAILURE;
913                         }
914                         break;
915                 case 3:
916                         if (!decode_printer_driver_3(mem_ctx, out.buffer, out.returned, &ctr->info3)) {
917                                 return WERR_GENERAL_FAILURE;
918                         }
919                         break;
920                 default:
921                         return WERR_UNKNOWN_LEVEL;
922                 }
923         }
924
925         return out.status;
926 }
927
928 /**********************************************************************
929 **********************************************************************/
930
931 WERROR rpccli_spoolss_addprinterex (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
932                                  uint32 level, PRINTER_INFO_CTR*ctr)
933 {
934         prs_struct qbuf, rbuf;
935         SPOOL_Q_ADDPRINTEREX in;
936         SPOOL_R_ADDPRINTEREX out;
937         fstring server, client, user;
938
939         ZERO_STRUCT(in);
940         ZERO_STRUCT(out);
941         
942         slprintf(client, sizeof(fstring)-1, "\\\\%s", global_myname());
943         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
944         
945         strupper_m(client);
946         strupper_m(server);
947
948         fstrcpy  (user, cli->auth->user_name);
949
950         make_spoolss_q_addprinterex( mem_ctx, &in, server, client, 
951                 user, level, ctr);
952
953         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ADDPRINTEREX,
954                     in, out, 
955                     qbuf, rbuf,
956                     spoolss_io_q_addprinterex,
957                     spoolss_io_r_addprinterex, 
958                     WERR_GENERAL_FAILURE );
959
960         return out.status;      
961 }
962
963 /**********************************************************************
964 **********************************************************************/
965
966 WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
967                              POLICY_HND *handle, int level, uint32 *num_forms,
968                              FORM_1 **forms)
969 {
970         prs_struct qbuf, rbuf;
971         SPOOL_Q_ENUMFORMS in;
972         SPOOL_R_ENUMFORMS out;
973         RPC_BUFFER buffer;
974         uint32 offered;
975
976         ZERO_STRUCT(in);
977         ZERO_STRUCT(out);
978
979         offered = 0;
980         if (!rpcbuf_init(&buffer, offered, mem_ctx))
981                 return WERR_NOMEM;
982         make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
983
984         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
985                     in, out, 
986                     qbuf, rbuf,
987                     spoolss_io_q_enumforms,
988                     spoolss_io_r_enumforms, 
989                     WERR_GENERAL_FAILURE );
990
991         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
992                 offered = out.needed;
993                 
994                 ZERO_STRUCT(in);
995                 ZERO_STRUCT(out);
996
997                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
998                         return WERR_NOMEM;
999                 make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
1000
1001                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
1002                             in, out, 
1003                             qbuf, rbuf,
1004                             spoolss_io_q_enumforms,
1005                             spoolss_io_r_enumforms, 
1006                             WERR_GENERAL_FAILURE );
1007         }
1008
1009         if (!W_ERROR_IS_OK(out.status))
1010                 return out.status;
1011
1012         *num_forms = out.numofforms;
1013         
1014         if (!decode_forms_1(mem_ctx, out.buffer, *num_forms, forms)) {
1015                 return WERR_GENERAL_FAILURE;
1016         }
1017
1018         return out.status;
1019 }
1020
1021 /**********************************************************************
1022 **********************************************************************/
1023
1024 WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1025                             POLICY_HND *hnd, uint32 level, uint32 firstjob, 
1026                             uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr)
1027 {
1028         prs_struct qbuf, rbuf;
1029         SPOOL_Q_ENUMJOBS in;
1030         SPOOL_R_ENUMJOBS out;
1031         RPC_BUFFER buffer;
1032         uint32 offered;
1033
1034         ZERO_STRUCT(in);
1035         ZERO_STRUCT(out);
1036
1037         offered = 0;
1038         if (!rpcbuf_init(&buffer, offered, mem_ctx))
1039                 return WERR_NOMEM;
1040         make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
1041                 &buffer, offered );
1042
1043         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
1044                     in, out, 
1045                     qbuf, rbuf,
1046                     spoolss_io_q_enumjobs,
1047                     spoolss_io_r_enumjobs, 
1048                     WERR_GENERAL_FAILURE );
1049
1050         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
1051                 offered = out.needed;
1052                 
1053                 ZERO_STRUCT(in);
1054                 ZERO_STRUCT(out);
1055
1056                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
1057                         return WERR_NOMEM;
1058                 make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
1059                         &buffer, offered );
1060
1061                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
1062                             in, out, 
1063                             qbuf, rbuf,
1064                             spoolss_io_q_enumjobs,
1065                             spoolss_io_r_enumjobs, 
1066                             WERR_GENERAL_FAILURE );
1067         }
1068
1069         if (!W_ERROR_IS_OK(out.status))
1070                 return out.status;
1071                 
1072         switch(level) {
1073         case 1:
1074                 if (!decode_jobs_1(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_1)) {
1075                         return WERR_GENERAL_FAILURE;
1076                 }
1077                 break;
1078         case 2:
1079                 if (!decode_jobs_2(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_2)) {
1080                         return WERR_GENERAL_FAILURE;
1081                 }
1082                 break;
1083         default:
1084                 DEBUG(3, ("unsupported info level %d", level));
1085                 return WERR_UNKNOWN_LEVEL;
1086         }
1087         
1088         *returned = out.returned;
1089
1090         return out.status;
1091 }
1092
1093 /**********************************************************************
1094 **********************************************************************/
1095
1096 WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1097                           POLICY_HND *hnd, uint32 jobid, uint32 level,
1098                           JOB_INFO_CTR *ctr)
1099 {
1100         prs_struct qbuf, rbuf;
1101         SPOOL_Q_GETJOB in;
1102         SPOOL_R_GETJOB out;
1103         RPC_BUFFER buffer;
1104         uint32 offered;
1105
1106         ZERO_STRUCT(in);
1107         ZERO_STRUCT(out);
1108
1109         offered = 0;
1110         if (!rpcbuf_init(&buffer, offered, mem_ctx))
1111                 return WERR_NOMEM;
1112         make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
1113
1114         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
1115                     in, out, 
1116                     qbuf, rbuf,
1117                     spoolss_io_q_getjob,
1118                     spoolss_io_r_getjob, 
1119                     WERR_GENERAL_FAILURE );
1120
1121         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1122                 offered = out.needed;
1123                 
1124                 ZERO_STRUCT(in);
1125                 ZERO_STRUCT(out);
1126                 
1127                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
1128                         return WERR_NOMEM;
1129                 make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
1130
1131                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
1132                             in, out, 
1133                             qbuf, rbuf,
1134                             spoolss_io_q_getjob,
1135                             spoolss_io_r_getjob, 
1136                             WERR_GENERAL_FAILURE );
1137         }
1138
1139         if (!W_ERROR_IS_OK(out.status))
1140                 return out.status;
1141
1142         switch(level) {
1143         case 1:
1144                 if (!decode_jobs_1(mem_ctx, out.buffer, 1, &ctr->job.job_info_1)) {
1145                         return WERR_GENERAL_FAILURE;
1146                 }
1147                 break;
1148         case 2:
1149                 if (!decode_jobs_2(mem_ctx, out.buffer, 1, &ctr->job.job_info_2)) {
1150                         return WERR_GENERAL_FAILURE;
1151                 }
1152                 break;
1153         default:
1154                 return WERR_UNKNOWN_LEVEL;
1155         }
1156
1157         return out.status;
1158 }
1159
1160 /**********************************************************************
1161 **********************************************************************/
1162
1163 WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1164                                   POLICY_HND *hnd, const char *valuename, 
1165                                   REGISTRY_VALUE *value)
1166 {
1167         prs_struct qbuf, rbuf;
1168         SPOOL_Q_GETPRINTERDATA in;
1169         SPOOL_R_GETPRINTERDATA out;
1170         uint32 offered;
1171
1172         ZERO_STRUCT(in);
1173         ZERO_STRUCT(out);
1174
1175         offered = 0;
1176         make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
1177
1178         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
1179                     in, out, 
1180                     qbuf, rbuf,
1181                     spoolss_io_q_getprinterdata,
1182                     spoolss_io_r_getprinterdata, 
1183                     WERR_GENERAL_FAILURE );
1184
1185         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1186                 offered = out.needed;
1187                 
1188                 ZERO_STRUCT(in);
1189                 ZERO_STRUCT(out);
1190                 
1191                 make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
1192
1193                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
1194                             in, out, 
1195                             qbuf, rbuf,
1196                             spoolss_io_q_getprinterdata,
1197                             spoolss_io_r_getprinterdata, 
1198                             WERR_GENERAL_FAILURE );
1199         }
1200
1201         if (!W_ERROR_IS_OK(out.status))
1202                 return out.status;      
1203
1204         /* Return output parameters */
1205
1206         if (out.needed) {
1207                 value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
1208         } else {
1209                 value->data_p = NULL;
1210         }
1211         value->type = out.type;
1212         value->size = out.size;
1213
1214         return out.status;
1215 }
1216
1217 /**********************************************************************
1218 **********************************************************************/
1219
1220 WERROR rpccli_spoolss_setprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1221                                   POLICY_HND *hnd, REGISTRY_VALUE *value)
1222 {
1223         prs_struct qbuf, rbuf;
1224         SPOOL_Q_SETPRINTERDATA in;
1225         SPOOL_R_SETPRINTERDATA out;
1226
1227         ZERO_STRUCT(in);
1228         ZERO_STRUCT(out);
1229
1230         make_spoolss_q_setprinterdata( &in, hnd, value->valuename, 
1231                 value->type, (char *)value->data_p, value->size);
1232
1233         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_SETPRINTERDATA,
1234                     in, out, 
1235                     qbuf, rbuf,
1236                     spoolss_io_q_setprinterdata,
1237                     spoolss_io_r_setprinterdata, 
1238                     WERR_GENERAL_FAILURE );
1239                     
1240         return out.status;
1241 }
1242
1243 /**********************************************************************
1244 **********************************************************************/
1245
1246 WERROR rpccli_spoolss_enumprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1247                                    POLICY_HND *hnd, uint32 ndx,
1248                                    uint32 value_offered, uint32 data_offered,
1249                                    uint32 *value_needed, uint32 *data_needed,
1250                                    REGISTRY_VALUE *value)
1251 {
1252         prs_struct qbuf, rbuf;
1253         SPOOL_Q_ENUMPRINTERDATA in;
1254         SPOOL_R_ENUMPRINTERDATA out;
1255
1256         ZERO_STRUCT(in);
1257         ZERO_STRUCT(out);
1258
1259         make_spoolss_q_enumprinterdata( &in, hnd, ndx, value_offered, data_offered );
1260
1261         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATA,
1262                     in, out, 
1263                     qbuf, rbuf,
1264                     spoolss_io_q_enumprinterdata,
1265                     spoolss_io_r_enumprinterdata, 
1266                     WERR_GENERAL_FAILURE );
1267
1268         if ( value_needed )
1269                 *value_needed = out.realvaluesize;
1270         if ( data_needed )
1271                 *data_needed = out.realdatasize;
1272                 
1273         if (!W_ERROR_IS_OK(out.status))
1274                 return out.status;
1275
1276         if (value) {
1277                 rpcstr_pull(value->valuename, out.value, sizeof(value->valuename), -1,
1278                             STR_TERMINATE);
1279                 if (out.realdatasize) {
1280                         value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data,
1281                                                        out.realdatasize);
1282                 } else {
1283                         value->data_p = NULL;
1284                 }
1285                 value->type = out.type;
1286                 value->size = out.realdatasize;
1287         }
1288         
1289         return out.status;
1290 }
1291
1292 /**********************************************************************
1293 **********************************************************************/
1294
1295 WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1296                                      POLICY_HND *hnd, const char *keyname, 
1297                                      REGVAL_CTR *ctr)
1298 {
1299         prs_struct qbuf, rbuf;
1300         SPOOL_Q_ENUMPRINTERDATAEX in;
1301         SPOOL_R_ENUMPRINTERDATAEX out;
1302         int i;
1303         uint32 offered;
1304
1305         ZERO_STRUCT(in);
1306         ZERO_STRUCT(out);
1307
1308         offered = 0;
1309         make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
1310
1311         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
1312                     in, out, 
1313                     qbuf, rbuf,
1314                     spoolss_io_q_enumprinterdataex,
1315                     spoolss_io_r_enumprinterdataex, 
1316                     WERR_GENERAL_FAILURE );
1317
1318         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1319                 offered = out.needed;
1320                 
1321                 ZERO_STRUCT(in);
1322                 ZERO_STRUCT(out);
1323                 
1324                 make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
1325
1326                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
1327                             in, out, 
1328                             qbuf, rbuf,
1329                             spoolss_io_q_enumprinterdataex,
1330                             spoolss_io_r_enumprinterdataex, 
1331                             WERR_GENERAL_FAILURE );
1332         }
1333         
1334         if (!W_ERROR_IS_OK(out.status))
1335                 return out.status;
1336
1337         for (i = 0; i < out.returned; i++) {
1338                 PRINTER_ENUM_VALUES *v = &out.ctr.values[i];
1339                 fstring name;
1340
1341                 rpcstr_pull(name, v->valuename.buffer, sizeof(name), -1, 
1342                             STR_TERMINATE);
1343                 regval_ctr_addvalue(ctr, name, v->type, (const char *)v->data, v->data_len);
1344         }
1345
1346         return out.status;
1347 }
1348
1349 /**********************************************************************
1350 **********************************************************************/
1351
1352 WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1353                                   POLICY_HND *hnd, const char *keyname,
1354                                   uint16 **keylist, uint32 *len)
1355 {
1356         prs_struct qbuf, rbuf;
1357         SPOOL_Q_ENUMPRINTERKEY in;
1358         SPOOL_R_ENUMPRINTERKEY out;
1359         uint32 offered = 0;
1360
1361         ZERO_STRUCT(in);
1362         ZERO_STRUCT(out);
1363
1364         make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
1365
1366         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
1367                     in, out, 
1368                     qbuf, rbuf,
1369                     spoolss_io_q_enumprinterkey,
1370                     spoolss_io_r_enumprinterkey, 
1371                     WERR_GENERAL_FAILURE );
1372
1373         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1374                 offered = out.needed;
1375                 
1376                 ZERO_STRUCT(in);
1377                 ZERO_STRUCT(out);
1378                 
1379                 make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
1380
1381                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
1382                             in, out, 
1383                             qbuf, rbuf,
1384                             spoolss_io_q_enumprinterkey,
1385                             spoolss_io_r_enumprinterkey, 
1386                             WERR_GENERAL_FAILURE );
1387         }
1388
1389         if ( !W_ERROR_IS_OK(out.status) )
1390                 return out.status;      
1391         
1392         if (keylist) {
1393                 *keylist = SMB_MALLOC_ARRAY(uint16, out.keys.buf_len);
1394                 if (!*keylist) {
1395                         return WERR_NOMEM;
1396                 }
1397                 memcpy(*keylist, out.keys.buffer, out.keys.buf_len * 2);
1398                 if (len)
1399                         *len = out.keys.buf_len * 2;
1400         }
1401
1402         return out.status;
1403 }
1404
1405 /** @} **/