c9d23efdf26513816666546fbaacc94b97b0506f
[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_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_enumprinterdrivers (struct rpc_pipe_client *cli, 
786                                        TALLOC_CTX *mem_ctx,
787                                        uint32 level, const char *env,
788                                        uint32 *num_drivers,
789                                        PRINTER_DRIVER_CTR *ctr)
790 {
791         prs_struct qbuf, rbuf;
792         SPOOL_Q_ENUMPRINTERDRIVERS in;
793         SPOOL_R_ENUMPRINTERDRIVERS out;
794         RPC_BUFFER buffer;
795         fstring server;
796         uint32 offered;
797
798         ZERO_STRUCT(in);
799         ZERO_STRUCT(out);
800
801         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
802         strupper_m(server);
803
804         offered = 0;
805         if (!rpcbuf_init(&buffer, offered, mem_ctx))
806                 return WERR_NOMEM;
807         make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
808                 &buffer, offered);
809         
810         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
811                     in, out, 
812                     qbuf, rbuf,
813                     spoolss_io_q_enumprinterdrivers,
814                     spoolss_io_r_enumprinterdrivers, 
815                     WERR_GENERAL_FAILURE );
816
817         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
818                 offered = out.needed;
819                 
820                 ZERO_STRUCT(in);
821                 ZERO_STRUCT(out);
822                 
823                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
824                         return WERR_NOMEM;
825                 make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
826                         &buffer, offered);
827         
828                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
829                             in, out, 
830                             qbuf, rbuf,
831                             spoolss_io_q_enumprinterdrivers,
832                             spoolss_io_r_enumprinterdrivers, 
833                             WERR_GENERAL_FAILURE );
834         }
835         
836         *num_drivers = out.returned;
837
838         if ( !W_ERROR_IS_OK(out.status) )
839                 return out.status;
840                 
841         if ( out.returned ) {
842
843                 switch (level) {
844                 case 1:
845                         if (!decode_printer_driver_1(mem_ctx, out.buffer, out.returned, &ctr->info1)) {
846                                 return WERR_GENERAL_FAILURE;
847                         }
848                         break;
849                 case 2:
850                         if (!decode_printer_driver_2(mem_ctx, out.buffer, out.returned, &ctr->info2)) {
851                                 return WERR_GENERAL_FAILURE;
852                         }
853                         break;
854                 case 3:
855                         if (!decode_printer_driver_3(mem_ctx, out.buffer, out.returned, &ctr->info3)) {
856                                 return WERR_GENERAL_FAILURE;
857                         }
858                         break;
859                 default:
860                         return WERR_UNKNOWN_LEVEL;
861                 }
862         }
863
864         return out.status;
865 }
866
867 /**********************************************************************
868 **********************************************************************/
869
870 WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
871                              POLICY_HND *handle, int level, uint32 *num_forms,
872                              FORM_1 **forms)
873 {
874         prs_struct qbuf, rbuf;
875         SPOOL_Q_ENUMFORMS in;
876         SPOOL_R_ENUMFORMS out;
877         RPC_BUFFER buffer;
878         uint32 offered;
879
880         ZERO_STRUCT(in);
881         ZERO_STRUCT(out);
882
883         offered = 0;
884         if (!rpcbuf_init(&buffer, offered, mem_ctx))
885                 return WERR_NOMEM;
886         make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
887
888         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
889                     in, out, 
890                     qbuf, rbuf,
891                     spoolss_io_q_enumforms,
892                     spoolss_io_r_enumforms, 
893                     WERR_GENERAL_FAILURE );
894
895         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
896                 offered = out.needed;
897                 
898                 ZERO_STRUCT(in);
899                 ZERO_STRUCT(out);
900
901                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
902                         return WERR_NOMEM;
903                 make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
904
905                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
906                             in, out, 
907                             qbuf, rbuf,
908                             spoolss_io_q_enumforms,
909                             spoolss_io_r_enumforms, 
910                             WERR_GENERAL_FAILURE );
911         }
912
913         if (!W_ERROR_IS_OK(out.status))
914                 return out.status;
915
916         *num_forms = out.numofforms;
917         
918         if (!decode_forms_1(mem_ctx, out.buffer, *num_forms, forms)) {
919                 return WERR_GENERAL_FAILURE;
920         }
921
922         return out.status;
923 }
924
925 /**********************************************************************
926 **********************************************************************/
927
928 WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
929                             POLICY_HND *hnd, uint32 level, uint32 firstjob, 
930                             uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr)
931 {
932         prs_struct qbuf, rbuf;
933         SPOOL_Q_ENUMJOBS in;
934         SPOOL_R_ENUMJOBS out;
935         RPC_BUFFER buffer;
936         uint32 offered;
937
938         ZERO_STRUCT(in);
939         ZERO_STRUCT(out);
940
941         offered = 0;
942         if (!rpcbuf_init(&buffer, offered, mem_ctx))
943                 return WERR_NOMEM;
944         make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
945                 &buffer, offered );
946
947         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
948                     in, out, 
949                     qbuf, rbuf,
950                     spoolss_io_q_enumjobs,
951                     spoolss_io_r_enumjobs, 
952                     WERR_GENERAL_FAILURE );
953
954         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
955                 offered = out.needed;
956                 
957                 ZERO_STRUCT(in);
958                 ZERO_STRUCT(out);
959
960                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
961                         return WERR_NOMEM;
962                 make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
963                         &buffer, offered );
964
965                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
966                             in, out, 
967                             qbuf, rbuf,
968                             spoolss_io_q_enumjobs,
969                             spoolss_io_r_enumjobs, 
970                             WERR_GENERAL_FAILURE );
971         }
972
973         if (!W_ERROR_IS_OK(out.status))
974                 return out.status;
975                 
976         switch(level) {
977         case 1:
978                 if (!decode_jobs_1(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_1)) {
979                         return WERR_GENERAL_FAILURE;
980                 }
981                 break;
982         case 2:
983                 if (!decode_jobs_2(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_2)) {
984                         return WERR_GENERAL_FAILURE;
985                 }
986                 break;
987         default:
988                 DEBUG(3, ("unsupported info level %d", level));
989                 return WERR_UNKNOWN_LEVEL;
990         }
991         
992         *returned = out.returned;
993
994         return out.status;
995 }
996
997 /**********************************************************************
998 **********************************************************************/
999
1000 WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1001                           POLICY_HND *hnd, uint32 jobid, uint32 level,
1002                           JOB_INFO_CTR *ctr)
1003 {
1004         prs_struct qbuf, rbuf;
1005         SPOOL_Q_GETJOB in;
1006         SPOOL_R_GETJOB out;
1007         RPC_BUFFER buffer;
1008         uint32 offered;
1009
1010         ZERO_STRUCT(in);
1011         ZERO_STRUCT(out);
1012
1013         offered = 0;
1014         if (!rpcbuf_init(&buffer, offered, mem_ctx))
1015                 return WERR_NOMEM;
1016         make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
1017
1018         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
1019                     in, out, 
1020                     qbuf, rbuf,
1021                     spoolss_io_q_getjob,
1022                     spoolss_io_r_getjob, 
1023                     WERR_GENERAL_FAILURE );
1024
1025         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1026                 offered = out.needed;
1027                 
1028                 ZERO_STRUCT(in);
1029                 ZERO_STRUCT(out);
1030                 
1031                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
1032                         return WERR_NOMEM;
1033                 make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
1034
1035                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
1036                             in, out, 
1037                             qbuf, rbuf,
1038                             spoolss_io_q_getjob,
1039                             spoolss_io_r_getjob, 
1040                             WERR_GENERAL_FAILURE );
1041         }
1042
1043         if (!W_ERROR_IS_OK(out.status))
1044                 return out.status;
1045
1046         switch(level) {
1047         case 1:
1048                 if (!decode_jobs_1(mem_ctx, out.buffer, 1, &ctr->job.job_info_1)) {
1049                         return WERR_GENERAL_FAILURE;
1050                 }
1051                 break;
1052         case 2:
1053                 if (!decode_jobs_2(mem_ctx, out.buffer, 1, &ctr->job.job_info_2)) {
1054                         return WERR_GENERAL_FAILURE;
1055                 }
1056                 break;
1057         default:
1058                 return WERR_UNKNOWN_LEVEL;
1059         }
1060
1061         return out.status;
1062 }
1063
1064 /**********************************************************************
1065 **********************************************************************/
1066
1067 WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1068                                   POLICY_HND *hnd, const char *valuename, 
1069                                   REGISTRY_VALUE *value)
1070 {
1071         prs_struct qbuf, rbuf;
1072         SPOOL_Q_GETPRINTERDATA in;
1073         SPOOL_R_GETPRINTERDATA out;
1074         uint32 offered;
1075
1076         ZERO_STRUCT(in);
1077         ZERO_STRUCT(out);
1078
1079         offered = 0;
1080         make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
1081
1082         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
1083                     in, out, 
1084                     qbuf, rbuf,
1085                     spoolss_io_q_getprinterdata,
1086                     spoolss_io_r_getprinterdata, 
1087                     WERR_GENERAL_FAILURE );
1088
1089         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1090                 offered = out.needed;
1091                 
1092                 ZERO_STRUCT(in);
1093                 ZERO_STRUCT(out);
1094                 
1095                 make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
1096
1097                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
1098                             in, out, 
1099                             qbuf, rbuf,
1100                             spoolss_io_q_getprinterdata,
1101                             spoolss_io_r_getprinterdata, 
1102                             WERR_GENERAL_FAILURE );
1103         }
1104
1105         if (!W_ERROR_IS_OK(out.status))
1106                 return out.status;      
1107
1108         /* Return output parameters */
1109
1110         if (out.needed) {
1111                 value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
1112         } else {
1113                 value->data_p = NULL;
1114         }
1115         value->type = out.type;
1116         value->size = out.size;
1117
1118         return out.status;
1119 }
1120
1121 /**********************************************************************
1122 **********************************************************************/
1123
1124 WERROR rpccli_spoolss_setprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1125                                   POLICY_HND *hnd, REGISTRY_VALUE *value)
1126 {
1127         prs_struct qbuf, rbuf;
1128         SPOOL_Q_SETPRINTERDATA in;
1129         SPOOL_R_SETPRINTERDATA out;
1130
1131         ZERO_STRUCT(in);
1132         ZERO_STRUCT(out);
1133
1134         make_spoolss_q_setprinterdata( &in, hnd, value->valuename, 
1135                 value->type, (char *)value->data_p, value->size);
1136
1137         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_SETPRINTERDATA,
1138                     in, out, 
1139                     qbuf, rbuf,
1140                     spoolss_io_q_setprinterdata,
1141                     spoolss_io_r_setprinterdata, 
1142                     WERR_GENERAL_FAILURE );
1143                     
1144         return out.status;
1145 }
1146
1147 /**********************************************************************
1148 **********************************************************************/
1149
1150 WERROR rpccli_spoolss_enumprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1151                                    POLICY_HND *hnd, uint32 ndx,
1152                                    uint32 value_offered, uint32 data_offered,
1153                                    uint32 *value_needed, uint32 *data_needed,
1154                                    REGISTRY_VALUE *value)
1155 {
1156         prs_struct qbuf, rbuf;
1157         SPOOL_Q_ENUMPRINTERDATA in;
1158         SPOOL_R_ENUMPRINTERDATA out;
1159
1160         ZERO_STRUCT(in);
1161         ZERO_STRUCT(out);
1162
1163         make_spoolss_q_enumprinterdata( &in, hnd, ndx, value_offered, data_offered );
1164
1165         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATA,
1166                     in, out, 
1167                     qbuf, rbuf,
1168                     spoolss_io_q_enumprinterdata,
1169                     spoolss_io_r_enumprinterdata, 
1170                     WERR_GENERAL_FAILURE );
1171
1172         if ( value_needed )
1173                 *value_needed = out.realvaluesize;
1174         if ( data_needed )
1175                 *data_needed = out.realdatasize;
1176                 
1177         if (!W_ERROR_IS_OK(out.status))
1178                 return out.status;
1179
1180         if (value) {
1181                 rpcstr_pull(value->valuename, out.value, sizeof(value->valuename), -1,
1182                             STR_TERMINATE);
1183                 if (out.realdatasize) {
1184                         value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data,
1185                                                        out.realdatasize);
1186                 } else {
1187                         value->data_p = NULL;
1188                 }
1189                 value->type = out.type;
1190                 value->size = out.realdatasize;
1191         }
1192         
1193         return out.status;
1194 }
1195
1196 /**********************************************************************
1197 **********************************************************************/
1198
1199 WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1200                                      POLICY_HND *hnd, const char *keyname, 
1201                                      REGVAL_CTR *ctr)
1202 {
1203         prs_struct qbuf, rbuf;
1204         SPOOL_Q_ENUMPRINTERDATAEX in;
1205         SPOOL_R_ENUMPRINTERDATAEX out;
1206         int i;
1207         uint32 offered;
1208
1209         ZERO_STRUCT(in);
1210         ZERO_STRUCT(out);
1211
1212         offered = 0;
1213         make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
1214
1215         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
1216                     in, out, 
1217                     qbuf, rbuf,
1218                     spoolss_io_q_enumprinterdataex,
1219                     spoolss_io_r_enumprinterdataex, 
1220                     WERR_GENERAL_FAILURE );
1221
1222         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1223                 offered = out.needed;
1224                 
1225                 ZERO_STRUCT(in);
1226                 ZERO_STRUCT(out);
1227                 
1228                 make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
1229
1230                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
1231                             in, out, 
1232                             qbuf, rbuf,
1233                             spoolss_io_q_enumprinterdataex,
1234                             spoolss_io_r_enumprinterdataex, 
1235                             WERR_GENERAL_FAILURE );
1236         }
1237         
1238         if (!W_ERROR_IS_OK(out.status))
1239                 return out.status;
1240
1241         for (i = 0; i < out.returned; i++) {
1242                 PRINTER_ENUM_VALUES *v = &out.ctr.values[i];
1243                 fstring name;
1244
1245                 rpcstr_pull(name, v->valuename.buffer, sizeof(name), -1, 
1246                             STR_TERMINATE);
1247                 regval_ctr_addvalue(ctr, name, v->type, (const char *)v->data, v->data_len);
1248         }
1249
1250         return out.status;
1251 }
1252
1253 /**********************************************************************
1254 **********************************************************************/
1255
1256 WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1257                                   POLICY_HND *hnd, const char *keyname,
1258                                   uint16 **keylist, uint32 *len)
1259 {
1260         prs_struct qbuf, rbuf;
1261         SPOOL_Q_ENUMPRINTERKEY in;
1262         SPOOL_R_ENUMPRINTERKEY out;
1263         uint32 offered = 0;
1264
1265         ZERO_STRUCT(in);
1266         ZERO_STRUCT(out);
1267
1268         make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
1269
1270         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
1271                     in, out, 
1272                     qbuf, rbuf,
1273                     spoolss_io_q_enumprinterkey,
1274                     spoolss_io_r_enumprinterkey, 
1275                     WERR_GENERAL_FAILURE );
1276
1277         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1278                 offered = out.needed;
1279                 
1280                 ZERO_STRUCT(in);
1281                 ZERO_STRUCT(out);
1282                 
1283                 make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
1284
1285                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
1286                             in, out, 
1287                             qbuf, rbuf,
1288                             spoolss_io_q_enumprinterkey,
1289                             spoolss_io_r_enumprinterkey, 
1290                             WERR_GENERAL_FAILURE );
1291         }
1292
1293         if ( !W_ERROR_IS_OK(out.status) )
1294                 return out.status;      
1295         
1296         if (keylist) {
1297                 *keylist = SMB_MALLOC_ARRAY(uint16, out.keys.buf_len);
1298                 if (!*keylist) {
1299                         return WERR_NOMEM;
1300                 }
1301                 memcpy(*keylist, out.keys.buffer, out.keys.buf_len * 2);
1302                 if (len)
1303                         *len = out.keys.buf_len * 2;
1304         }
1305
1306         return out.status;
1307 }
1308 /** @} **/