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