When re-writing tdb version numbers as little endian int32, we must
[ira/wip.git] / source3 / libsmb / cli_spoolss.c
1 /* 
2    Unix SMB/Netbios implementation.
3    RPC pipe client
4
5    Copyright (C) Gerald Carter                2001,
6    Copyright (C) Tim Potter                   2000-2001,
7    Copyright (C) Andrew Tridgell              1994-2000,
8    Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
9    Copyright (C) Jean-Francois Micouleau      1999-2000.
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 2 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, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 /** @defgroup spoolss SPOOLSS - NT printing routines
29  *  @ingroup rpc_client
30  *
31  * @{
32  **/
33
34 /** Return a handle to the specified printer or print server.
35  *
36  * @param cli              Pointer to client state structure which is open
37  * on the SPOOLSS pipe.
38  *
39  * @param mem_ctx          Pointer to an initialised talloc context.
40  *
41  * @param printername      The name of the printer or print server to be
42  * opened in UNC format.
43  *
44  * @param datatype         Specifies the default data type for the printer. 
45  * 
46  * @param access_required  The access rights requested on the printer or
47  * print server.
48  * 
49  * @param station          The UNC name of the requesting workstation.
50  * 
51  * @param username         The name of the user requesting the open.
52  *
53  * @param pol              Returned policy handle.
54  */
55
56 WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
57                                    char *printername, char *datatype, 
58                                    uint32 access_required, char *station, 
59                                    char *username, POLICY_HND *pol)
60 {
61         prs_struct qbuf, rbuf;
62         SPOOL_Q_OPEN_PRINTER_EX q;
63         SPOOL_R_OPEN_PRINTER_EX r;
64         WERROR result = W_ERROR(ERRgeneral);
65
66         ZERO_STRUCT(q);
67         ZERO_STRUCT(r);
68
69         /* Initialise parse structures */
70
71         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
72         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
73
74         /* Initialise input parameters */
75
76         make_spoolss_q_open_printer_ex(&q, printername, datatype,
77                                        access_required, station, username);
78         
79         /* Marshall data and send request */
80
81         if (!spoolss_io_q_open_printer_ex("", &q, &qbuf, 0) ||
82             !rpc_api_pipe_req(cli, SPOOLSS_OPENPRINTEREX, &qbuf, &rbuf))
83                 goto done;
84
85         /* Unmarshall response */
86
87         if (!spoolss_io_r_open_printer_ex("", &r, &rbuf, 0))
88                 goto done;
89
90         /* Return output parameters */
91
92         result = r.status;
93
94         if (W_ERROR_IS_OK(result))
95                 *pol = r.handle;
96
97  done:
98         prs_mem_free(&qbuf);
99         prs_mem_free(&rbuf);
100
101         return result;
102 }
103
104 /** Close a printer handle
105  *
106  * @param cli              Pointer to client state structure which is open
107  * on the SPOOLSS pipe.
108  *
109  * @param mem_ctx          Pointer to an initialised talloc context.
110  *
111  * @param pol              Policy handle of printer or print server to close.
112  */
113
114 WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
115                                  POLICY_HND *pol)
116 {
117         prs_struct qbuf, rbuf;
118         SPOOL_Q_CLOSEPRINTER q;
119         SPOOL_R_CLOSEPRINTER r;
120         WERROR result = W_ERROR(ERRgeneral);
121
122         ZERO_STRUCT(q);
123         ZERO_STRUCT(r);
124
125         /* Initialise parse structures */
126
127         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
128         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
129
130         /* Initialise input parameters */
131
132         make_spoolss_q_closeprinter(&q, pol);
133         
134         /* Marshall data and send request */
135
136         if (!spoolss_io_q_closeprinter("", &q, &qbuf, 0) ||
137             !rpc_api_pipe_req(cli, SPOOLSS_CLOSEPRINTER, &qbuf, &rbuf))
138                 goto done;
139
140         /* Unmarshall response */
141
142         if (!spoolss_io_r_closeprinter("", &r, &rbuf, 0))
143                 goto done;
144
145         /* Return output parameters */
146
147         result = r.status;
148
149         if (W_ERROR_IS_OK(result))
150                 *pol = r.handle;
151
152  done:
153         prs_mem_free(&qbuf);
154         prs_mem_free(&rbuf);
155
156         return result;
157 }
158
159 /* Initialize a spoolss NEW_BUFFER */
160
161 static void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
162 {
163         buffer->ptr = (size != 0);
164         buffer->size = size;
165         buffer->string_at_end = size;
166         prs_init(&buffer->prs, size, ctx, MARSHALL);
167         buffer->struct_start = prs_offset(&buffer->prs);
168 }
169
170 /* Decode various printer info levels - perhaps this should live in
171    parse_spoolss.c? */
172
173 static void decode_printer_info_0(
174         TALLOC_CTX *mem_ctx,
175         NEW_BUFFER *buffer, 
176         uint32 returned, 
177         PRINTER_INFO_0 **info
178 )
179 {
180         uint32 i;
181         PRINTER_INFO_0  *inf;
182
183         inf=(PRINTER_INFO_0 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_0));
184
185         buffer->prs.data_offset=0;
186
187         for (i=0; i<returned; i++) {
188                 smb_io_printer_info_0("", buffer, &inf[i], 0);
189         }
190
191         *info=inf;
192 }
193
194 static void decode_printer_info_1(
195         TALLOC_CTX *mem_ctx,
196         NEW_BUFFER *buffer, 
197         uint32 returned, 
198         PRINTER_INFO_1 **info
199 )
200 {
201         uint32 i;
202         PRINTER_INFO_1  *inf;
203
204         inf=(PRINTER_INFO_1 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_1));
205
206         buffer->prs.data_offset=0;
207
208         for (i=0; i<returned; i++) {
209                 smb_io_printer_info_1("", buffer, &inf[i], 0);
210         }
211
212         *info=inf;
213 }
214
215 static void decode_printer_info_2(
216         TALLOC_CTX *mem_ctx,
217         NEW_BUFFER *buffer, 
218         uint32 returned, 
219         PRINTER_INFO_2 **info
220 )
221 {
222         uint32 i;
223         PRINTER_INFO_2  *inf;
224
225         inf=(PRINTER_INFO_2 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_2));
226
227         buffer->prs.data_offset=0;
228
229         for (i=0; i<returned; i++) {
230                 /* a little initialization as we go */
231                 inf[i].secdesc = NULL;
232                 smb_io_printer_info_2("", buffer, &inf[i], 0);
233         }
234
235         *info=inf;
236 }
237
238 static void decode_printer_info_3(
239         TALLOC_CTX *mem_ctx,
240         NEW_BUFFER *buffer, 
241         uint32 returned, 
242         PRINTER_INFO_3 **info
243 )
244 {
245         uint32 i;
246         PRINTER_INFO_3  *inf;
247
248         inf=(PRINTER_INFO_3 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_3));
249
250         buffer->prs.data_offset=0;
251
252         for (i=0; i<returned; i++) {
253                 inf[i].secdesc = NULL;
254                 smb_io_printer_info_3("", buffer, &inf[i], 0);
255         }
256
257         *info=inf;
258 }
259
260 /**********************************************************************
261  Decode a PORT_INFO_1 struct from a NEW_BUFFER 
262 **********************************************************************/
263 static void decode_port_info_1(
264         TALLOC_CTX *mem_ctx,
265         NEW_BUFFER *buffer, 
266         uint32 returned, 
267         PORT_INFO_1 **info
268 )
269 {
270         uint32 i;
271         PORT_INFO_1 *inf;
272
273         inf=(PORT_INFO_1*)talloc(mem_ctx, returned*sizeof(PORT_INFO_1));
274
275         prs_set_offset(&buffer->prs, 0);
276
277         for (i=0; i<returned; i++) {
278                 smb_io_port_info_1("", buffer, &(inf[i]), 0);
279         }
280
281         *info=inf;
282 }
283
284 /**********************************************************************
285  Decode a PORT_INFO_2 struct from a NEW_BUFFER 
286 **********************************************************************/
287 static void decode_port_info_2(
288         TALLOC_CTX *mem_ctx,
289         NEW_BUFFER *buffer, 
290         uint32 returned, 
291         PORT_INFO_2 **info)
292 {
293         uint32 i;
294         PORT_INFO_2 *inf;
295
296         inf=(PORT_INFO_2*)talloc(mem_ctx, returned*sizeof(PORT_INFO_2));
297
298         prs_set_offset(&buffer->prs, 0);
299
300         for (i=0; i<returned; i++) {
301                 smb_io_port_info_2("", buffer, &(inf[i]), 0);
302         }
303
304         *info=inf;
305 }
306
307 static void decode_printer_driver_1(
308         TALLOC_CTX *mem_ctx,
309         NEW_BUFFER *buffer, 
310         uint32 returned, 
311         DRIVER_INFO_1 **info
312 )
313 {
314         uint32 i;
315         DRIVER_INFO_1 *inf;
316
317         inf=(DRIVER_INFO_1 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_1));
318
319         buffer->prs.data_offset=0;
320
321         for (i=0; i<returned; i++) {
322                 smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0);
323         }
324
325         *info=inf;
326 }
327
328 static void decode_printer_driver_2(
329         TALLOC_CTX *mem_ctx,
330         NEW_BUFFER *buffer, 
331         uint32 returned, 
332         DRIVER_INFO_2 **info
333 )
334 {
335         uint32 i;
336         DRIVER_INFO_2 *inf;
337
338         inf=(DRIVER_INFO_2 *)talloc(mem_ctx, 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         TALLOC_CTX *mem_ctx,
351         NEW_BUFFER *buffer, 
352         uint32 returned, 
353         DRIVER_INFO_3 **info
354 )
355 {
356         uint32 i;
357         DRIVER_INFO_3 *inf;
358
359         inf=(DRIVER_INFO_3 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_3));
360
361         buffer->prs.data_offset=0;
362
363         for (i=0; i<returned; i++) {
364                 smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0);
365         }
366
367         *info=inf;
368 }
369
370 static void decode_printerdriverdir_1 (
371         TALLOC_CTX *mem_ctx,
372         NEW_BUFFER *buffer, 
373         uint32 returned, 
374         DRIVER_DIRECTORY_1 **info
375 )
376 {
377         DRIVER_DIRECTORY_1 *inf;
378  
379         inf=(DRIVER_DIRECTORY_1 *)talloc(mem_ctx, sizeof(DRIVER_DIRECTORY_1));
380
381         prs_set_offset(&buffer->prs, 0);
382
383         smb_io_driverdir_1("", buffer, inf, 0);
384  
385         *info=inf;
386 }
387
388 /** Enumerate printers on a print server.
389  *
390  * @param cli              Pointer to client state structure which is open
391  *                         on the SPOOLSS pipe.
392  * @param mem_ctx          Pointer to an initialised talloc context.
393  *
394  * @param offered          Buffer size offered in the request.
395  * @param needed           Number of bytes needed to complete the request.
396  *                         may be NULL.
397  *
398  * @param flags            Selected from PRINTER_ENUM_* flags.
399  * @param level            Request information level.
400  *
401  * @param num_printers     Pointer to number of printers returned.  May be
402  *                         NULL.
403  * @param ctr              Return structure for printer information.  May
404  *                         be NULL.
405  */
406
407 WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
408                                  uint32 offered, uint32 *needed,
409                                  uint32 flags, uint32 level,
410                                  uint32 *num_printers, PRINTER_INFO_CTR *ctr)
411 {
412         prs_struct qbuf, rbuf;
413         SPOOL_Q_ENUMPRINTERS q;
414         SPOOL_R_ENUMPRINTERS r;
415         NEW_BUFFER buffer;
416         WERROR result = W_ERROR(ERRgeneral);
417         fstring server;
418
419         ZERO_STRUCT(q);
420         ZERO_STRUCT(r);
421
422         fstrcpy (server, cli->desthost);
423         strupper (server);
424         
425         /* Initialise input parameters */
426
427         init_buffer(&buffer, offered, mem_ctx);
428
429         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
430         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
431
432         make_spoolss_q_enumprinters(&q, flags, server, level, &buffer, 
433                                     offered);
434
435         /* Marshall data and send request */
436         
437         if (!spoolss_io_q_enumprinters("", &q, &qbuf, 0) ||
438             !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERS, &qbuf, &rbuf))
439                 goto done;
440
441         /* Unmarshall response */
442
443         if (spoolss_io_r_enumprinters("", &r, &rbuf, 0)) {
444                 if (needed)
445                         *needed = r.needed;
446         }
447         
448         result = r.status;
449
450         /* Return output parameters */
451
452         if (!W_ERROR_IS_OK(r.status))
453                 goto done;
454
455         if (num_printers)
456                 *num_printers = r.returned;
457
458         if (!ctr)
459                 goto done;
460
461         switch (level) {
462         case 1:
463                 decode_printer_info_1(mem_ctx, r.buffer, r.returned, 
464                                       &ctr->printers_1);
465                 break;
466         case 2:
467                 decode_printer_info_2(mem_ctx, r.buffer, r.returned, 
468                                       &ctr->printers_2);
469                 break;
470         case 3:
471                 decode_printer_info_3(mem_ctx, r.buffer, r.returned, 
472                                       &ctr->printers_3);
473                 break;
474         }                       
475         
476  done:
477         prs_mem_free(&qbuf);
478         prs_mem_free(&rbuf);
479
480         return result;  
481 }
482
483 /** Enumerate printer ports on a print server.
484  *
485  * @param cli              Pointer to client state structure which is open
486  *                         on the SPOOLSS pipe.
487  * @param mem_ctx          Pointer to an initialised talloc context.
488  *
489  * @param offered          Buffer size offered in the request.
490  * @param needed           Number of bytes needed to complete the request.
491  *                         May be NULL.
492  *
493  * @param level            Requested information level.
494  *
495  * @param num_ports        Pointer to number of ports returned.  May be NULL.
496  * @param ctr              Pointer to structure holding port information.
497  *                         May be NULL.
498  */
499
500 WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx,
501                               uint32 offered, uint32 *needed,
502                               uint32 level, int *num_ports, PORT_INFO_CTR *ctr)
503 {
504         prs_struct qbuf, rbuf;
505         SPOOL_Q_ENUMPORTS q;
506         SPOOL_R_ENUMPORTS r;
507         NEW_BUFFER buffer;
508         WERROR result = W_ERROR(ERRgeneral);
509         fstring server;
510
511         ZERO_STRUCT(q);
512         ZERO_STRUCT(r);
513
514         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
515         strupper (server);
516
517         /* Initialise input parameters */
518         
519         init_buffer(&buffer, offered, mem_ctx);
520         
521         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
522         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
523         
524         make_spoolss_q_enumports(&q, server, level, &buffer, offered);
525         
526         /* Marshall data and send request */
527
528         if (!spoolss_io_q_enumports("", &q, &qbuf, 0) ||
529             !rpc_api_pipe_req(cli, SPOOLSS_ENUMPORTS, &qbuf, &rbuf))
530                 goto done;
531
532         /* Unmarshall response */
533
534         if (spoolss_io_r_enumports("", &r, &rbuf, 0)) {
535                 if (needed)
536                         *needed = r.needed;
537         }
538                 
539         result = r.status;
540
541         /* Return output parameters */
542
543         if (!W_ERROR_IS_OK(result))
544                 goto done;
545
546         if (num_ports)
547                 *num_ports = r.returned;
548
549         if (!ctr)
550                 goto done;
551         
552         switch (level) {
553         case 1:
554                 decode_port_info_1(mem_ctx, r.buffer, r.returned, 
555                                    &ctr->port.info_1);
556                 break;
557         case 2:
558                 decode_port_info_2(mem_ctx, r.buffer, r.returned, 
559                                    &ctr->port.info_2);
560                 break;
561         }                       
562
563  done:
564         prs_mem_free(&qbuf);
565         prs_mem_free(&rbuf);
566         
567         return result;  
568 }
569
570 /* Get printer info */
571 NTSTATUS cli_spoolss_getprinter(
572         struct cli_state *cli, 
573         TALLOC_CTX *mem_ctx,
574         POLICY_HND *pol,
575         uint32 level, 
576         PRINTER_INFO_CTR *ctr
577 )
578 {
579         prs_struct qbuf, rbuf;
580         SPOOL_Q_GETPRINTER q;
581         SPOOL_R_GETPRINTER r;
582         NEW_BUFFER buffer;
583         uint32 needed = 100;
584         NTSTATUS result;
585
586         ZERO_STRUCT(q);
587         ZERO_STRUCT(r);
588
589         do {
590                 /* Initialise input parameters */
591
592                 init_buffer(&buffer, needed, mem_ctx);
593
594                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
595                 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
596
597                 make_spoolss_q_getprinter(mem_ctx, &q, pol, level, &buffer, needed);
598
599                 /* Marshall data and send request */
600                 if (!spoolss_io_q_getprinter("", &q, &qbuf, 0) ||
601                     !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTER, &qbuf, &rbuf)) 
602                 {
603                         result = NT_STATUS_UNSUCCESSFUL;
604                         goto done;
605                 }
606
607                 /* Unmarshall response */
608                 if (spoolss_io_r_getprinter("", &r, &rbuf, 0)) {
609                         needed = r.needed;
610                 }
611                 
612                 /* Return output parameters */
613                 result = werror_to_ntstatus(r.status);
614                 if (NT_STATUS_IS_OK(result)) {
615                         switch (level) {
616                         case 0:
617                                 decode_printer_info_0(mem_ctx, r.buffer, 1, &ctr->printers_0);
618                                 break;
619                         case 1:
620                                 decode_printer_info_1(mem_ctx, r.buffer, 1, &ctr->printers_1);
621                                 break;
622                         case 2:
623                                 decode_printer_info_2(mem_ctx, r.buffer, 1, &ctr->printers_2);
624                                 break;
625                         case 3:
626                                 decode_printer_info_3(mem_ctx, r.buffer, 1, &ctr->printers_3);
627                                 break;
628                         }                       
629                 }
630
631         done:
632                 prs_mem_free(&qbuf);
633                 prs_mem_free(&rbuf);
634
635         } while (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_BUFFER_TOO_SMALL));
636
637         return result;  
638 }
639
640 /**********************************************************************
641  * Set printer info 
642  */
643 NTSTATUS cli_spoolss_setprinter(
644         struct cli_state *cli, 
645         TALLOC_CTX *mem_ctx,
646         POLICY_HND *pol,
647         uint32 level, 
648         PRINTER_INFO_CTR *ctr,
649         uint32 command
650 )
651 {
652         prs_struct qbuf, rbuf;
653         SPOOL_Q_SETPRINTER q;
654         SPOOL_R_SETPRINTER r;
655         NTSTATUS result = NT_STATUS_ACCESS_DENIED;
656
657         ZERO_STRUCT(q);
658         ZERO_STRUCT(r);
659
660         /* Initialise input parameters */
661         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
662         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
663                 
664         make_spoolss_q_setprinter(mem_ctx, &q, pol, level, ctr, command);
665
666         /* Marshall data and send request */
667         if (!spoolss_io_q_setprinter("", &q, &qbuf, 0) ||
668             !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTER, &qbuf, &rbuf)) 
669         {
670                 result = NT_STATUS_ACCESS_DENIED;
671                 goto done;
672         }
673
674         /* Unmarshall response */
675         if (!spoolss_io_r_setprinter("", &r, &rbuf, 0)) 
676         {
677                 goto done;
678         }
679         
680         result = werror_to_ntstatus(r.status);
681                 
682 done:
683         prs_mem_free(&qbuf);
684         prs_mem_free(&rbuf);
685
686
687         return result;  
688 }
689
690 /** Get installed printer drivers for a given printer
691  *
692  * @param cli              Pointer to client state structure which is open
693  * on the SPOOLSS pipe.
694  *
695  * @param mem_ctx          Pointer to an initialised talloc context.
696  *
697  * @param offered          Buffer size offered in the request.
698  * @param needed           Number of bytes needed to complete the request.
699  *                         may be NULL.
700  *
701  * @param pol              Pointer to an open policy handle for the printer
702  *                         opened with cli_spoolss_open_printer_ex().
703  * @param level            Requested information level.
704  * @param env              The print environment or archictecture.  This is
705  *                         "Windows NT x86" for NT4.
706  * @param ctr              Returned printer driver information.
707  */
708
709 WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, 
710                                     TALLOC_CTX *mem_ctx, 
711                                     uint32 offered, uint32 *needed,
712                                     POLICY_HND *pol, uint32 level, 
713                                     char *env, PRINTER_DRIVER_CTR *ctr)
714 {
715         prs_struct qbuf, rbuf;
716         SPOOL_Q_GETPRINTERDRIVER2 q;
717         SPOOL_R_GETPRINTERDRIVER2 r;
718         NEW_BUFFER buffer;
719         WERROR result = W_ERROR(ERRgeneral);
720         fstring server;
721
722         ZERO_STRUCT(q);
723         ZERO_STRUCT(r);
724
725         fstrcpy (server, cli->desthost);
726         strupper (server);
727
728         /* Initialise input parameters */
729
730         init_buffer(&buffer, offered, mem_ctx);
731
732         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
733         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
734
735         make_spoolss_q_getprinterdriver2(&q, pol, env, level, 2, 2,
736                                          &buffer, offered);
737
738         /* Marshall data and send request */
739
740         if (!spoolss_io_q_getprinterdriver2 ("", &q, &qbuf, 0) ||
741             !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVER2, &qbuf, &rbuf)) 
742                 goto done;
743
744         /* Unmarshall response */
745
746         if (spoolss_io_r_getprinterdriver2 ("", &r, &rbuf, 0)) {
747                 if (needed)
748                         *needed = r.needed;
749         }
750
751         result = r.status;
752
753         /* Return output parameters */
754
755         if (!W_ERROR_IS_OK(result))
756                 goto done;
757
758         if (!ctr)
759                 goto done;
760
761         switch (level) {
762         case 1:
763                 decode_printer_driver_1(mem_ctx, r.buffer, 1, &ctr->info1);
764                 break;
765         case 2:
766                 decode_printer_driver_2(mem_ctx, r.buffer, 1, &ctr->info2);
767                 break;
768         case 3:
769                 decode_printer_driver_3(mem_ctx, r.buffer, 1, &ctr->info3);
770                 break;
771         }                       
772
773  done:
774         prs_mem_free(&qbuf);
775         prs_mem_free(&rbuf);
776                 
777         return result;  
778 }
779
780 /**********************************************************************
781  * Get installed printer drivers for a given printer
782  */
783 NTSTATUS cli_spoolss_enumprinterdrivers (
784         struct cli_state        *cli, 
785         TALLOC_CTX              *mem_ctx,
786         uint32                  level,
787         char*                   env,
788         uint32                  *returned,
789         PRINTER_DRIVER_CTR      *ctr
790 )
791 {
792         prs_struct                      qbuf, rbuf;
793         SPOOL_Q_ENUMPRINTERDRIVERS      q;
794         SPOOL_R_ENUMPRINTERDRIVERS      r;
795         NEW_BUFFER                      buffer;
796         uint32                          needed = 0;
797         NTSTATUS                        result;
798         fstring                         server;
799
800         ZERO_STRUCT(q);
801         ZERO_STRUCT(r);
802
803         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
804         strupper (server);
805
806         do 
807         {
808                 /* Initialise input parameters */
809                 init_buffer(&buffer, needed, mem_ctx);
810
811                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
812                 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
813
814
815                 /* write the request */
816                 make_spoolss_q_enumprinterdrivers(&q, server, env, level, &buffer, needed);
817
818                 /* Marshall data and send request */
819                 if (!spoolss_io_q_enumprinterdrivers ("", &q, &qbuf, 0) ||
820                     !rpc_api_pipe_req (cli, SPOOLSS_ENUMPRINTERDRIVERS, &qbuf, &rbuf)) 
821                 {
822                         result = NT_STATUS_UNSUCCESSFUL;
823                         goto done;
824                 }
825
826                 /* Unmarshall response */
827                 if (spoolss_io_r_enumprinterdrivers ("", &r, &rbuf, 0)) 
828                 {
829                         needed = r.needed;
830                 }
831                 
832                 /* Return output parameters */
833                 result = werror_to_ntstatus(r.status);
834                 if (NT_STATUS_IS_OK(result) && 
835                     (r.returned != 0))
836                 {
837                         *returned = r.returned;
838
839                         switch (level) 
840                         {
841                         case 1:
842                                 decode_printer_driver_1(mem_ctx, r.buffer, r.returned, &ctr->info1);
843                                 break;
844                         case 2:
845                                 decode_printer_driver_2(mem_ctx, r.buffer, r.returned, &ctr->info2);
846                                 break;
847                         case 3:
848                                 decode_printer_driver_3(mem_ctx, r.buffer, r.returned, &ctr->info3);
849                                 break;
850                         }                       
851                 }
852
853         done:
854                 prs_mem_free(&qbuf);
855                 prs_mem_free(&rbuf);
856
857         } while (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_BUFFER_TOO_SMALL));
858
859         return result;  
860 }
861
862
863 /**********************************************************************
864  * Get installed printer drivers for a given printer
865  */
866 NTSTATUS cli_spoolss_getprinterdriverdir (
867         struct cli_state        *cli, 
868         TALLOC_CTX              *mem_ctx,
869         uint32                  level,
870         char*                   env,
871         DRIVER_DIRECTORY_CTR    *ctr
872 )
873 {
874         prs_struct                      qbuf, rbuf;
875         SPOOL_Q_GETPRINTERDRIVERDIR     q;
876         SPOOL_R_GETPRINTERDRIVERDIR     r;
877         NEW_BUFFER                      buffer;
878         uint32                          needed = 100;
879         NTSTATUS                        result;
880         fstring                         server;
881
882         ZERO_STRUCT(q);
883         ZERO_STRUCT(r);
884
885         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
886         strupper (server);
887
888         do 
889         {
890                 /* Initialise input parameters */
891                 init_buffer(&buffer, needed, mem_ctx);
892
893                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
894                 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
895
896
897                 /* write the request */
898                 make_spoolss_q_getprinterdriverdir(&q, server, env, level, &buffer, needed);
899
900                 /* Marshall data and send request */
901                 if (!spoolss_io_q_getprinterdriverdir ("", &q, &qbuf, 0) ||
902                     !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVERDIRECTORY, &qbuf, &rbuf)) 
903                 {
904                         result = NT_STATUS_UNSUCCESSFUL;
905                         goto done;
906                 }
907
908                 /* Unmarshall response */
909                 if (spoolss_io_r_getprinterdriverdir ("", &r, &rbuf, 0)) 
910                 {
911                         needed = r.needed;
912                 }
913                 
914                 /* Return output parameters */
915                 result = werror_to_ntstatus(r.status);
916                 if (NT_STATUS_IS_OK(result))
917                 {
918                         switch (level) 
919                         {
920                         case 1:
921                                 decode_printerdriverdir_1(mem_ctx, r.buffer, 1, &ctr->info1);
922                                 break;
923                         }                       
924                 }
925
926         done:
927                 prs_mem_free(&qbuf);
928                 prs_mem_free(&rbuf);
929
930         } while (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_BUFFER_TOO_SMALL));
931
932         return result;  
933 }
934
935 /**********************************************************************
936  * Install a printer driver
937  */
938 NTSTATUS cli_spoolss_addprinterdriver (
939         struct cli_state        *cli, 
940         TALLOC_CTX              *mem_ctx,
941         uint32                  level,
942         PRINTER_DRIVER_CTR      *ctr
943 )
944 {
945         prs_struct                      qbuf, rbuf;
946         SPOOL_Q_ADDPRINTERDRIVER        q;
947         SPOOL_R_ADDPRINTERDRIVER        r;
948         NTSTATUS                        result = NT_STATUS_UNSUCCESSFUL;
949         fstring                         server;
950
951         ZERO_STRUCT(q);
952         ZERO_STRUCT(r);
953         
954         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
955         strupper (server);
956
957         /* Initialise input parameters */
958         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
959         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
960
961
962         /* write the request */
963         make_spoolss_q_addprinterdriver (mem_ctx, &q, server, level, ctr);
964
965         /* Marshall data and send request */
966         result = NT_STATUS_UNSUCCESSFUL;
967         if (!spoolss_io_q_addprinterdriver ("", &q, &qbuf, 0) ||
968             !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTERDRIVER, &qbuf, &rbuf)) 
969         {
970                 goto done;
971         }
972
973                 
974         /* Unmarshall response */
975         result = NT_STATUS_UNSUCCESSFUL;
976         if (!spoolss_io_r_addprinterdriver ("", &r, &rbuf, 0))
977         {
978                 goto done;
979         }
980                 
981         /* Return output parameters */
982         result = werror_to_ntstatus(r.status);
983
984 done:
985         prs_mem_free(&qbuf);
986         prs_mem_free(&rbuf);
987         
988         return result;  
989 }
990
991 /**********************************************************************
992  * Install a printer 
993  */
994 NTSTATUS cli_spoolss_addprinterex (
995         struct cli_state        *cli, 
996         TALLOC_CTX              *mem_ctx,
997         uint32                  level,
998         PRINTER_INFO_CTR        *ctr
999 )
1000 {
1001         prs_struct                      qbuf, rbuf;
1002         SPOOL_Q_ADDPRINTEREX            q;
1003         SPOOL_R_ADDPRINTEREX            r;
1004         NTSTATUS                        result;
1005         fstring                         server,
1006                                         client,
1007                                         user;
1008
1009         ZERO_STRUCT(q);
1010         ZERO_STRUCT(r);
1011
1012         slprintf (client, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1013         strupper (client);
1014         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1015         strupper (server);
1016         fstrcpy  (user, cli->user_name);
1017         
1018
1019         /* Initialise input parameters */
1020         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1021         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1022
1023
1024         /* write the request */
1025         make_spoolss_q_addprinterex (mem_ctx, &q, server, client, user, level, ctr);
1026
1027         /* Marshall data and send request */
1028         result = NT_STATUS_UNSUCCESSFUL;
1029         if (!spoolss_io_q_addprinterex ("", &q, &qbuf, 0) ||
1030             !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTEREX, &qbuf, &rbuf)) 
1031         {
1032                 goto done;
1033         }
1034
1035                 
1036         /* Unmarshall response */
1037         result = NT_STATUS_UNSUCCESSFUL;
1038         if (!spoolss_io_r_addprinterex ("", &r, &rbuf, 0))
1039         {
1040                 goto done;
1041         }
1042                 
1043         /* Return output parameters */
1044         result = werror_to_ntstatus(r.status);
1045
1046 done:
1047         prs_mem_free(&qbuf);
1048         prs_mem_free(&rbuf);
1049
1050         return result;  
1051 }
1052
1053 /**********************************************************************
1054  * Delete a Printer Driver from the server (does not remove 
1055  * the driver files
1056  */
1057 NTSTATUS cli_spoolss_deleteprinterdriver (
1058         struct cli_state        *cli, 
1059         TALLOC_CTX              *mem_ctx,
1060         char                    *arch,
1061         char                    *driver
1062 )
1063 {
1064         prs_struct                      qbuf, rbuf;
1065         SPOOL_Q_DELETEPRINTERDRIVER     q;
1066         SPOOL_R_DELETEPRINTERDRIVER     r;
1067         NTSTATUS                        result;
1068         fstring                         server;
1069
1070         ZERO_STRUCT(q);
1071         ZERO_STRUCT(r);
1072
1073
1074         /* Initialise input parameters */
1075         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1076         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1077
1078         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1079         strupper (server);
1080
1081         /* write the request */
1082         make_spoolss_q_deleteprinterdriver (mem_ctx, &q, server, arch, driver);
1083
1084         /* Marshall data and send request */
1085         result = NT_STATUS_UNSUCCESSFUL;
1086         if (!spoolss_io_q_deleteprinterdriver ("", &q, &qbuf, 0) ||
1087             !rpc_api_pipe_req (cli,SPOOLSS_DELETEPRINTERDRIVER , &qbuf, &rbuf)) 
1088         {
1089                 goto done;
1090         }
1091
1092                 
1093         /* Unmarshall response */
1094         result = NT_STATUS_UNSUCCESSFUL;
1095         if (!spoolss_io_r_deleteprinterdriver ("", &r, &rbuf, 0))
1096         {
1097                 goto done;
1098         }
1099                 
1100         /* Return output parameters */
1101         result = werror_to_ntstatus(r.status);
1102
1103 done:
1104         prs_mem_free(&qbuf);
1105         prs_mem_free(&rbuf);
1106
1107         return result;  
1108 }
1109
1110 /* Get print processor directory */
1111
1112 NTSTATUS cli_spoolss_getprintprocessordirectory(struct cli_state *cli,
1113                                                 TALLOC_CTX *mem_ctx,
1114                                                 char *name,
1115                                                 char *environment,
1116                                                 fstring procdir)
1117 {
1118         prs_struct qbuf, rbuf;
1119         SPOOL_Q_GETPRINTPROCESSORDIRECTORY q;
1120         SPOOL_R_GETPRINTPROCESSORDIRECTORY r;
1121         NTSTATUS result;
1122         int level = 1;
1123         NEW_BUFFER buffer;
1124         uint32 needed = 100;
1125
1126         ZERO_STRUCT(q);
1127         ZERO_STRUCT(r);
1128
1129         /* Initialise parse structures */
1130
1131
1132         /* Initialise input parameters */
1133
1134         do {
1135                 init_buffer(&buffer, needed, mem_ctx);
1136
1137                 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1138                 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1139                 
1140                 make_spoolss_q_getprintprocessordirectory(&q, name, 
1141                                                           environment, level,
1142                                                           &buffer, needed);
1143
1144                 /* Marshall data and send request */
1145
1146                 if (!spoolss_io_q_getprintprocessordirectory("", &q, &qbuf, 0) ||
1147                     !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTPROCESSORDIRECTORY, &qbuf, &rbuf)) {
1148                         result = NT_STATUS_UNSUCCESSFUL;
1149                         goto done;
1150                 }
1151                 
1152                 /* Unmarshall response */
1153                 
1154                 if (!spoolss_io_r_getprintprocessordirectory("", &r, &rbuf, 0)) {
1155                         result = NT_STATUS_UNSUCCESSFUL;
1156                         goto done;
1157                 }
1158
1159                 /* Return output parameters */
1160                 
1161                 result = werror_to_ntstatus(r.status);
1162
1163         } while (NT_STATUS_V(result) == 
1164                  NT_STATUS_V(NT_STATUS_BUFFER_TOO_SMALL));
1165
1166  done:
1167         prs_mem_free(&qbuf);
1168         prs_mem_free(&rbuf);
1169
1170         return result;
1171 }
1172
1173 /** @} **/