s3-spoolss: remove old rpccli_spoolss_getjob.
[kai/samba.git] / source3 / rpc_client / cli_spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Gerald Carter                2001-2005,
6    Copyright (C) Tim Potter                   2000-2002,
7    Copyright (C) Andrew Tridgell              1994-2000,
8    Copyright (C) Jean-Francois Micouleau      1999-2000.
9    Copyright (C) Jeremy Allison                         2005.
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "rpc_client.h"
27
28 /**********************************************************************
29  convencience wrapper around rpccli_spoolss_OpenPrinterEx
30 **********************************************************************/
31
32 WERROR rpccli_spoolss_openprinter_ex(struct rpc_pipe_client *cli,
33                                      TALLOC_CTX *mem_ctx,
34                                      const char *printername,
35                                      uint32_t access_desired,
36                                      struct policy_handle *handle)
37 {
38         NTSTATUS status;
39         WERROR werror;
40         struct spoolss_DevmodeContainer devmode_ctr;
41         union spoolss_UserLevel userlevel;
42         struct spoolss_UserLevel1 level1;
43
44         ZERO_STRUCT(devmode_ctr);
45
46         level1.size     = 28;
47         level1.client   = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
48         W_ERROR_HAVE_NO_MEMORY(level1.client);
49         level1.user     = cli->auth->user_name;
50         level1.build    = 1381;
51         level1.major    = 2;
52         level1.minor    = 0;
53         level1.processor = 0;
54
55         userlevel.level1 = &level1;
56
57         status = rpccli_spoolss_OpenPrinterEx(cli, mem_ctx,
58                                               printername,
59                                               NULL,
60                                               devmode_ctr,
61                                               access_desired,
62                                               1, /* level */
63                                               userlevel,
64                                               handle,
65                                               &werror);
66
67         if (!W_ERROR_IS_OK(werror)) {
68                 return werror;
69         }
70
71         if (!NT_STATUS_IS_OK(status)) {
72                 return ntstatus_to_werror(status);
73         }
74
75         return WERR_OK;
76 }
77
78 /**********************************************************************
79  convencience wrapper around rpccli_spoolss_GetPrinterDriver2
80 **********************************************************************/
81
82 WERROR rpccli_spoolss_getprinterdriver2(struct rpc_pipe_client *cli,
83                                         TALLOC_CTX *mem_ctx,
84                                         struct policy_handle *handle,
85                                         const char *architecture,
86                                         uint32_t level,
87                                         uint32_t offered,
88                                         uint32_t client_major_version,
89                                         uint32_t client_minor_version,
90                                         union spoolss_DriverInfo *info,
91                                         uint32_t *server_major_version,
92                                         uint32_t *server_minor_version)
93 {
94         NTSTATUS status;
95         WERROR werror;
96         uint32_t needed;
97         DATA_BLOB buffer;
98
99         if (offered > 0) {
100                 buffer = data_blob_talloc_zero(mem_ctx, offered);
101                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
102         }
103
104         status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
105                                                   handle,
106                                                   architecture,
107                                                   level,
108                                                   (offered > 0) ? &buffer : NULL,
109                                                   offered,
110                                                   client_major_version,
111                                                   client_minor_version,
112                                                   info,
113                                                   &needed,
114                                                   server_major_version,
115                                                   server_minor_version,
116                                                   &werror);
117         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
118                 offered = needed;
119                 buffer = data_blob_talloc_zero(mem_ctx, needed);
120                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
121
122                 status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
123                                                           handle,
124                                                           architecture,
125                                                           level,
126                                                           &buffer,
127                                                           offered,
128                                                           client_major_version,
129                                                           client_minor_version,
130                                                           info,
131                                                           &needed,
132                                                           server_major_version,
133                                                           server_minor_version,
134                                                           &werror);
135         }
136
137         return werror;
138 }
139
140 /**********************************************************************
141  convencience wrapper around rpccli_spoolss_AddPrinterEx
142 **********************************************************************/
143
144 WERROR rpccli_spoolss_addprinterex(struct rpc_pipe_client *cli,
145                                    TALLOC_CTX *mem_ctx,
146                                    struct spoolss_SetPrinterInfoCtr *info_ctr)
147 {
148         WERROR result;
149         NTSTATUS status;
150         struct spoolss_DevmodeContainer devmode_ctr;
151         struct sec_desc_buf secdesc_ctr;
152         struct spoolss_UserLevelCtr userlevel_ctr;
153         struct spoolss_UserLevel1 level1;
154         struct policy_handle handle;
155
156         ZERO_STRUCT(devmode_ctr);
157         ZERO_STRUCT(secdesc_ctr);
158
159         level1.size             = 28;
160         level1.build            = 1381;
161         level1.major            = 2;
162         level1.minor            = 0;
163         level1.processor        = 0;
164         level1.client           = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
165         W_ERROR_HAVE_NO_MEMORY(level1.client);
166         level1.user             = cli->auth->user_name;
167
168         userlevel_ctr.level = 1;
169         userlevel_ctr.user_info.level1 = &level1;
170
171         status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx,
172                                              cli->srv_name_slash,
173                                              info_ctr,
174                                              &devmode_ctr,
175                                              &secdesc_ctr,
176                                              &userlevel_ctr,
177                                              &handle,
178                                              &result);
179         return result;
180 }
181
182 /**********************************************************************
183  convencience wrapper around rpccli_spoolss_GetPrinter
184 **********************************************************************/
185
186 WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli,
187                                  TALLOC_CTX *mem_ctx,
188                                  struct policy_handle *handle,
189                                  uint32_t level,
190                                  uint32_t offered,
191                                  union spoolss_PrinterInfo *info)
192 {
193         NTSTATUS status;
194         WERROR werror;
195         DATA_BLOB buffer;
196         uint32_t needed;
197
198         if (offered > 0) {
199                 buffer = data_blob_talloc_zero(mem_ctx, offered);
200                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
201         }
202
203         status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
204                                            handle,
205                                            level,
206                                            (offered > 0) ? &buffer : NULL,
207                                            offered,
208                                            info,
209                                            &needed,
210                                            &werror);
211
212         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
213
214                 offered = needed;
215                 buffer = data_blob_talloc_zero(mem_ctx, offered);
216                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
217
218                 status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
219                                                    handle,
220                                                    level,
221                                                    &buffer,
222                                                    offered,
223                                                    info,
224                                                    &needed,
225                                                    &werror);
226         }
227
228         return werror;
229 }
230
231 /**********************************************************************
232  convencience wrapper around rpccli_spoolss_GetJob
233 **********************************************************************/
234
235 WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli,
236                              TALLOC_CTX *mem_ctx,
237                              struct policy_handle *handle,
238                              uint32_t job_id,
239                              uint32_t level,
240                              uint32_t offered,
241                              union spoolss_JobInfo *info)
242 {
243         NTSTATUS status;
244         WERROR werror;
245         uint32_t needed;
246         DATA_BLOB buffer;
247
248         if (offered > 0) {
249                 buffer = data_blob_talloc_zero(mem_ctx, offered);
250                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
251         }
252
253         status = rpccli_spoolss_GetJob(cli, mem_ctx,
254                                        handle,
255                                        job_id,
256                                        level,
257                                        (offered > 0) ? &buffer : NULL,
258                                        offered,
259                                        info,
260                                        &needed,
261                                        &werror);
262
263         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
264                 offered = needed;
265                 buffer = data_blob_talloc_zero(mem_ctx, needed);
266                 W_ERROR_HAVE_NO_MEMORY(buffer.data);
267
268                 status = rpccli_spoolss_GetJob(cli, mem_ctx,
269                                                handle,
270                                                job_id,
271                                                level,
272                                                &buffer,
273                                                offered,
274                                                info,
275                                                &needed,
276                                                &werror);
277         }
278
279         return werror;
280 }
281
282
283 /*********************************************************************
284  Decode various spoolss rpc's and info levels
285  ********************************************************************/
286
287 /**********************************************************************
288 **********************************************************************/
289
290 static bool decode_printer_info_0(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
291                                 uint32 returned, PRINTER_INFO_0 **info)
292 {
293         uint32 i;
294         PRINTER_INFO_0  *inf;
295
296         if (returned) {
297                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_0, returned);
298                 if (!inf) {
299                         return False;
300                 }
301                 memset(inf, 0, returned*sizeof(PRINTER_INFO_0));
302         } else {
303                 inf = NULL;
304         }
305
306         prs_set_offset(&buffer->prs,0);
307
308         for (i=0; i<returned; i++) {
309                 if (!smb_io_printer_info_0("", buffer, &inf[i], 0)) {
310                         return False;
311                 }
312         }
313
314         *info=inf;
315         return True;
316 }
317
318 /**********************************************************************
319 **********************************************************************/
320
321 static bool decode_printer_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
322                                 uint32 returned, PRINTER_INFO_1 **info)
323 {
324         uint32 i;
325         PRINTER_INFO_1  *inf;
326
327         if (returned) {
328                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_1, returned);
329                 if (!inf) {
330                         return False;
331                 }
332                 memset(inf, 0, returned*sizeof(PRINTER_INFO_1));
333         } else {
334                 inf = NULL;
335         }
336
337         prs_set_offset(&buffer->prs,0);
338
339         for (i=0; i<returned; i++) {
340                 if (!smb_io_printer_info_1("", buffer, &inf[i], 0)) {
341                         return False;
342                 }
343         }
344
345         *info=inf;
346         return True;
347 }
348
349 /**********************************************************************
350 **********************************************************************/
351
352 static bool decode_printer_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
353                                 uint32 returned, PRINTER_INFO_2 **info)
354 {
355         uint32 i;
356         PRINTER_INFO_2  *inf;
357
358         if (returned) {
359                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_2, returned);
360                 if (!inf) {
361                         return False;
362                 }
363                 memset(inf, 0, returned*sizeof(PRINTER_INFO_2));
364         } else {
365                 inf = NULL;
366         }
367
368         prs_set_offset(&buffer->prs,0);
369
370         for (i=0; i<returned; i++) {
371                 /* a little initialization as we go */
372                 inf[i].secdesc = NULL;
373                 if (!smb_io_printer_info_2("", buffer, &inf[i], 0)) {
374                         return False;
375                 }
376         }
377
378         *info=inf;
379         return True;
380 }
381
382 /**********************************************************************
383 **********************************************************************/
384
385 static bool decode_printer_info_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
386                                 uint32 returned, PRINTER_INFO_3 **info)
387 {
388         uint32 i;
389         PRINTER_INFO_3  *inf;
390
391         if (returned) {
392                 inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_3, returned);
393                 if (!inf) {
394                         return False;
395                 }
396                 memset(inf, 0, returned*sizeof(PRINTER_INFO_3));
397         } else {
398                 inf = NULL;
399         }
400
401         prs_set_offset(&buffer->prs,0);
402
403         for (i=0; i<returned; i++) {
404                 inf[i].secdesc = NULL;
405                 if (!smb_io_printer_info_3("", buffer, &inf[i], 0)) {
406                         return False;
407                 }
408         }
409
410         *info=inf;
411         return True;
412 }
413
414 /**********************************************************************
415 **********************************************************************/
416
417 static bool decode_port_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
418                         uint32 returned, PORT_INFO_1 **info)
419 {
420         uint32 i;
421         PORT_INFO_1 *inf;
422
423         if (returned) {
424                 inf=TALLOC_ARRAY(mem_ctx, PORT_INFO_1, returned);
425                 if (!inf) {
426                         return False;
427                 }
428                 memset(inf, 0, returned*sizeof(PORT_INFO_1));
429         } else {
430                 inf = NULL;
431         }
432
433         prs_set_offset(&buffer->prs, 0);
434
435         for (i=0; i<returned; i++) {
436                 if (!smb_io_port_info_1("", buffer, &(inf[i]), 0)) {
437                         return False;
438                 }
439         }
440
441         *info=inf;
442         return True;
443 }
444
445 /**********************************************************************
446 **********************************************************************/
447
448 static bool decode_port_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
449                         uint32 returned, PORT_INFO_2 **info)
450 {
451         uint32 i;
452         PORT_INFO_2 *inf;
453
454         if (returned) {
455                 inf=TALLOC_ARRAY(mem_ctx, PORT_INFO_2, returned);
456                 if (!inf) {
457                         return False;
458                 }
459                 memset(inf, 0, returned*sizeof(PORT_INFO_2));
460         } else {
461                 inf = NULL;
462         }
463
464         prs_set_offset(&buffer->prs, 0);
465
466         for (i=0; i<returned; i++) {
467                 if (!smb_io_port_info_2("", buffer, &(inf[i]), 0)) {
468                         return False;
469                 }
470         }
471
472         *info=inf;
473         return True;
474 }
475
476 /**********************************************************************
477 **********************************************************************/
478
479 static bool decode_printer_driver_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
480                         uint32 returned, DRIVER_INFO_1 **info)
481 {
482         uint32 i;
483         DRIVER_INFO_1 *inf;
484
485         if (returned) {
486                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_1, returned);
487                 if (!inf) {
488                         return False;
489                 }
490                 memset(inf, 0, returned*sizeof(DRIVER_INFO_1));
491         } else {
492                 inf = NULL;
493         }
494
495         prs_set_offset(&buffer->prs,0);
496
497         for (i=0; i<returned; i++) {
498                 if (!smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0)) {
499                         return False;
500                 }
501         }
502
503         *info=inf;
504         return True;
505 }
506
507 /**********************************************************************
508 **********************************************************************/
509
510 static bool decode_printer_driver_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
511                         uint32 returned, DRIVER_INFO_2 **info)
512 {
513         uint32 i;
514         DRIVER_INFO_2 *inf;
515
516         if (returned) {
517                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_2, returned);
518                 if (!inf) {
519                         return False;
520                 }
521                 memset(inf, 0, returned*sizeof(DRIVER_INFO_2));
522         } else {
523                 inf = NULL;
524         }
525
526         prs_set_offset(&buffer->prs,0);
527
528         for (i=0; i<returned; i++) {
529                 if (!smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0)) {
530                         return False;
531                 }
532         }
533
534         *info=inf;
535         return True;
536 }
537
538 /**********************************************************************
539 **********************************************************************/
540
541 static bool decode_printer_driver_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
542                         uint32 returned, DRIVER_INFO_3 **info)
543 {
544         uint32 i;
545         DRIVER_INFO_3 *inf;
546
547         if (returned) {
548                 inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_3, returned);
549                 if (!inf) {
550                         return False;
551                 }
552                 memset(inf, 0, returned*sizeof(DRIVER_INFO_3));
553         } else {
554                 inf = NULL;
555         }
556
557         prs_set_offset(&buffer->prs,0);
558
559         for (i=0; i<returned; i++) {
560                 if (!smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0)) {
561                         return False;
562                 }
563         }
564
565         *info=inf;
566         return True;
567 }
568
569 /**********************************************************************
570 **********************************************************************/
571
572 static bool decode_jobs_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
573                           uint32 num_jobs, JOB_INFO_1 **jobs)
574 {
575         uint32 i;
576
577         if (num_jobs) {
578                 *jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_1, num_jobs);
579                 if (*jobs == NULL) {
580                         return False;
581                 }
582         } else {
583                 *jobs = NULL;
584         }
585         prs_set_offset(&buffer->prs,0);
586
587         for (i = 0; i < num_jobs; i++) {
588                 if (!smb_io_job_info_1("", buffer, &((*jobs)[i]), 0)) {
589                         return False;
590                 }
591         }
592
593         return True;
594 }
595
596 /**********************************************************************
597 **********************************************************************/
598
599 static bool decode_jobs_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
600                           uint32 num_jobs, JOB_INFO_2 **jobs)
601 {
602         uint32 i;
603
604         if (num_jobs) {
605                 *jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_2, num_jobs);
606                 if (*jobs == NULL) {
607                         return False;
608                 }
609         } else {
610                 *jobs = NULL;
611         }
612         prs_set_offset(&buffer->prs,0);
613
614         for (i = 0; i < num_jobs; i++) {
615                 if (!smb_io_job_info_2("", buffer, &((*jobs)[i]), 0)) {
616                         return False;
617                 }
618         }
619
620         return True;
621 }
622
623 /**********************************************************************
624 **********************************************************************/
625
626 static bool decode_forms_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
627                            uint32 num_forms, FORM_1 **forms)
628 {
629         int i;
630
631         if (num_forms) {
632                 *forms = TALLOC_ARRAY(mem_ctx, FORM_1, num_forms);
633                 if (*forms == NULL) {
634                         return False;
635                 }
636         } else {
637                 *forms = NULL;
638         }
639
640         prs_set_offset(&buffer->prs,0);
641
642         for (i = 0; i < num_forms; i++) {
643                 if (!smb_io_form_1("", buffer, &((*forms)[i]), 0)) {
644                         return False;
645                 }
646         }
647
648         return True;
649 }
650
651 /**********************************************************************
652 **********************************************************************/
653
654 WERROR rpccli_spoolss_enum_printers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
655                                  char *name, uint32 flags, uint32 level,
656                                  uint32 *num_printers, PRINTER_INFO_CTR *ctr)
657 {
658         prs_struct qbuf, rbuf;
659         SPOOL_Q_ENUMPRINTERS in;
660         SPOOL_R_ENUMPRINTERS out;
661         RPC_BUFFER buffer;
662         uint32 offered;
663
664         ZERO_STRUCT(in);
665         ZERO_STRUCT(out);
666
667         offered = 0;
668         if (!rpcbuf_init(&buffer, offered, mem_ctx))
669                 return WERR_NOMEM;
670         make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
671
672         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERS,
673                     in, out, 
674                     qbuf, rbuf,
675                     spoolss_io_q_enumprinters,
676                     spoolss_io_r_enumprinters, 
677                     WERR_GENERAL_FAILURE );
678                     
679         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
680                 offered = out.needed;
681                 
682                 ZERO_STRUCT(in);
683                 ZERO_STRUCT(out);
684
685                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
686                         return WERR_NOMEM;
687                 make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
688
689                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERS,
690                             in, out, 
691                             qbuf, rbuf,
692                             spoolss_io_q_enumprinters,
693                             spoolss_io_r_enumprinters, 
694                             WERR_GENERAL_FAILURE );
695         }
696
697         if ( !W_ERROR_IS_OK(out.status) )
698                 return out.status;
699
700         switch (level) {
701         case 0:
702                 if (!decode_printer_info_0(mem_ctx, out.buffer, out.returned, &ctr->printers_0)) {
703                         return WERR_GENERAL_FAILURE;
704                 }
705                 break;
706         case 1:
707                 if (!decode_printer_info_1(mem_ctx, out.buffer, out.returned, &ctr->printers_1)) {
708                         return WERR_GENERAL_FAILURE;
709                 }
710                 break;
711         case 2:
712                 if (!decode_printer_info_2(mem_ctx, out.buffer, out.returned, &ctr->printers_2)) {
713                         return WERR_GENERAL_FAILURE;
714                 }
715                 break;
716         case 3:
717                 if (!decode_printer_info_3(mem_ctx, out.buffer, out.returned, &ctr->printers_3)) {
718                         return WERR_GENERAL_FAILURE;
719                 }
720                 break;
721         default:
722                 return WERR_UNKNOWN_LEVEL;
723         }                       
724
725         *num_printers = out.returned;
726
727         return out.status;
728 }
729
730 /**********************************************************************
731 **********************************************************************/
732
733 WERROR rpccli_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
734                               uint32 level, uint32 *num_ports, PORT_INFO_CTR *ctr)
735 {
736         prs_struct qbuf, rbuf;
737         SPOOL_Q_ENUMPORTS in;
738         SPOOL_R_ENUMPORTS out;
739         RPC_BUFFER buffer;
740         fstring server;
741         uint32 offered;
742
743         ZERO_STRUCT(in);
744         ZERO_STRUCT(out);
745
746         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
747         strupper_m(server);
748
749         offered = 0;
750         if (!rpcbuf_init(&buffer, offered, mem_ctx))
751                 return WERR_NOMEM;
752         make_spoolss_q_enumports( &in, server, level, &buffer, offered );
753         
754         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPORTS,
755                     in, out, 
756                     qbuf, rbuf,
757                     spoolss_io_q_enumports,
758                     spoolss_io_r_enumports, 
759                     WERR_GENERAL_FAILURE );
760                         
761         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
762                 offered = out.needed;
763                 
764                 ZERO_STRUCT(in);
765                 ZERO_STRUCT(out);
766                 
767                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
768                         return WERR_NOMEM;
769                 make_spoolss_q_enumports( &in, server, level, &buffer, offered );
770
771                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPORTS,
772                             in, out, 
773                             qbuf, rbuf,
774                             spoolss_io_q_enumports,
775                             spoolss_io_r_enumports, 
776                             WERR_GENERAL_FAILURE );
777         }
778         
779         if ( !W_ERROR_IS_OK(out.status) )
780                 return out.status;
781         
782         switch (level) {
783         case 1:
784                 if (!decode_port_info_1(mem_ctx, out.buffer, out.returned, &ctr->port.info_1)) {
785                         return WERR_GENERAL_FAILURE;
786                 }
787                 break;
788         case 2:
789                 if (!decode_port_info_2(mem_ctx, out.buffer, out.returned, &ctr->port.info_2)) {
790                         return WERR_GENERAL_FAILURE;
791                 }
792                 break;
793         default:
794                 return WERR_UNKNOWN_LEVEL;
795         }
796
797         *num_ports = out.returned;
798
799         return out.status;
800 }
801
802 /**********************************************************************
803 **********************************************************************/
804
805 WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli, 
806                                        TALLOC_CTX *mem_ctx,
807                                        uint32 level, const char *env,
808                                        uint32 *num_drivers,
809                                        PRINTER_DRIVER_CTR *ctr)
810 {
811         prs_struct qbuf, rbuf;
812         SPOOL_Q_ENUMPRINTERDRIVERS in;
813         SPOOL_R_ENUMPRINTERDRIVERS out;
814         RPC_BUFFER buffer;
815         fstring server;
816         uint32 offered;
817
818         ZERO_STRUCT(in);
819         ZERO_STRUCT(out);
820
821         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
822         strupper_m(server);
823
824         offered = 0;
825         if (!rpcbuf_init(&buffer, offered, mem_ctx))
826                 return WERR_NOMEM;
827         make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
828                 &buffer, offered);
829         
830         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
831                     in, out, 
832                     qbuf, rbuf,
833                     spoolss_io_q_enumprinterdrivers,
834                     spoolss_io_r_enumprinterdrivers, 
835                     WERR_GENERAL_FAILURE );
836
837         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
838                 offered = out.needed;
839                 
840                 ZERO_STRUCT(in);
841                 ZERO_STRUCT(out);
842                 
843                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
844                         return WERR_NOMEM;
845                 make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
846                         &buffer, offered);
847         
848                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
849                             in, out, 
850                             qbuf, rbuf,
851                             spoolss_io_q_enumprinterdrivers,
852                             spoolss_io_r_enumprinterdrivers, 
853                             WERR_GENERAL_FAILURE );
854         }
855         
856         *num_drivers = out.returned;
857
858         if ( !W_ERROR_IS_OK(out.status) )
859                 return out.status;
860                 
861         if ( out.returned ) {
862
863                 switch (level) {
864                 case 1:
865                         if (!decode_printer_driver_1(mem_ctx, out.buffer, out.returned, &ctr->info1)) {
866                                 return WERR_GENERAL_FAILURE;
867                         }
868                         break;
869                 case 2:
870                         if (!decode_printer_driver_2(mem_ctx, out.buffer, out.returned, &ctr->info2)) {
871                                 return WERR_GENERAL_FAILURE;
872                         }
873                         break;
874                 case 3:
875                         if (!decode_printer_driver_3(mem_ctx, out.buffer, out.returned, &ctr->info3)) {
876                                 return WERR_GENERAL_FAILURE;
877                         }
878                         break;
879                 default:
880                         return WERR_UNKNOWN_LEVEL;
881                 }
882         }
883
884         return out.status;
885 }
886
887 /**********************************************************************
888 **********************************************************************/
889
890 WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
891                              POLICY_HND *handle, int level, uint32 *num_forms,
892                              FORM_1 **forms)
893 {
894         prs_struct qbuf, rbuf;
895         SPOOL_Q_ENUMFORMS in;
896         SPOOL_R_ENUMFORMS out;
897         RPC_BUFFER buffer;
898         uint32 offered;
899
900         ZERO_STRUCT(in);
901         ZERO_STRUCT(out);
902
903         offered = 0;
904         if (!rpcbuf_init(&buffer, offered, mem_ctx))
905                 return WERR_NOMEM;
906         make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
907
908         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
909                     in, out, 
910                     qbuf, rbuf,
911                     spoolss_io_q_enumforms,
912                     spoolss_io_r_enumforms, 
913                     WERR_GENERAL_FAILURE );
914
915         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
916                 offered = out.needed;
917                 
918                 ZERO_STRUCT(in);
919                 ZERO_STRUCT(out);
920
921                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
922                         return WERR_NOMEM;
923                 make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
924
925                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
926                             in, out, 
927                             qbuf, rbuf,
928                             spoolss_io_q_enumforms,
929                             spoolss_io_r_enumforms, 
930                             WERR_GENERAL_FAILURE );
931         }
932
933         if (!W_ERROR_IS_OK(out.status))
934                 return out.status;
935
936         *num_forms = out.numofforms;
937         
938         if (!decode_forms_1(mem_ctx, out.buffer, *num_forms, forms)) {
939                 return WERR_GENERAL_FAILURE;
940         }
941
942         return out.status;
943 }
944
945 /**********************************************************************
946 **********************************************************************/
947
948 WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
949                             POLICY_HND *hnd, uint32 level, uint32 firstjob, 
950                             uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr)
951 {
952         prs_struct qbuf, rbuf;
953         SPOOL_Q_ENUMJOBS in;
954         SPOOL_R_ENUMJOBS out;
955         RPC_BUFFER buffer;
956         uint32 offered;
957
958         ZERO_STRUCT(in);
959         ZERO_STRUCT(out);
960
961         offered = 0;
962         if (!rpcbuf_init(&buffer, offered, mem_ctx))
963                 return WERR_NOMEM;
964         make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
965                 &buffer, offered );
966
967         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
968                     in, out, 
969                     qbuf, rbuf,
970                     spoolss_io_q_enumjobs,
971                     spoolss_io_r_enumjobs, 
972                     WERR_GENERAL_FAILURE );
973
974         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
975                 offered = out.needed;
976                 
977                 ZERO_STRUCT(in);
978                 ZERO_STRUCT(out);
979
980                 if (!rpcbuf_init(&buffer, offered, mem_ctx))
981                         return WERR_NOMEM;
982                 make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
983                         &buffer, offered );
984
985                 CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
986                             in, out, 
987                             qbuf, rbuf,
988                             spoolss_io_q_enumjobs,
989                             spoolss_io_r_enumjobs, 
990                             WERR_GENERAL_FAILURE );
991         }
992
993         if (!W_ERROR_IS_OK(out.status))
994                 return out.status;
995                 
996         switch(level) {
997         case 1:
998                 if (!decode_jobs_1(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_1)) {
999                         return WERR_GENERAL_FAILURE;
1000                 }
1001                 break;
1002         case 2:
1003                 if (!decode_jobs_2(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_2)) {
1004                         return WERR_GENERAL_FAILURE;
1005                 }
1006                 break;
1007         default:
1008                 DEBUG(3, ("unsupported info level %d", level));
1009                 return WERR_UNKNOWN_LEVEL;
1010         }
1011         
1012         *returned = out.returned;
1013
1014         return out.status;
1015 }
1016
1017 /**********************************************************************
1018 **********************************************************************/
1019
1020 WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1021                                   POLICY_HND *hnd, const char *valuename, 
1022                                   REGISTRY_VALUE *value)
1023 {
1024         prs_struct qbuf, rbuf;
1025         SPOOL_Q_GETPRINTERDATA in;
1026         SPOOL_R_GETPRINTERDATA out;
1027         uint32 offered;
1028
1029         ZERO_STRUCT(in);
1030         ZERO_STRUCT(out);
1031
1032         offered = 0;
1033         make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
1034
1035         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
1036                     in, out, 
1037                     qbuf, rbuf,
1038                     spoolss_io_q_getprinterdata,
1039                     spoolss_io_r_getprinterdata, 
1040                     WERR_GENERAL_FAILURE );
1041
1042         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1043                 offered = out.needed;
1044                 
1045                 ZERO_STRUCT(in);
1046                 ZERO_STRUCT(out);
1047                 
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
1058         if (!W_ERROR_IS_OK(out.status))
1059                 return out.status;      
1060
1061         /* Return output parameters */
1062
1063         if (out.needed) {
1064                 value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
1065         } else {
1066                 value->data_p = NULL;
1067         }
1068         value->type = out.type;
1069         value->size = out.size;
1070
1071         return out.status;
1072 }
1073
1074 /**********************************************************************
1075 **********************************************************************/
1076
1077 WERROR rpccli_spoolss_setprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1078                                   POLICY_HND *hnd, REGISTRY_VALUE *value)
1079 {
1080         prs_struct qbuf, rbuf;
1081         SPOOL_Q_SETPRINTERDATA in;
1082         SPOOL_R_SETPRINTERDATA out;
1083
1084         ZERO_STRUCT(in);
1085         ZERO_STRUCT(out);
1086
1087         make_spoolss_q_setprinterdata( &in, hnd, value->valuename, 
1088                 value->type, (char *)value->data_p, value->size);
1089
1090         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_SETPRINTERDATA,
1091                     in, out, 
1092                     qbuf, rbuf,
1093                     spoolss_io_q_setprinterdata,
1094                     spoolss_io_r_setprinterdata, 
1095                     WERR_GENERAL_FAILURE );
1096                     
1097         return out.status;
1098 }
1099
1100 /**********************************************************************
1101 **********************************************************************/
1102
1103 WERROR rpccli_spoolss_enumprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1104                                    POLICY_HND *hnd, uint32 ndx,
1105                                    uint32 value_offered, uint32 data_offered,
1106                                    uint32 *value_needed, uint32 *data_needed,
1107                                    REGISTRY_VALUE *value)
1108 {
1109         prs_struct qbuf, rbuf;
1110         SPOOL_Q_ENUMPRINTERDATA in;
1111         SPOOL_R_ENUMPRINTERDATA out;
1112
1113         ZERO_STRUCT(in);
1114         ZERO_STRUCT(out);
1115
1116         make_spoolss_q_enumprinterdata( &in, hnd, ndx, value_offered, data_offered );
1117
1118         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATA,
1119                     in, out, 
1120                     qbuf, rbuf,
1121                     spoolss_io_q_enumprinterdata,
1122                     spoolss_io_r_enumprinterdata, 
1123                     WERR_GENERAL_FAILURE );
1124
1125         if ( value_needed )
1126                 *value_needed = out.realvaluesize;
1127         if ( data_needed )
1128                 *data_needed = out.realdatasize;
1129                 
1130         if (!W_ERROR_IS_OK(out.status))
1131                 return out.status;
1132
1133         if (value) {
1134                 rpcstr_pull(value->valuename, out.value, sizeof(value->valuename), -1,
1135                             STR_TERMINATE);
1136                 if (out.realdatasize) {
1137                         value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data,
1138                                                        out.realdatasize);
1139                 } else {
1140                         value->data_p = NULL;
1141                 }
1142                 value->type = out.type;
1143                 value->size = out.realdatasize;
1144         }
1145         
1146         return out.status;
1147 }
1148
1149 /**********************************************************************
1150 **********************************************************************/
1151
1152 WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1153                                      POLICY_HND *hnd, const char *keyname, 
1154                                      REGVAL_CTR *ctr)
1155 {
1156         prs_struct qbuf, rbuf;
1157         SPOOL_Q_ENUMPRINTERDATAEX in;
1158         SPOOL_R_ENUMPRINTERDATAEX out;
1159         int i;
1160         uint32 offered;
1161
1162         ZERO_STRUCT(in);
1163         ZERO_STRUCT(out);
1164
1165         offered = 0;
1166         make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
1167
1168         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
1169                     in, out, 
1170                     qbuf, rbuf,
1171                     spoolss_io_q_enumprinterdataex,
1172                     spoolss_io_r_enumprinterdataex, 
1173                     WERR_GENERAL_FAILURE );
1174
1175         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1176                 offered = out.needed;
1177                 
1178                 ZERO_STRUCT(in);
1179                 ZERO_STRUCT(out);
1180                 
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         
1191         if (!W_ERROR_IS_OK(out.status))
1192                 return out.status;
1193
1194         for (i = 0; i < out.returned; i++) {
1195                 PRINTER_ENUM_VALUES *v = &out.ctr.values[i];
1196                 fstring name;
1197
1198                 rpcstr_pull(name, v->valuename.buffer, sizeof(name), -1, 
1199                             STR_TERMINATE);
1200                 regval_ctr_addvalue(ctr, name, v->type, (const char *)v->data, v->data_len);
1201         }
1202
1203         return out.status;
1204 }
1205
1206 /**********************************************************************
1207 **********************************************************************/
1208
1209 WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1210                                   POLICY_HND *hnd, const char *keyname,
1211                                   uint16 **keylist, uint32 *len)
1212 {
1213         prs_struct qbuf, rbuf;
1214         SPOOL_Q_ENUMPRINTERKEY in;
1215         SPOOL_R_ENUMPRINTERKEY out;
1216         uint32 offered = 0;
1217
1218         ZERO_STRUCT(in);
1219         ZERO_STRUCT(out);
1220
1221         make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
1222
1223         CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
1224                     in, out, 
1225                     qbuf, rbuf,
1226                     spoolss_io_q_enumprinterkey,
1227                     spoolss_io_r_enumprinterkey, 
1228                     WERR_GENERAL_FAILURE );
1229
1230         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
1231                 offered = out.needed;
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
1246         if ( !W_ERROR_IS_OK(out.status) )
1247                 return out.status;      
1248         
1249         if (keylist) {
1250                 *keylist = SMB_MALLOC_ARRAY(uint16, out.keys.buf_len);
1251                 if (!*keylist) {
1252                         return WERR_NOMEM;
1253                 }
1254                 memcpy(*keylist, out.keys.buffer, out.keys.buf_len * 2);
1255                 if (len)
1256                         *len = out.keys.buf_len * 2;
1257         }
1258
1259         return out.status;
1260 }
1261 /** @} **/