s3-spoolss: remove unused decode_printer_info_7.
[ira/wip.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_port_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
366                         uint32 returned, PORT_INFO_1 **info)
367 {
368         uint32 i;
369         PORT_INFO_1 *inf;
370
371         if (returned) {
372                 inf=TALLOC_ARRAY(mem_ctx, PORT_INFO_1, returned);
373                 if (!inf) {
374                         return False;
375                 }
376                 memset(inf, 0, returned*sizeof(PORT_INFO_1));
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_port_info_1("", buffer, &(inf[i]), 0)) {
385                         return False;
386                 }
387         }
388
389         *info=inf;
390         return True;
391 }
392
393 /**********************************************************************
394 **********************************************************************/
395
396 static bool decode_port_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
397                         uint32 returned, PORT_INFO_2 **info)
398 {
399         uint32 i;
400         PORT_INFO_2 *inf;
401
402         if (returned) {
403                 inf=TALLOC_ARRAY(mem_ctx, PORT_INFO_2, returned);
404                 if (!inf) {
405                         return False;
406                 }
407                 memset(inf, 0, returned*sizeof(PORT_INFO_2));
408         } else {
409                 inf = NULL;
410         }
411
412         prs_set_offset(&buffer->prs, 0);
413
414         for (i=0; i<returned; i++) {
415                 if (!smb_io_port_info_2("", buffer, &(inf[i]), 0)) {
416                         return False;
417                 }
418         }
419
420         *info=inf;
421         return True;
422 }
423
424 /**********************************************************************
425 **********************************************************************/
426
427 static bool decode_printer_driver_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
428                         uint32 returned, DRIVER_INFO_1 **info)
429 {
430         uint32 i;
431         DRIVER_INFO_1 *inf;
432
433         if (returned) {
434                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_1, returned);
435                 if (!inf) {
436                         return False;
437                 }
438                 memset(inf, 0, returned*sizeof(DRIVER_INFO_1));
439         } else {
440                 inf = NULL;
441         }
442
443         prs_set_offset(&buffer->prs,0);
444
445         for (i=0; i<returned; i++) {
446                 if (!smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0)) {
447                         return False;
448                 }
449         }
450
451         *info=inf;
452         return True;
453 }
454
455 /**********************************************************************
456 **********************************************************************/
457
458 static bool decode_printer_driver_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
459                         uint32 returned, DRIVER_INFO_2 **info)
460 {
461         uint32 i;
462         DRIVER_INFO_2 *inf;
463
464         if (returned) {
465                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_2, returned);
466                 if (!inf) {
467                         return False;
468                 }
469                 memset(inf, 0, returned*sizeof(DRIVER_INFO_2));
470         } else {
471                 inf = NULL;
472         }
473
474         prs_set_offset(&buffer->prs,0);
475
476         for (i=0; i<returned; i++) {
477                 if (!smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0)) {
478                         return False;
479                 }
480         }
481
482         *info=inf;
483         return True;
484 }
485
486 /**********************************************************************
487 **********************************************************************/
488
489 static bool decode_printer_driver_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
490                         uint32 returned, DRIVER_INFO_3 **info)
491 {
492         uint32 i;
493         DRIVER_INFO_3 *inf;
494
495         if (returned) {
496                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_3, returned);
497                 if (!inf) {
498                         return False;
499                 }
500                 memset(inf, 0, returned*sizeof(DRIVER_INFO_3));
501         } else {
502                 inf = NULL;
503         }
504
505         prs_set_offset(&buffer->prs,0);
506
507         for (i=0; i<returned; i++) {
508                 if (!smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0)) {
509                         return False;
510                 }
511         }
512
513         *info=inf;
514         return True;
515 }
516
517 /**********************************************************************
518 **********************************************************************/
519
520 static bool decode_jobs_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
521                           uint32 num_jobs, JOB_INFO_1 **jobs)
522 {
523         uint32 i;
524
525         if (num_jobs) {
526                 *jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_1, num_jobs);
527                 if (*jobs == NULL) {
528                         return False;
529                 }
530         } else {
531                 *jobs = NULL;
532         }
533         prs_set_offset(&buffer->prs,0);
534
535         for (i = 0; i < num_jobs; i++) {
536                 if (!smb_io_job_info_1("", buffer, &((*jobs)[i]), 0)) {
537                         return False;
538                 }
539         }
540
541         return True;
542 }
543
544 /**********************************************************************
545 **********************************************************************/
546
547 static bool decode_jobs_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
548                           uint32 num_jobs, JOB_INFO_2 **jobs)
549 {
550         uint32 i;
551
552         if (num_jobs) {
553                 *jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_2, num_jobs);
554                 if (*jobs == NULL) {
555                         return False;
556                 }
557         } else {
558                 *jobs = NULL;
559         }
560         prs_set_offset(&buffer->prs,0);
561
562         for (i = 0; i < num_jobs; i++) {
563                 if (!smb_io_job_info_2("", buffer, &((*jobs)[i]), 0)) {
564                         return False;
565                 }
566         }
567
568         return True;
569 }
570
571 /**********************************************************************
572 **********************************************************************/
573
574 static bool decode_forms_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
575                            uint32 num_forms, FORM_1 **forms)
576 {
577         int i;
578
579         if (num_forms) {
580                 *forms = TALLOC_ARRAY(mem_ctx, FORM_1, num_forms);
581                 if (*forms == NULL) {
582                         return False;
583                 }
584         } else {
585                 *forms = NULL;
586         }
587
588         prs_set_offset(&buffer->prs,0);
589
590         for (i = 0; i < num_forms; i++) {
591                 if (!smb_io_form_1("", buffer, &((*forms)[i]), 0)) {
592                         return False;
593                 }
594         }
595
596         return True;
597 }
598
599 /**********************************************************************
600 **********************************************************************/
601
602 WERROR rpccli_spoolss_enum_printers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
603                                  char *name, uint32 flags, uint32 level,
604                                  uint32 *num_printers, PRINTER_INFO_CTR *ctr)
605 {
606         prs_struct qbuf, rbuf;
607         SPOOL_Q_ENUMPRINTERS in;
608         SPOOL_R_ENUMPRINTERS out;
609         RPC_BUFFER buffer;
610         uint32 offered;
611
612         ZERO_STRUCT(in);
613         ZERO_STRUCT(out);
614
615         offered = 0;
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         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
628                 offered = out.needed;
629                 
630                 ZERO_STRUCT(in);
631                 ZERO_STRUCT(out);
632
633                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
634                         return WERR_NOMEM;
635                 make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
636
637                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERS,
638                             in, out, 
639                             qbuf, rbuf,
640                             spoolss_io_q_enumprinters,
641                             spoolss_io_r_enumprinters, 
642                             WERR_GENERAL_FAILURE );
643         }
644
645         if ( !W_ERROR_IS_OK(out.status) )
646                 return out.status;
647
648         switch (level) {
649         case 0:
650                 if (!decode_printer_info_0(mem_ctx, out.buffer, out.returned, &ctr->printers_0)) {
651                         return WERR_GENERAL_FAILURE;
652                 }
653                 break;
654         case 1:
655                 if (!decode_printer_info_1(mem_ctx, out.buffer, out.returned, &ctr->printers_1)) {
656                         return WERR_GENERAL_FAILURE;
657                 }
658                 break;
659         case 2:
660                 if (!decode_printer_info_2(mem_ctx, out.buffer, out.returned, &ctr->printers_2)) {
661                         return WERR_GENERAL_FAILURE;
662                 }
663                 break;
664         case 3:
665                 if (!decode_printer_info_3(mem_ctx, out.buffer, out.returned, &ctr->printers_3)) {
666                         return WERR_GENERAL_FAILURE;
667                 }
668                 break;
669         default:
670                 return WERR_UNKNOWN_LEVEL;
671         }                       
672
673         *num_printers = out.returned;
674
675         return out.status;
676 }
677
678 /**********************************************************************
679 **********************************************************************/
680
681 WERROR rpccli_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
682                               uint32 level, uint32 *num_ports, PORT_INFO_CTR *ctr)
683 {
684         prs_struct qbuf, rbuf;
685         SPOOL_Q_ENUMPORTS in;
686         SPOOL_R_ENUMPORTS out;
687         RPC_BUFFER buffer;
688         fstring server;
689         uint32 offered;
690
691         ZERO_STRUCT(in);
692         ZERO_STRUCT(out);
693
694         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
695         strupper_m(server);
696
697         offered = 0;
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         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
710                 offered = out.needed;
711                 
712                 ZERO_STRUCT(in);
713                 ZERO_STRUCT(out);
714                 
715                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
716                         return WERR_NOMEM;
717                 make_spoolss_q_enumports( &in, server, level, &buffer, offered );
718
719                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPORTS,
720                             in, out, 
721                             qbuf, rbuf,
722                             spoolss_io_q_enumports,
723                             spoolss_io_r_enumports, 
724                             WERR_GENERAL_FAILURE );
725         }
726         
727         if ( !W_ERROR_IS_OK(out.status) )
728                 return out.status;
729         
730         switch (level) {
731         case 1:
732                 if (!decode_port_info_1(mem_ctx, out.buffer, out.returned, &ctr->port.info_1)) {
733                         return WERR_GENERAL_FAILURE;
734                 }
735                 break;
736         case 2:
737                 if (!decode_port_info_2(mem_ctx, out.buffer, out.returned, &ctr->port.info_2)) {
738                         return WERR_GENERAL_FAILURE;
739                 }
740                 break;
741         default:
742                 return WERR_UNKNOWN_LEVEL;
743         }
744
745         *num_ports = out.returned;
746
747         return out.status;
748 }
749
750 /**********************************************************************
751 **********************************************************************/
752
753 WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli, 
754                                        TALLOC_CTX *mem_ctx,
755                                        uint32 level, const char *env,
756                                        uint32 *num_drivers,
757                                        PRINTER_DRIVER_CTR *ctr)
758 {
759         prs_struct qbuf, rbuf;
760         SPOOL_Q_ENUMPRINTERDRIVERS in;
761         SPOOL_R_ENUMPRINTERDRIVERS out;
762         RPC_BUFFER buffer;
763         fstring server;
764         uint32 offered;
765
766         ZERO_STRUCT(in);
767         ZERO_STRUCT(out);
768
769         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
770         strupper_m(server);
771
772         offered = 0;
773         if (!rpcbuf_init(&buffer, offered, mem_ctx))
774                 return WERR_NOMEM;
775         make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
776                 &buffer, offered);
777         
778         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
779                     in, out, 
780                     qbuf, rbuf,
781                     spoolss_io_q_enumprinterdrivers,
782                     spoolss_io_r_enumprinterdrivers, 
783                     WERR_GENERAL_FAILURE );
784
785         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
786                 offered = out.needed;
787                 
788                 ZERO_STRUCT(in);
789                 ZERO_STRUCT(out);
790                 
791                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
792                         return WERR_NOMEM;
793                 make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
794                         &buffer, offered);
795         
796                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
797                             in, out, 
798                             qbuf, rbuf,
799                             spoolss_io_q_enumprinterdrivers,
800                             spoolss_io_r_enumprinterdrivers, 
801                             WERR_GENERAL_FAILURE );
802         }
803         
804         *num_drivers = out.returned;
805
806         if ( !W_ERROR_IS_OK(out.status) )
807                 return out.status;
808                 
809         if ( out.returned ) {
810
811                 switch (level) {
812                 case 1:
813                         if (!decode_printer_driver_1(mem_ctx, out.buffer, out.returned, &ctr->info1)) {
814                                 return WERR_GENERAL_FAILURE;
815                         }
816                         break;
817                 case 2:
818                         if (!decode_printer_driver_2(mem_ctx, out.buffer, out.returned, &ctr->info2)) {
819                                 return WERR_GENERAL_FAILURE;
820                         }
821                         break;
822                 case 3:
823                         if (!decode_printer_driver_3(mem_ctx, out.buffer, out.returned, &ctr->info3)) {
824                                 return WERR_GENERAL_FAILURE;
825                         }
826                         break;
827                 default:
828                         return WERR_UNKNOWN_LEVEL;
829                 }
830         }
831
832         return out.status;
833 }
834
835 /**********************************************************************
836 **********************************************************************/
837
838 WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
839                              POLICY_HND *handle, int level, uint32 *num_forms,
840                              FORM_1 **forms)
841 {
842         prs_struct qbuf, rbuf;
843         SPOOL_Q_ENUMFORMS in;
844         SPOOL_R_ENUMFORMS out;
845         RPC_BUFFER buffer;
846         uint32 offered;
847
848         ZERO_STRUCT(in);
849         ZERO_STRUCT(out);
850
851         offered = 0;
852         if (!rpcbuf_init(&buffer, offered, mem_ctx))
853                 return WERR_NOMEM;
854         make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
855
856         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
857                     in, out, 
858                     qbuf, rbuf,
859                     spoolss_io_q_enumforms,
860                     spoolss_io_r_enumforms, 
861                     WERR_GENERAL_FAILURE );
862
863         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
864                 offered = out.needed;
865                 
866                 ZERO_STRUCT(in);
867                 ZERO_STRUCT(out);
868
869                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
870                         return WERR_NOMEM;
871                 make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
872
873                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
874                             in, out, 
875                             qbuf, rbuf,
876                             spoolss_io_q_enumforms,
877                             spoolss_io_r_enumforms, 
878                             WERR_GENERAL_FAILURE );
879         }
880
881         if (!W_ERROR_IS_OK(out.status))
882                 return out.status;
883
884         *num_forms = out.numofforms;
885         
886         if (!decode_forms_1(mem_ctx, out.buffer, *num_forms, forms)) {
887                 return WERR_GENERAL_FAILURE;
888         }
889
890         return out.status;
891 }
892
893 /**********************************************************************
894 **********************************************************************/
895
896 WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
897                             POLICY_HND *hnd, uint32 level, uint32 firstjob, 
898                             uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr)
899 {
900         prs_struct qbuf, rbuf;
901         SPOOL_Q_ENUMJOBS in;
902         SPOOL_R_ENUMJOBS out;
903         RPC_BUFFER buffer;
904         uint32 offered;
905
906         ZERO_STRUCT(in);
907         ZERO_STRUCT(out);
908
909         offered = 0;
910         if (!rpcbuf_init(&buffer, offered, mem_ctx))
911                 return WERR_NOMEM;
912         make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
913                 &buffer, offered );
914
915         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
916                     in, out, 
917                     qbuf, rbuf,
918                     spoolss_io_q_enumjobs,
919                     spoolss_io_r_enumjobs, 
920                     WERR_GENERAL_FAILURE );
921
922         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
923                 offered = out.needed;
924                 
925                 ZERO_STRUCT(in);
926                 ZERO_STRUCT(out);
927
928                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
929                         return WERR_NOMEM;
930                 make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
931                         &buffer, offered );
932
933                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
934                             in, out, 
935                             qbuf, rbuf,
936                             spoolss_io_q_enumjobs,
937                             spoolss_io_r_enumjobs, 
938                             WERR_GENERAL_FAILURE );
939         }
940
941         if (!W_ERROR_IS_OK(out.status))
942                 return out.status;
943                 
944         switch(level) {
945         case 1:
946                 if (!decode_jobs_1(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_1)) {
947                         return WERR_GENERAL_FAILURE;
948                 }
949                 break;
950         case 2:
951                 if (!decode_jobs_2(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_2)) {
952                         return WERR_GENERAL_FAILURE;
953                 }
954                 break;
955         default:
956                 DEBUG(3, ("unsupported info level %d", level));
957                 return WERR_UNKNOWN_LEVEL;
958         }
959         
960         *returned = out.returned;
961
962         return out.status;
963 }
964
965 /**********************************************************************
966 **********************************************************************/
967
968 WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
969                           POLICY_HND *hnd, uint32 jobid, uint32 level,
970                           JOB_INFO_CTR *ctr)
971 {
972         prs_struct qbuf, rbuf;
973         SPOOL_Q_GETJOB in;
974         SPOOL_R_GETJOB out;
975         RPC_BUFFER buffer;
976         uint32 offered;
977
978         ZERO_STRUCT(in);
979         ZERO_STRUCT(out);
980
981         offered = 0;
982         if (!rpcbuf_init(&buffer, offered, mem_ctx))
983                 return WERR_NOMEM;
984         make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
985
986         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
987                     in, out, 
988                     qbuf, rbuf,
989                     spoolss_io_q_getjob,
990                     spoolss_io_r_getjob, 
991                     WERR_GENERAL_FAILURE );
992
993         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
994                 offered = out.needed;
995                 
996                 ZERO_STRUCT(in);
997                 ZERO_STRUCT(out);
998                 
999                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
1000                         return WERR_NOMEM;
1001                 make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
1002
1003                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
1004                             in, out, 
1005                             qbuf, rbuf,
1006                             spoolss_io_q_getjob,
1007                             spoolss_io_r_getjob, 
1008                             WERR_GENERAL_FAILURE );
1009         }
1010
1011         if (!W_ERROR_IS_OK(out.status))
1012                 return out.status;
1013
1014         switch(level) {
1015         case 1:
1016                 if (!decode_jobs_1(mem_ctx, out.buffer, 1, &ctr->job.job_info_1)) {
1017                         return WERR_GENERAL_FAILURE;
1018                 }
1019                 break;
1020         case 2:
1021                 if (!decode_jobs_2(mem_ctx, out.buffer, 1, &ctr->job.job_info_2)) {
1022                         return WERR_GENERAL_FAILURE;
1023                 }
1024                 break;
1025         default:
1026                 return WERR_UNKNOWN_LEVEL;
1027         }
1028
1029         return out.status;
1030 }
1031
1032 /**********************************************************************
1033 **********************************************************************/
1034
1035 WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1036                                   POLICY_HND *hnd, const char *valuename, 
1037                                   REGISTRY_VALUE *value)
1038 {
1039         prs_struct qbuf, rbuf;
1040         SPOOL_Q_GETPRINTERDATA in;
1041         SPOOL_R_GETPRINTERDATA out;
1042         uint32 offered;
1043
1044         ZERO_STRUCT(in);
1045         ZERO_STRUCT(out);
1046
1047         offered = 0;
1048         make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
1049
1050         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
1051                     in, out, 
1052                     qbuf, rbuf,
1053                     spoolss_io_q_getprinterdata,
1054                     spoolss_io_r_getprinterdata, 
1055                     WERR_GENERAL_FAILURE );
1056
1057         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1058                 offered = out.needed;
1059                 
1060                 ZERO_STRUCT(in);
1061                 ZERO_STRUCT(out);
1062                 
1063                 make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
1064
1065                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
1066                             in, out, 
1067                             qbuf, rbuf,
1068                             spoolss_io_q_getprinterdata,
1069                             spoolss_io_r_getprinterdata, 
1070                             WERR_GENERAL_FAILURE );
1071         }
1072
1073         if (!W_ERROR_IS_OK(out.status))
1074                 return out.status;      
1075
1076         /* Return output parameters */
1077
1078         if (out.needed) {
1079                 value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
1080         } else {
1081                 value->data_p = NULL;
1082         }
1083         value->type = out.type;
1084         value->size = out.size;
1085
1086         return out.status;
1087 }
1088
1089 /**********************************************************************
1090 **********************************************************************/
1091
1092 WERROR rpccli_spoolss_setprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1093                                   POLICY_HND *hnd, REGISTRY_VALUE *value)
1094 {
1095         prs_struct qbuf, rbuf;
1096         SPOOL_Q_SETPRINTERDATA in;
1097         SPOOL_R_SETPRINTERDATA out;
1098
1099         ZERO_STRUCT(in);
1100         ZERO_STRUCT(out);
1101
1102         make_spoolss_q_setprinterdata( &in, hnd, value->valuename, 
1103                 value->type, (char *)value->data_p, value->size);
1104
1105         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_SETPRINTERDATA,
1106                     in, out, 
1107                     qbuf, rbuf,
1108                     spoolss_io_q_setprinterdata,
1109                     spoolss_io_r_setprinterdata, 
1110                     WERR_GENERAL_FAILURE );
1111                     
1112         return out.status;
1113 }
1114
1115 /**********************************************************************
1116 **********************************************************************/
1117
1118 WERROR rpccli_spoolss_enumprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1119                                    POLICY_HND *hnd, uint32 ndx,
1120                                    uint32 value_offered, uint32 data_offered,
1121                                    uint32 *value_needed, uint32 *data_needed,
1122                                    REGISTRY_VALUE *value)
1123 {
1124         prs_struct qbuf, rbuf;
1125         SPOOL_Q_ENUMPRINTERDATA in;
1126         SPOOL_R_ENUMPRINTERDATA out;
1127
1128         ZERO_STRUCT(in);
1129         ZERO_STRUCT(out);
1130
1131         make_spoolss_q_enumprinterdata( &in, hnd, ndx, value_offered, data_offered );
1132
1133         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATA,
1134                     in, out, 
1135                     qbuf, rbuf,
1136                     spoolss_io_q_enumprinterdata,
1137                     spoolss_io_r_enumprinterdata, 
1138                     WERR_GENERAL_FAILURE );
1139
1140         if ( value_needed )
1141                 *value_needed = out.realvaluesize;
1142         if ( data_needed )
1143                 *data_needed = out.realdatasize;
1144                 
1145         if (!W_ERROR_IS_OK(out.status))
1146                 return out.status;
1147
1148         if (value) {
1149                 rpcstr_pull(value->valuename, out.value, sizeof(value->valuename), -1,
1150                             STR_TERMINATE);
1151                 if (out.realdatasize) {
1152                         value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data,
1153                                                        out.realdatasize);
1154                 } else {
1155                         value->data_p = NULL;
1156                 }
1157                 value->type = out.type;
1158                 value->size = out.realdatasize;
1159         }
1160         
1161         return out.status;
1162 }
1163
1164 /**********************************************************************
1165 **********************************************************************/
1166
1167 WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1168                                      POLICY_HND *hnd, const char *keyname, 
1169                                      REGVAL_CTR *ctr)
1170 {
1171         prs_struct qbuf, rbuf;
1172         SPOOL_Q_ENUMPRINTERDATAEX in;
1173         SPOOL_R_ENUMPRINTERDATAEX out;
1174         int i;
1175         uint32 offered;
1176
1177         ZERO_STRUCT(in);
1178         ZERO_STRUCT(out);
1179
1180         offered = 0;
1181         make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
1182
1183         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
1184                     in, out, 
1185                     qbuf, rbuf,
1186                     spoolss_io_q_enumprinterdataex,
1187                     spoolss_io_r_enumprinterdataex, 
1188                     WERR_GENERAL_FAILURE );
1189
1190         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1191                 offered = out.needed;
1192                 
1193                 ZERO_STRUCT(in);
1194                 ZERO_STRUCT(out);
1195                 
1196                 make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
1197
1198                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
1199                             in, out, 
1200                             qbuf, rbuf,
1201                             spoolss_io_q_enumprinterdataex,
1202                             spoolss_io_r_enumprinterdataex, 
1203                             WERR_GENERAL_FAILURE );
1204         }
1205         
1206         if (!W_ERROR_IS_OK(out.status))
1207                 return out.status;
1208
1209         for (i = 0; i < out.returned; i++) {
1210                 PRINTER_ENUM_VALUES *v = &out.ctr.values[i];
1211                 fstring name;
1212
1213                 rpcstr_pull(name, v->valuename.buffer, sizeof(name), -1, 
1214                             STR_TERMINATE);
1215                 regval_ctr_addvalue(ctr, name, v->type, (const char *)v->data, v->data_len);
1216         }
1217
1218         return out.status;
1219 }
1220
1221 /**********************************************************************
1222 **********************************************************************/
1223
1224 WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1225                                   POLICY_HND *hnd, const char *keyname,
1226                                   uint16 **keylist, uint32 *len)
1227 {
1228         prs_struct qbuf, rbuf;
1229         SPOOL_Q_ENUMPRINTERKEY in;
1230         SPOOL_R_ENUMPRINTERKEY out;
1231         uint32 offered = 0;
1232
1233         ZERO_STRUCT(in);
1234         ZERO_STRUCT(out);
1235
1236         make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
1237
1238         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
1239                     in, out, 
1240                     qbuf, rbuf,
1241                     spoolss_io_q_enumprinterkey,
1242                     spoolss_io_r_enumprinterkey, 
1243                     WERR_GENERAL_FAILURE );
1244
1245         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1246                 offered = out.needed;
1247                 
1248                 ZERO_STRUCT(in);
1249                 ZERO_STRUCT(out);
1250                 
1251                 make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
1252
1253                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
1254                             in, out, 
1255                             qbuf, rbuf,
1256                             spoolss_io_q_enumprinterkey,
1257                             spoolss_io_r_enumprinterkey, 
1258                             WERR_GENERAL_FAILURE );
1259         }
1260
1261         if ( !W_ERROR_IS_OK(out.status) )
1262                 return out.status;      
1263         
1264         if (keylist) {
1265                 *keylist = SMB_MALLOC_ARRAY(uint16, out.keys.buf_len);
1266                 if (!*keylist) {
1267                         return WERR_NOMEM;
1268                 }
1269                 memcpy(*keylist, out.keys.buffer, out.keys.buf_len * 2);
1270                 if (len)
1271                         *len = out.keys.buf_len * 2;
1272         }
1273
1274         return out.status;
1275 }
1276 /** @} **/