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