b335127b8be89fae19b832883b3d146c41711b17
[samba.git] / source3 / libsmb / cli_spoolss.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.2
4    RPC pipe client
5
6    Copyright (C) Gerald Carter                2001,
7    Copyright (C) Tim Potter                   2000,
8    Copyright (C) Andrew Tridgell              1994-2000
9    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
10    Copyright (C) Jean-Francois Micouleau      1999-2000
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27 #include "includes.h"
28
29 extern pstring global_myname;
30
31 /* Opens a SMB connection to the SPOOLSS pipe */
32 struct cli_state *cli_spoolss_initialise(struct cli_state *cli, 
33                                          char *system_name,
34                                          struct ntuser_creds *creds)
35 {
36         struct in_addr dest_ip;
37         struct nmb_name calling, called;
38         fstring dest_host;
39         extern pstring global_myname;
40         struct ntuser_creds anon;
41
42         /* Initialise cli_state information */
43
44         if (!cli_initialise(cli)) {
45                 return NULL;
46         }
47
48         if (!creds) {
49                 ZERO_STRUCT(anon);
50                 anon.pwd.null_pwd = 1;
51                 creds = &anon;
52         }
53
54         cli_init_creds(cli, creds);
55
56         /* Establish a SMB connection */
57
58         if (!resolve_srv_name(system_name, dest_host, &dest_ip)) {
59                 return NULL;
60         }
61
62         make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
63         make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
64
65         if (!cli_establish_connection(cli, dest_host, &dest_ip, &calling, 
66                                       &called, "IPC$", "IPC", False, True)) {
67                 return NULL;
68         }
69
70         /* Open a NT session thingy */
71
72         if (!cli_nt_session_open(cli, PIPE_SPOOLSS)) {
73                 cli_shutdown(cli);
74                 return NULL;
75         }
76
77         return cli;
78 }
79
80 /* Shut down a SMB connection to the SPOOLSS pipe */
81
82 void cli_spoolss_shutdown(struct cli_state *cli)
83 {
84         if (cli->fd != -1) cli_ulogoff(cli);
85         cli_shutdown(cli);
86 }
87
88 /* Open printer ex */
89
90 uint32 cli_spoolss_open_printer_ex(struct cli_state *cli, char *printername,
91                                    char *datatype, uint32 access_required,
92                                    char *station, char *username,
93                                    POLICY_HND *pol)
94 {
95         prs_struct qbuf, rbuf;
96         SPOOL_Q_OPEN_PRINTER_EX q;
97         SPOOL_R_OPEN_PRINTER_EX r;
98         uint32 result;
99
100         ZERO_STRUCT(q);
101         ZERO_STRUCT(r);
102
103         /* Initialise parse structures */
104
105         prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
106         prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
107
108         /* Initialise input parameters */
109
110         make_spoolss_q_open_printer_ex(&q, printername, datatype,
111                                        access_required, station, username);
112         
113         /* Marshall data and send request */
114
115         if (!spoolss_io_q_open_printer_ex("", &q, &qbuf, 0) ||
116             !rpc_api_pipe_req(cli, SPOOLSS_OPENPRINTEREX, &qbuf, &rbuf)) {
117                 result = NT_STATUS_UNSUCCESSFUL;
118                 goto done;
119         }
120
121         /* Unmarshall response */
122
123         if (!spoolss_io_r_open_printer_ex("", &r, &rbuf, 0)) {
124                 result = NT_STATUS_UNSUCCESSFUL;
125                 goto done;
126         }
127
128         /* Return output parameters */
129
130         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
131                 *pol = r.handle;
132         }
133
134  done:
135         prs_mem_free(&qbuf);
136         prs_mem_free(&rbuf);
137
138         return result;
139 }
140
141 /* Close a printer handle */
142
143 uint32 cli_spoolss_close_printer(struct cli_state *cli, POLICY_HND *pol)
144 {
145         prs_struct qbuf, rbuf;
146         SPOOL_Q_CLOSEPRINTER q;
147         SPOOL_R_CLOSEPRINTER r;
148         uint32 result;
149
150         ZERO_STRUCT(q);
151         ZERO_STRUCT(r);
152
153         /* Initialise parse structures */
154
155         prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
156         prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
157
158         /* Initialise input parameters */
159
160         make_spoolss_q_closeprinter(&q, pol);
161         
162         /* Marshall data and send request */
163
164         if (!spoolss_io_q_closeprinter("", &q, &qbuf, 0) ||
165             !rpc_api_pipe_req(cli, SPOOLSS_CLOSEPRINTER, &qbuf, &rbuf)) {
166                 result = NT_STATUS_UNSUCCESSFUL;
167                 goto done;
168         }
169
170         /* Unmarshall response */
171
172         if (!spoolss_io_r_closeprinter("", &r, &rbuf, 0)) {
173                 result = NT_STATUS_UNSUCCESSFUL;
174                 goto done;
175         }
176
177         /* Return output parameters */
178
179         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
180                 *pol = r.handle;
181         }
182
183  done:
184         prs_mem_free(&qbuf);
185         prs_mem_free(&rbuf);
186
187         return result;
188 }
189
190 /* Initialize a spoolss NEW_BUFFER */
191
192 static void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
193 {
194         buffer->ptr = (size != 0);
195         buffer->size = size;
196         buffer->string_at_end = size;
197         prs_init(&buffer->prs, size, ctx, MARSHALL);
198         buffer->struct_start = prs_offset(&buffer->prs);
199 }
200
201 /* Decode various printer info levels - perhaps this should live in
202    parse_spoolss.c? */
203
204 static void decode_printer_info_0(NEW_BUFFER *buffer, uint32 returned, 
205                                   PRINTER_INFO_0 **info)
206 {
207         uint32 i;
208         PRINTER_INFO_0  *inf;
209
210         inf=(PRINTER_INFO_0 *)malloc(returned*sizeof(PRINTER_INFO_0));
211
212         buffer->prs.data_offset=0;
213
214         for (i=0; i<returned; i++) {
215                 smb_io_printer_info_0("", buffer, &inf[i], 0);
216         }
217
218         *info=inf;
219 }
220
221 static void decode_printer_info_1(NEW_BUFFER *buffer, uint32 returned, 
222                                   PRINTER_INFO_1 **info)
223 {
224         uint32 i;
225         PRINTER_INFO_1  *inf;
226
227         inf=(PRINTER_INFO_1 *)malloc(returned*sizeof(PRINTER_INFO_1));
228
229         buffer->prs.data_offset=0;
230
231         for (i=0; i<returned; i++) {
232                 smb_io_printer_info_1("", buffer, &inf[i], 0);
233         }
234
235         *info=inf;
236 }
237
238 static void decode_printer_info_2(NEW_BUFFER *buffer, uint32 returned, 
239                                   PRINTER_INFO_2 **info)
240 {
241         uint32 i;
242         PRINTER_INFO_2  *inf;
243
244         inf=(PRINTER_INFO_2 *)malloc(returned*sizeof(PRINTER_INFO_2));
245
246         buffer->prs.data_offset=0;
247
248         for (i=0; i<returned; i++) {
249                 /* a little initialization as we go */
250                 inf[i].secdesc = NULL;
251                 smb_io_printer_info_2("", buffer, &inf[i], 0);
252         }
253
254         *info=inf;
255 }
256
257 static void decode_printer_info_3(NEW_BUFFER *buffer, uint32 returned, 
258                                   PRINTER_INFO_3 **info)
259 {
260         uint32 i;
261         PRINTER_INFO_3  *inf;
262
263         inf=(PRINTER_INFO_3 *)malloc(returned*sizeof(PRINTER_INFO_3));
264
265         buffer->prs.data_offset=0;
266
267         for (i=0; i<returned; i++) {
268                 inf[i].secdesc = NULL;
269                 smb_io_printer_info_3("", buffer, &inf[i], 0);
270         }
271
272         *info=inf;
273 }
274
275 /**********************************************************************
276  Decode a PORT_INFO_1 struct from a NEW_BUFFER 
277 **********************************************************************/
278 static void decode_port_info_1(NEW_BUFFER *buffer, uint32 returned, 
279                                PORT_INFO_1 **info)
280 {
281         uint32 i;
282         PORT_INFO_1 *inf;
283
284         inf=(PORT_INFO_1*)malloc(returned*sizeof(PORT_INFO_1));
285
286         prs_set_offset(&buffer->prs, 0);
287
288         for (i=0; i<returned; i++) {
289                 smb_io_port_info_1("", buffer, &(inf[i]), 0);
290         }
291
292         *info=inf;
293 }
294
295 /**********************************************************************
296  Decode a PORT_INFO_2 struct from a NEW_BUFFER 
297 **********************************************************************/
298 static void decode_port_info_2(NEW_BUFFER *buffer, uint32 returned, 
299                                PORT_INFO_2 **info)
300 {
301         uint32 i;
302         PORT_INFO_2 *inf;
303
304         inf=(PORT_INFO_2*)malloc(returned*sizeof(PORT_INFO_2));
305
306         prs_set_offset(&buffer->prs, 0);
307
308         for (i=0; i<returned; i++) {
309                 smb_io_port_info_2("", buffer, &(inf[i]), 0);
310         }
311
312         *info=inf;
313 }
314
315 static void decode_printer_driver_1(NEW_BUFFER *buffer, uint32 returned, 
316                                     DRIVER_INFO_1 **info)
317 {
318         uint32 i;
319         DRIVER_INFO_1 *inf;
320
321         inf=(DRIVER_INFO_1 *)malloc(returned*sizeof(DRIVER_INFO_1));
322
323         buffer->prs.data_offset=0;
324
325         for (i=0; i<returned; i++) {
326                 smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0);
327         }
328
329         *info=inf;
330 }
331
332 static void decode_printer_driver_2(NEW_BUFFER *buffer, uint32 returned, 
333                                     DRIVER_INFO_2 **info)
334 {
335         uint32 i;
336         DRIVER_INFO_2 *inf;
337
338         inf=(DRIVER_INFO_2 *)malloc(returned*sizeof(DRIVER_INFO_2));
339
340         buffer->prs.data_offset=0;
341
342         for (i=0; i<returned; i++) {
343                 smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0);
344         }
345
346         *info=inf;
347 }
348
349 static void decode_printer_driver_3(
350         NEW_BUFFER *buffer, 
351         uint32 returned, 
352         DRIVER_INFO_3 **info
353 )
354 {
355         uint32 i;
356         DRIVER_INFO_3 *inf;
357
358         inf=(DRIVER_INFO_3 *)malloc(returned*sizeof(DRIVER_INFO_3));
359
360         buffer->prs.data_offset=0;
361
362         for (i=0; i<returned; i++) {
363                 smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0);
364         }
365
366         *info=inf;
367 }
368
369 static void decode_printerdriverdir_1 (
370         NEW_BUFFER *buffer, 
371         uint32 returned, 
372         DRIVER_DIRECTORY_1 **info
373 )
374 {
375         DRIVER_DIRECTORY_1 *inf;
376  
377         inf=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1));
378
379         prs_set_offset(&buffer->prs, 0);
380
381         smb_io_driverdir_1("", buffer, inf, 0);
382  
383         *info=inf;
384 }
385
386
387 /* Enumerate printers */
388
389 uint32 cli_spoolss_enum_printers(struct cli_state *cli, uint32 flags,
390                                  uint32 level, int *returned, 
391                                  PRINTER_INFO_CTR *ctr)
392 {
393         prs_struct qbuf, rbuf;
394         SPOOL_Q_ENUMPRINTERS q;
395         SPOOL_R_ENUMPRINTERS r;
396         NEW_BUFFER buffer;
397         uint32 needed = 100;
398         uint32 result;
399         fstring server;
400
401         ZERO_STRUCT(q);
402         ZERO_STRUCT(r);
403
404         fstrcpy (server, cli->desthost);
405         strupper (server);
406         
407         do {
408                 /* Initialise input parameters */
409
410                 init_buffer(&buffer, needed, cli->mem_ctx);
411
412                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
413                 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
414
415                 make_spoolss_q_enumprinters(&q, flags, server, level, &buffer, 
416                                             needed);
417
418                 /* Marshall data and send request */
419
420                 if (!spoolss_io_q_enumprinters("", &q, &qbuf, 0) ||
421                     !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERS, &qbuf, &rbuf)) {
422                         result = NT_STATUS_UNSUCCESSFUL;
423                         goto done;
424                 }
425
426                 /* Unmarshall response */
427                 if (spoolss_io_r_enumprinters("", &r, &rbuf, 0)) {
428                         needed = r.needed;
429                 }
430                 
431                 /* Return output parameters */
432
433                 if ((result = r.status) == NT_STATUS_NOPROBLEMO && r.returned > 0) {
434
435                         *returned = r.returned;
436
437                         switch (level) {
438                         case 1:
439                                 decode_printer_info_1(r.buffer, r.returned, 
440                                                       &ctr->printers_1);
441                                 break;
442                         case 2:
443                                 decode_printer_info_2(r.buffer, r.returned, 
444                                                       &ctr->printers_2);
445                                 break;
446                         case 3:
447                                 decode_printer_info_3(r.buffer, r.returned, 
448                                                       &ctr->printers_3);
449                                 break;
450                         }                       
451                 }
452
453         done:
454                 prs_mem_free(&qbuf);
455                 prs_mem_free(&rbuf);
456
457         } while (result == ERROR_INSUFFICIENT_BUFFER);
458
459         return result;  
460 }
461
462 /* Enumerate printer ports */
463 uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level, 
464                               int *returned, PORT_INFO_CTR *ctr)
465 {
466         prs_struct qbuf, rbuf;
467         SPOOL_Q_ENUMPORTS q;
468         SPOOL_R_ENUMPORTS r;
469         NEW_BUFFER buffer;
470         uint32 needed = 100;
471         uint32 result;
472         fstring server;
473
474         ZERO_STRUCT(q);
475         ZERO_STRUCT(r);
476
477         slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
478         strupper (server);
479
480         do {
481                 /* Initialise input parameters */
482
483                 init_buffer(&buffer, needed, cli->mem_ctx);
484
485                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
486                 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
487
488                 make_spoolss_q_enumports(&q, server, level, &buffer, needed);
489
490                 /* Marshall data and send request */
491
492                 if (!spoolss_io_q_enumports("", &q, &qbuf, 0) ||
493                     !rpc_api_pipe_req(cli, SPOOLSS_ENUMPORTS, &qbuf, &rbuf)) {
494                         result = NT_STATUS_UNSUCCESSFUL;
495                         goto done;
496                 }
497
498                 /* Unmarshall response */
499                 if (spoolss_io_r_enumports("", &r, &rbuf, 0)) {
500                         needed = r.needed;
501                 }
502                 
503                 /* Return output parameters */
504
505                 if ((result = r.status) == NT_STATUS_NOPROBLEMO &&
506                     r.returned > 0) {
507
508                         *returned = r.returned;
509
510                         switch (level) {
511                         case 1:
512                                 decode_port_info_1(r.buffer, r.returned, 
513                                                    &ctr->port.info_1);
514                                 break;
515                         case 2:
516                                 decode_port_info_2(r.buffer, r.returned, 
517                                                    &ctr->port.info_2);
518                                 break;
519                         }                       
520                 }
521
522         done:
523                 prs_mem_free(&qbuf);
524                 prs_mem_free(&rbuf);
525
526         } while (result == ERROR_INSUFFICIENT_BUFFER);
527
528         return result;  
529 }
530
531 /* Get printer info */
532 uint32 cli_spoolss_getprinter(struct cli_state *cli, POLICY_HND *pol,
533                               uint32 level, PRINTER_INFO_CTR *ctr)
534 {
535         prs_struct qbuf, rbuf;
536         SPOOL_Q_GETPRINTER q;
537         SPOOL_R_GETPRINTER r;
538         NEW_BUFFER buffer;
539         uint32 needed = 100;
540         uint32 result;
541
542         ZERO_STRUCT(q);
543         ZERO_STRUCT(r);
544
545         do {
546                 /* Initialise input parameters */
547
548                 init_buffer(&buffer, needed, cli->mem_ctx);
549
550                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
551                 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
552
553                 make_spoolss_q_getprinter(&q, pol, level, &buffer, 
554                                           needed);
555
556                 /* Marshall data and send request */
557
558                 if (!spoolss_io_q_getprinter("", &q, &qbuf, 0) ||
559                     !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTER, &qbuf,
560                                       &rbuf)) {
561                         result = NT_STATUS_UNSUCCESSFUL;
562                         goto done;
563                 }
564
565                 /* Unmarshall response */
566                 if (spoolss_io_r_getprinter("", &r, &rbuf, 0)) {
567                         needed = r.needed;
568                 }
569                 
570                 /* Return output parameters */
571
572                 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
573
574                         switch (level) {
575                         case 0:
576                                 decode_printer_info_0(r.buffer, 1, 
577                                                       &ctr->printers_0);
578                                 break;
579                         case 1:
580                                 decode_printer_info_1(r.buffer, 1, 
581                                                       &ctr->printers_1);
582                                 break;
583                         case 2:
584                                 decode_printer_info_2(r.buffer, 1,
585                                                       &ctr->printers_2);
586                                 break;
587                         case 3:
588                                 decode_printer_info_3(r.buffer, 1,
589                                                       &ctr->printers_3);
590                                 break;
591                         }                       
592                 }
593
594         done:
595                 prs_mem_free(&qbuf);
596                 prs_mem_free(&rbuf);
597
598         } while (result == ERROR_INSUFFICIENT_BUFFER);
599
600         return result;  
601 }
602
603 /**********************************************************************
604  * Get installed printer drivers for a given printer
605  */
606 uint32 cli_spoolss_getprinterdriver (
607         struct cli_state        *cli, 
608         POLICY_HND              *pol, 
609         uint32                  level,
610         char*                   env,
611         PRINTER_DRIVER_CTR      *ctr
612 )
613 {
614         prs_struct qbuf, rbuf;
615         SPOOL_Q_GETPRINTERDRIVER2 q;
616         SPOOL_R_GETPRINTERDRIVER2 r;
617         NEW_BUFFER buffer;
618         uint32 needed = 1024;
619         uint32 result;
620         fstring server;
621
622         ZERO_STRUCT(q);
623         ZERO_STRUCT(r);
624
625         fstrcpy (server, cli->desthost);
626         strupper (server);
627
628         do 
629         {
630                 /* Initialise input parameters */
631
632                 init_buffer(&buffer, needed, cli->mem_ctx);
633
634                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
635                 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
636
637
638                 /* write the request */
639                 make_spoolss_q_getprinterdriver2(&q, pol, env, level, 2, 2, &buffer, needed);
640
641                 /* Marshall data and send request */
642                 if (!spoolss_io_q_getprinterdriver2 ("", &q, &qbuf, 0) ||
643                     !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVER2, &qbuf, &rbuf)) 
644                 {
645                         result = NT_STATUS_UNSUCCESSFUL;
646                         goto done;
647                 }
648
649                 /* Unmarshall response */
650                 if (spoolss_io_r_getprinterdriver2 ("", &r, &rbuf, 0)) 
651                 {
652                         needed = r.needed;
653                 }
654                 
655                 /* Return output parameters */
656                 if ((result = r.status) == NT_STATUS_NOPROBLEMO) 
657                 {
658
659                         switch (level) 
660                         {
661                         case 1:
662                                 decode_printer_driver_1(r.buffer, 1, &ctr->info1);
663                                 break;
664                         case 2:
665                                 decode_printer_driver_2(r.buffer, 1, &ctr->info2);
666                                 break;
667                         case 3:
668                                 decode_printer_driver_3(r.buffer, 1, &ctr->info3);
669                                 break;
670                         }                       
671                 }
672
673         done:
674                 prs_mem_free(&qbuf);
675                 prs_mem_free(&rbuf);
676
677         } while (result == ERROR_INSUFFICIENT_BUFFER);
678
679         return result;  
680 }
681
682 /**********************************************************************
683  * Get installed printer drivers for a given printer
684  */
685 uint32 cli_spoolss_enumprinterdrivers (
686         struct cli_state        *cli, 
687         uint32                  level,
688         char*                   env,
689         uint32                  *returned,
690         PRINTER_DRIVER_CTR      *ctr
691 )
692 {
693         prs_struct                      qbuf, rbuf;
694         SPOOL_Q_ENUMPRINTERDRIVERS      q;
695         SPOOL_R_ENUMPRINTERDRIVERS      r;
696         NEW_BUFFER                      buffer;
697         uint32                          needed = 0;
698         uint32                          result;
699         fstring                         server;
700
701         ZERO_STRUCT(q);
702         ZERO_STRUCT(r);
703
704         slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
705         strupper (server);
706
707         do 
708         {
709                 /* Initialise input parameters */
710                 init_buffer(&buffer, needed, cli->mem_ctx);
711
712                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
713                 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
714
715
716                 /* write the request */
717                 make_spoolss_q_enumprinterdrivers(&q, server, env, level, &buffer, needed);
718
719                 /* Marshall data and send request */
720                 if (!spoolss_io_q_enumprinterdrivers ("", &q, &qbuf, 0) ||
721                     !rpc_api_pipe_req (cli, SPOOLSS_ENUMPRINTERDRIVERS, &qbuf, &rbuf)) 
722                 {
723                         result = NT_STATUS_UNSUCCESSFUL;
724                         goto done;
725                 }
726
727                 /* Unmarshall response */
728                 if (spoolss_io_r_enumprinterdrivers ("", &r, &rbuf, 0)) 
729                 {
730                         needed = r.needed;
731                 }
732                 
733                 /* Return output parameters */
734                 if (((result=r.status) == NT_STATUS_NOPROBLEMO) && 
735                     (r.returned != 0))
736                 {
737                         *returned = r.returned;
738
739                         switch (level) 
740                         {
741                         case 1:
742                                 decode_printer_driver_1(r.buffer, r.returned, &ctr->info1);
743                                 break;
744                         case 2:
745                                 decode_printer_driver_2(r.buffer, r.returned, &ctr->info2);
746                                 break;
747                         case 3:
748                                 decode_printer_driver_3(r.buffer, r.returned, &ctr->info3);
749                                 break;
750                         }                       
751                 }
752
753         done:
754                 prs_mem_free(&qbuf);
755                 prs_mem_free(&rbuf);
756
757         } while (result == ERROR_INSUFFICIENT_BUFFER);
758
759         return result;  
760 }
761
762
763 /**********************************************************************
764  * Get installed printer drivers for a given printer
765  */
766 uint32 cli_spoolss_getprinterdriverdir (
767         struct cli_state        *cli, 
768         uint32                  level,
769         char*                   env,
770         DRIVER_DIRECTORY_CTR    *ctr
771 )
772 {
773         prs_struct                      qbuf, rbuf;
774         SPOOL_Q_GETPRINTERDRIVERDIR     q;
775         SPOOL_R_GETPRINTERDRIVERDIR     r;
776         NEW_BUFFER                      buffer;
777         uint32                          needed = 100;
778         uint32                          result;
779         fstring                         server;
780
781         ZERO_STRUCT(q);
782         ZERO_STRUCT(r);
783
784         slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
785         strupper (server);
786
787         do 
788         {
789                 /* Initialise input parameters */
790                 init_buffer(&buffer, needed, cli->mem_ctx);
791
792                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
793                 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
794
795
796                 /* write the request */
797                 make_spoolss_q_getprinterdriverdir(&q, server, env, level, &buffer, needed);
798
799                 /* Marshall data and send request */
800                 if (!spoolss_io_q_getprinterdriverdir ("", &q, &qbuf, 0) ||
801                     !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVERDIRECTORY, &qbuf, &rbuf)) 
802                 {
803                         result = NT_STATUS_UNSUCCESSFUL;
804                         goto done;
805                 }
806
807                 /* Unmarshall response */
808                 if (spoolss_io_r_getprinterdriverdir ("", &r, &rbuf, 0)) 
809                 {
810                         needed = r.needed;
811                 }
812                 
813                 /* Return output parameters */
814                 if ((result=r.status) == NT_STATUS_NOPROBLEMO)
815                 {
816                         switch (level) 
817                         {
818                         case 1:
819                                 decode_printerdriverdir_1(r.buffer, 1, &ctr->info1);
820                                 break;
821                         }                       
822                 }
823
824         done:
825                 prs_mem_free(&qbuf);
826                 prs_mem_free(&rbuf);
827
828         } while (result == ERROR_INSUFFICIENT_BUFFER);
829
830         return result;  
831 }
832
833 /**********************************************************************
834  * Install a printer driver
835  */
836 uint32 cli_spoolss_addprinterdriver (
837         struct cli_state        *cli, 
838         uint32                  level,
839         PRINTER_DRIVER_CTR      *ctr
840 )
841 {
842         prs_struct                      qbuf, rbuf;
843         SPOOL_Q_ADDPRINTERDRIVER        q;
844         SPOOL_R_ADDPRINTERDRIVER        r;
845         uint32                          result;
846         fstring                         server;
847
848         ZERO_STRUCT(q);
849         ZERO_STRUCT(r);
850
851         slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
852         strupper (server);
853
854         /* Initialise input parameters */
855         prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
856         prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
857
858
859         /* write the request */
860         make_spoolss_q_addprinterdriver (&q, server, level, ctr);
861
862         /* Marshall data and send request */
863         if (!spoolss_io_q_addprinterdriver ("", &q, &qbuf, 0) ||
864             !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTERDRIVER, &qbuf, &rbuf)) 
865         {
866                 return NT_STATUS_UNSUCCESSFUL;
867         }
868
869                 
870         /* Unmarshall response */
871         if (!spoolss_io_r_addprinterdriver ("", &r, &rbuf, 0))
872         {
873                 return NT_STATUS_UNSUCCESSFUL;
874         }
875                 
876         /* Return output parameters */
877         result = r.status;
878
879         return result;  
880 }
881
882 /**********************************************************************
883  * Install a printer 
884  */
885 uint32 cli_spoolss_addprinterex (
886         struct cli_state        *cli, 
887         uint32                  level,
888         PRINTER_INFO_CTR        *ctr
889 )
890 {
891         prs_struct                      qbuf, rbuf;
892         SPOOL_Q_ADDPRINTEREX            q;
893         SPOOL_R_ADDPRINTEREX            r;
894         uint32                          result;
895         fstring                         server,
896                                         client,
897                                         user;
898
899         ZERO_STRUCT(q);
900         ZERO_STRUCT(r);
901
902         slprintf (client, sizeof(fstring), "\\\\%s", cli->desthost);
903         strupper (client);
904         slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
905         strupper (server);
906         fstrcpy  (user, cli->user_name);
907         
908
909         /* Initialise input parameters */
910         prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
911         prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
912
913
914         /* write the request */
915         make_spoolss_q_addprinterex (&q, server, client, user, level, ctr);
916
917         /* Marshall data and send request */
918         if (!spoolss_io_q_addprinterex ("", &q, &qbuf, 0) ||
919             !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTEREX, &qbuf, &rbuf)) 
920         {
921                 return NT_STATUS_UNSUCCESSFUL;
922         }
923
924                 
925         /* Unmarshall response */
926         if (!spoolss_io_r_addprinterex ("", &r, &rbuf, 0))
927         {
928                 return NT_STATUS_UNSUCCESSFUL;
929         }
930                 
931         /* Return output parameters */
932         result = r.status;
933
934         return result;  
935 }
936
937