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