* Added EnumPorts()
[amitay/samba.git] / source3 / rpc_client / cli_spoolss.c
1 /*
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7  *  Copyright (C) Paul Ashton                  1997-2000,
8  *  Copyright (C) Jean Francois Micouleau      1998-2000,
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #include "includes.h"
26 #include "rpc_parse.h"
27 #include "rpc_client.h"
28 #include "nterr.h"
29
30 extern int DEBUGLEVEL;
31
32 /****************************************************************************
33 do a SPOOLSS Enum Printer Drivers
34 ****************************************************************************/
35 uint32 spoolss_enum_printerdrivers(const char * srv_name,
36                                 const char *environment,
37                                 uint32 level,
38                              NEW_BUFFER *buffer, uint32 offered,
39                              uint32 *needed, uint32 *returned)
40 {
41         prs_struct rbuf;
42         prs_struct buf;
43         SPOOL_Q_ENUMPRINTERDRIVERS q_o;
44         SPOOL_R_ENUMPRINTERDRIVERS r_o;
45
46         struct cli_connection *con = NULL;
47
48         if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con))
49                 return False;
50
51         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
52         prs_init(&rbuf, 0, 4, UNMARSHALL);
53
54         /* create and send a MSRPC command with api SPOOLSS_ENUM_PRINTERS */
55
56         DEBUG(5,("SPOOLSS Enum Printer Drivers (Server: %s Environment: %s level: %d)\n",
57                                 srv_name, environment, level));
58
59         make_spoolss_q_enumprinterdrivers(&q_o, srv_name, environment,
60                                 level, buffer, offered);
61
62         /* turn parameters into data stream */
63         if (!spoolss_io_q_enumprinterdrivers("", &q_o, &buf, 0) ) {
64                 prs_mem_free(&rbuf);
65                 prs_mem_free(&buf );
66
67                 cli_connection_unlink(con);
68         }
69
70         if(!rpc_con_pipe_req(con, SPOOLSS_ENUMPRINTERDRIVERS, &buf, &rbuf)) {
71                 prs_mem_free(&rbuf);
72                 prs_mem_free(&buf );
73
74                 cli_connection_unlink(con);
75         }
76
77         prs_mem_free(&buf);
78         ZERO_STRUCT(r_o);
79
80         prs_switch_type(&buffer->prs, UNMARSHALL);
81         prs_set_offset(&buffer->prs, 0);
82         r_o.buffer=buffer;
83
84         if(!new_spoolss_io_r_enumprinterdrivers("", &r_o, &rbuf, 0)) {
85                 prs_mem_free(&rbuf);
86                 cli_connection_unlink(con);
87         }
88
89         *needed=r_o.needed;
90         *returned=r_o.returned;
91
92         prs_mem_free(&rbuf);
93         prs_mem_free(&buf );
94
95         cli_connection_unlink(con);
96
97         return r_o.status;
98 }
99
100 /****************************************************************************
101 do a SPOOLSS Enum Printers
102 ****************************************************************************/
103 uint32 spoolss_enum_printers(uint32 flags, fstring srv_name, uint32 level,
104                              NEW_BUFFER *buffer, uint32 offered,
105                              uint32 *needed, uint32 *returned)
106 {
107         prs_struct rbuf;
108         prs_struct buf;
109         SPOOL_Q_ENUMPRINTERS q_o;
110         SPOOL_R_ENUMPRINTERS r_o;
111
112         struct cli_connection *con = NULL;
113
114         if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con))
115                 return False;
116
117         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
118         prs_init(&rbuf, 0, 4, UNMARSHALL);
119
120         /* create and send a MSRPC command with api SPOOLSS_ENUM_PRINTERS */
121
122         DEBUG(5,("SPOOLSS Enum Printers (Server: %s level: %d)\n", srv_name, level));
123
124         make_spoolss_q_enumprinters(&q_o, flags, "", level, buffer, offered);
125
126         /* turn parameters into data stream */
127         if (!spoolss_io_q_enumprinters("", &q_o, &buf, 0) ) {
128                 prs_mem_free(&rbuf);
129                 prs_mem_free(&buf );
130
131                 cli_connection_unlink(con);
132         }
133
134         if(!rpc_con_pipe_req(con, SPOOLSS_ENUMPRINTERS, &buf, &rbuf)) {
135                 prs_mem_free(&rbuf);
136                 prs_mem_free(&buf );
137
138                 cli_connection_unlink(con);
139         }
140
141         prs_mem_free(&buf );
142         ZERO_STRUCT(r_o);
143
144         prs_switch_type(&buffer->prs, UNMARSHALL);
145         prs_set_offset(&buffer->prs, 0);
146         r_o.buffer=buffer;
147
148         if(!new_spoolss_io_r_enumprinters("", &r_o, &rbuf, 0)) {
149                 prs_mem_free(&rbuf);
150                 cli_connection_unlink(con);
151         }
152
153         *needed=r_o.needed;
154         *returned=r_o.returned;
155
156         prs_mem_free(&rbuf);
157         prs_mem_free(&buf );
158
159         cli_connection_unlink(con);
160
161         return r_o.status;
162 }
163
164 /****************************************************************************
165 do a SPOOLSS Enum Ports
166 ****************************************************************************/
167 uint32 spoolss_enum_ports(fstring srv_name, uint32 level,
168                              NEW_BUFFER *buffer, uint32 offered,
169                              uint32 *needed, uint32 *returned)
170 {
171         prs_struct rbuf;
172         prs_struct buf;
173         SPOOL_Q_ENUMPORTS q_o;
174         SPOOL_R_ENUMPORTS r_o;
175
176         struct cli_connection *con = NULL;
177
178         if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con))
179                 return False;
180
181         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
182         prs_init(&rbuf, 0, 4, UNMARSHALL);
183
184         /* create and send a MSRPC command with api SPOOLSS_ENUMPORTS */
185
186         DEBUG(5,("SPOOLSS Enum Ports (Server: %s level: %d)\n", srv_name, level));
187
188         make_spoolss_q_enumports(&q_o, "", level, buffer, offered);
189
190         /* turn parameters into data stream */
191         if (!spoolss_io_q_enumports("", &q_o, &buf, 0) ) {
192                 prs_mem_free(&rbuf);
193                 prs_mem_free(&buf );
194
195                 cli_connection_unlink(con);
196         }
197
198         if(!rpc_con_pipe_req(con, SPOOLSS_ENUMPORTS, &buf, &rbuf)) {
199                 prs_mem_free(&rbuf);
200                 prs_mem_free(&buf );
201
202                 cli_connection_unlink(con);
203         }
204
205         prs_mem_free(&buf );
206         ZERO_STRUCT(r_o);
207
208         prs_switch_type(&buffer->prs, UNMARSHALL);
209         prs_set_offset(&buffer->prs, 0);
210         r_o.buffer=buffer;
211
212         if(!new_spoolss_io_r_enumports("", &r_o, &rbuf, 0)) {
213                 prs_mem_free(&rbuf);
214                 cli_connection_unlink(con);
215         }
216
217         *needed=r_o.needed;
218         *returned=r_o.returned;
219
220         prs_mem_free(&rbuf);
221         prs_mem_free(&buf );
222
223         cli_connection_unlink(con);
224
225         return r_o.status;
226 }
227
228 /****************************************************************************
229 do a SPOOLSS Enum Jobs
230 ****************************************************************************/
231 uint32 spoolss_enum_jobs(const POLICY_HND *hnd, uint32 firstjob, uint32 numofjobs,
232                          uint32 level, NEW_BUFFER *buffer, uint32 offered,
233                          uint32 *needed, uint32 *returned)
234 {
235         prs_struct rbuf;
236         prs_struct buf;
237         SPOOL_Q_ENUMJOBS q_o;
238         SPOOL_R_ENUMJOBS r_o;
239
240         if (hnd == NULL)
241                 return NT_STATUS_INVALID_PARAMETER;
242
243         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
244         prs_init(&rbuf, 0, 4, UNMARSHALL);
245
246         /* create and send a MSRPC command with api SPOOLSS_ENUMJOBS */
247
248         DEBUG(5,("SPOOLSS Enum Jobs level: %d)\n", level));
249
250         make_spoolss_q_enumjobs(&q_o, hnd, firstjob, numofjobs, level, buffer, offered);
251
252         /* turn parameters into data stream */
253         if (!spoolss_io_q_enumjobs("", &q_o, &buf, 0)) {
254                 prs_mem_free(&rbuf);
255                 prs_mem_free(&buf );
256         }
257
258         if(!rpc_hnd_pipe_req(hnd, SPOOLSS_ENUMJOBS, &buf, &rbuf))
259         {
260                 prs_mem_free(&rbuf);
261                 prs_mem_free(&buf );
262         }
263
264         ZERO_STRUCT(r_o);
265         prs_mem_free(&buf );
266
267         r_o.buffer=buffer;
268
269         if(!spoolss_io_r_enumjobs("", &r_o, &rbuf, 0)) {
270                 prs_mem_free(&rbuf);
271         }
272
273         *needed=r_o.needed;
274         *returned=r_o.returned;
275
276         prs_mem_free(&rbuf);
277         prs_mem_free(&buf );
278
279         return r_o.status;
280 }
281
282 /***************************************************************************
283 do a SPOOLSS Enum printer datas
284 ****************************************************************************/
285 uint32 spoolss_enum_printerdata(const POLICY_HND *hnd, uint32 idx,
286                         uint32 *valuelen, uint16 *value, uint32 *rvaluelen,
287                         uint32 *type,
288                         uint32 *datalen, uint8 *data, uint32 *rdatalen)
289 {
290         prs_struct rbuf;
291         prs_struct buf;
292         SPOOL_Q_ENUMPRINTERDATA q_o;
293         SPOOL_R_ENUMPRINTERDATA r_o;
294
295         if (hnd == NULL)
296                 return NT_STATUS_INVALID_PARAMETER;
297
298         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
299         prs_init(&rbuf, 0, 4, UNMARSHALL);
300
301         /* create and send a MSRPC command with api SPOOLSS_ENUMJOBS */
302
303         DEBUG(5,("SPOOLSS Enum Printer data)\n"));
304
305         make_spoolss_q_enumprinterdata(&q_o, hnd, idx, *valuelen, *datalen);
306
307         /* turn parameters into data stream */
308         if (!spoolss_io_q_enumprinterdata("", &q_o, &buf, 0)) {
309                 prs_mem_free(&rbuf);
310                 prs_mem_free(&buf );
311         }
312
313         if(!rpc_hnd_pipe_req(hnd, SPOOLSS_ENUMPRINTERDATA, &buf, &rbuf)) {
314                 prs_mem_free(&rbuf);
315                 prs_mem_free(&buf );
316         }
317
318         ZERO_STRUCT(r_o);
319         prs_mem_free(&buf );
320
321         r_o.data=data;
322         r_o.value=value;
323
324         if(!spoolss_io_r_enumprinterdata("", &r_o, &rbuf, 0)) {
325                 prs_mem_free(&rbuf);
326         }
327
328         *valuelen=r_o.valuesize;
329         *rvaluelen=r_o.realvaluesize;
330         *type=r_o.type;
331         *datalen=r_o.datasize;
332         *rdatalen=r_o.realdatasize;
333
334         prs_mem_free(&rbuf);
335         prs_mem_free(&buf );
336
337         return r_o.status;
338 }
339
340 /****************************************************************************
341 do a SPOOLSS Enum printer datas
342 ****************************************************************************/
343 uint32 spoolss_getprinter(const POLICY_HND *hnd, uint32 level,
344                              NEW_BUFFER *buffer, uint32 offered,
345                              uint32 *needed)
346 {
347         prs_struct rbuf;
348         prs_struct buf;
349         SPOOL_Q_GETPRINTER q_o;
350         SPOOL_R_GETPRINTER r_o;
351
352         if (hnd == NULL)
353                 return NT_STATUS_INVALID_PARAMETER;
354
355         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
356         prs_init(&rbuf, 0, 4, UNMARSHALL);
357
358         /* create and send a MSRPC command with api SPOOLSS_ENUMJOBS */
359
360         DEBUG(5,("SPOOLSS Enum Printer data)\n"));
361
362         make_spoolss_q_getprinter(&q_o, hnd, level, buffer, offered);
363
364         /* turn parameters into data stream */
365         if (!spoolss_io_q_getprinter("", &q_o, &buf, 0)) {
366                 prs_mem_free(&rbuf);
367                 prs_mem_free(&buf );
368         }
369
370         if(!rpc_hnd_pipe_req(hnd, SPOOLSS_GETPRINTER, &buf, &rbuf)) {
371                 prs_mem_free(&rbuf);
372                 prs_mem_free(&buf );
373         }
374
375         ZERO_STRUCT(r_o);
376         prs_mem_free(&buf );
377
378         prs_switch_type(&buffer->prs, UNMARSHALL);
379         prs_set_offset(&buffer->prs, 0);
380         r_o.buffer=buffer;
381
382         if(!spoolss_io_r_getprinter("", &r_o, &rbuf, 0)) {
383                 prs_mem_free(&rbuf);
384         }
385
386         *needed=r_o.needed;
387
388         prs_mem_free(&rbuf);
389         prs_mem_free(&buf );
390
391         return r_o.status;
392 }
393
394 /****************************************************************************
395 do a SPOOLSS Enum printer driver
396 ****************************************************************************/
397 uint32 spoolss_getprinterdriver(const POLICY_HND *hnd,
398                                 const char *environment, uint32 level,
399                                 NEW_BUFFER *buffer, uint32 offered,
400                                 uint32 *needed)
401 {
402         prs_struct rbuf;
403         prs_struct buf;
404         SPOOL_Q_GETPRINTERDRIVER2 q_o;
405         SPOOL_R_GETPRINTERDRIVER2 r_o;
406
407         if (hnd == NULL)
408                 return NT_STATUS_INVALID_PARAMETER;
409
410         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
411         prs_init(&rbuf, 0, 4, UNMARSHALL);
412
413         /* create and send a MSRPC command with api SPOOLSS_ENUMJOBS */
414
415         DEBUG(5,("SPOOLSS Enum Printer driver)\n"));
416
417         make_spoolss_q_getprinterdriver2(&q_o, hnd, environment, level, 2, 0, buffer, offered);
418
419         /* turn parameters into data stream */
420         if (!spoolss_io_q_getprinterdriver2("", &q_o, &buf, 0)) {
421                 prs_mem_free(&rbuf);
422                 prs_mem_free(&buf );
423         }
424
425         if(!rpc_hnd_pipe_req(hnd, SPOOLSS_GETPRINTERDRIVER2, &buf, &rbuf)) {
426                 prs_mem_free(&rbuf);
427                 prs_mem_free(&buf );
428         }
429
430         ZERO_STRUCT(r_o);
431         prs_mem_free(&buf );
432
433         prs_switch_type(&buffer->prs, UNMARSHALL);
434         prs_set_offset(&buffer->prs, 0);
435         r_o.buffer=buffer;
436
437         if(!spoolss_io_r_getprinterdriver2("", &r_o, &rbuf, 0)) {
438                 prs_mem_free(&rbuf);
439         }
440
441         *needed=r_o.needed;
442
443         prs_mem_free(&rbuf);
444         prs_mem_free(&buf );
445
446         return r_o.status;
447 }
448
449
450
451 /****************************************************************************
452 do a SPOOLSS Open Printer Ex
453 ****************************************************************************/
454 BOOL spoolss_open_printer_ex(  const char *printername,
455                          const char *datatype, uint32 access_required,
456                          const char *station,  const char *username,
457                         POLICY_HND *hnd)
458 {
459         prs_struct rbuf;
460         prs_struct buf;
461         SPOOL_Q_OPEN_PRINTER_EX q_o;
462         BOOL valid_pol = False;
463         fstring srv_name;
464         char *s = NULL;
465
466         struct cli_connection *con = NULL;
467
468         memset(srv_name, 0, sizeof(srv_name));
469         fstrcpy(srv_name, printername);
470
471         s = strchr(&srv_name[2], '\\');
472         if (s != NULL)
473                 *s = '\0';
474
475         if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con))
476                 return False;
477
478         if (hnd == NULL) return False;
479
480         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
481         prs_init(&rbuf, 0, 4, UNMARSHALL);
482
483         /* create and send a MSRPC command with api SPOOLSS_OPENPRINTEREX */
484
485         DEBUG(5,("SPOOLSS Open Printer Ex\n"));
486
487         make_spoolss_q_open_printer_ex(&q_o, printername, datatype,
488                                        access_required, station, username);
489
490         /* turn parameters into data stream */
491         if (spoolss_io_q_open_printer_ex("", &q_o, &buf, 0) &&
492             rpc_con_pipe_req(con, SPOOLSS_OPENPRINTEREX, &buf, &rbuf))
493         {
494                 SPOOL_R_OPEN_PRINTER_EX r_o;
495                 BOOL p = True;
496
497                 spoolss_io_r_open_printer_ex("", &r_o, &rbuf, 0);
498
499                 if (prs_offset(&rbuf)!= 0 && r_o.status != 0)
500                 {
501                         /* report error code */
502                         DEBUG(5,("SPOOLSS_OPENPRINTEREX: %s\n", get_nt_error_msg(r_o.status)));
503                         p = False;
504                 }
505
506                 if (p)
507                 {
508                         /* ok, at last: we're happy. return the policy handle */
509                         *hnd = r_o.handle;
510
511                         /* associate the handle returned with the current 
512                            state of the clienjt connection */
513                         valid_pol = RpcHndList_set_connection(hnd, con);
514
515                 }
516         }
517
518         prs_mem_free(&rbuf);
519         prs_mem_free(&buf );
520
521         return valid_pol;
522 }
523
524 /****************************************************************************
525 do a SPOOL Close
526 ****************************************************************************/
527 BOOL spoolss_closeprinter(POLICY_HND *hnd)
528 {
529         prs_struct rbuf;
530         prs_struct buf;
531         SPOOL_Q_CLOSEPRINTER q_c;
532         BOOL valid_close = False;
533
534         if (hnd == NULL) 
535                 return False;
536
537         /* create and send a MSRPC command with api SPOOLSS_CLOSEPRINTER */
538
539         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
540         prs_init(&rbuf, 0, 4, UNMARSHALL);
541
542         DEBUG(4,("SPOOL Close Printer\n"));
543
544         /* store the parameters */
545         make_spoolss_q_closeprinter(&q_c, hnd);
546
547         /* turn parameters into data stream */
548         if (spoolss_io_q_closeprinter("", &q_c, &buf, 0) &&
549             rpc_hnd_pipe_req(hnd, SPOOLSS_CLOSEPRINTER, &buf, &rbuf))
550         {
551                 SPOOL_R_CLOSEPRINTER r_c;
552
553                 spoolss_io_r_closeprinter("", &r_c, &rbuf, 0);
554
555                 if (prs_offset(&rbuf)!=0 && r_c.status != 0)
556                 {
557                         /* report error code */
558                         DEBUG(0,("SPOOL_CLOSEPRINTER: %s\n", get_nt_error_msg(r_c.status)));
559                 }
560                 else
561                         valid_close = True;
562         }
563
564         prs_mem_free(&rbuf);
565         prs_mem_free(&buf );
566
567         /* disassociate with the cli_connection */
568         RpcHndList_del_connection(hnd);
569
570         return valid_close;
571 }
572
573 /****************************************************************************
574 do a SPOOLSS Get printer datas
575 ****************************************************************************/
576 uint32 spoolss_getprinterdata(const POLICY_HND *hnd, const UNISTR2 *valuename,
577                         uint32 in_size,
578                         uint32 *type,
579                         uint32 *out_size,
580                         uint8 *data,
581                         uint32 *needed)
582 {
583         prs_struct rbuf;
584         prs_struct buf;
585         SPOOL_Q_GETPRINTERDATA q_o;
586         SPOOL_R_GETPRINTERDATA r_o;
587
588         if (hnd == NULL)
589                 return NT_STATUS_INVALID_PARAMETER;
590
591         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
592         prs_init(&rbuf, 0, 4, UNMARSHALL);
593
594         /* create and send a MSRPC command with api SPOOLSS_GETPRINTERDATA */
595
596         DEBUG(5,("SPOOLSS Get Printer data)\n"));
597
598         make_spoolss_q_getprinterdata(&q_o, hnd, valuename, in_size);
599
600         /* turn parameters into data stream */
601         if (!spoolss_io_q_getprinterdata("", &q_o, &buf, 0)) {
602                 prs_mem_free(&rbuf);
603                 prs_mem_free(&buf );
604         }
605
606         if (!rpc_hnd_pipe_req(hnd, SPOOLSS_GETPRINTERDATA, &buf, &rbuf)) {
607                 prs_mem_free(&rbuf);
608                 prs_mem_free(&buf );
609         }
610
611         ZERO_STRUCT(r_o);
612         prs_mem_free(&buf );
613
614         r_o.data=data;
615
616         if(!spoolss_io_r_getprinterdata("", &r_o, &rbuf, 0)) {
617                 prs_mem_free(&rbuf);
618         }
619
620         *type=r_o.type;
621         *out_size=r_o.size;
622         *needed=r_o.needed;
623
624         prs_mem_free(&rbuf);
625         prs_mem_free(&buf );
626
627         return r_o.status;
628 }
629
630 /****************************************************************************
631 do a SPOOLSS Get Printer Driver Direcotry
632 ****************************************************************************/
633 uint32 spoolss_getprinterdriverdir(fstring srv_name, fstring env_name, uint32 level,
634                              NEW_BUFFER *buffer, uint32 offered,
635                              uint32 *needed)
636 {
637         prs_struct rbuf;
638         prs_struct buf;
639         SPOOL_Q_GETPRINTERDRIVERDIR q_o;
640         SPOOL_R_GETPRINTERDRIVERDIR r_o;
641
642         struct cli_connection *con = NULL;
643
644         if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con))
645                 return False;
646
647         prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
648         prs_init(&rbuf, 0, 4, UNMARSHALL);
649
650         /* create and send a MSRPC command with api SPOOLSS_ENUM_PRINTERS */
651
652         DEBUG(5,("SPOOLSS GetPrinterDriverDir (Server: %s Env: %s level: %d)\n", 
653                   srv_name, env_name, level));
654
655         make_spoolss_q_getprinterdriverdir(&q_o, srv_name, env_name, level, 
656                                            buffer, offered);
657
658         /* turn parameters into data stream */
659         if (!spoolss_io_q_getprinterdriverdir("", &q_o, &buf, 0) ) {
660                 prs_mem_free(&rbuf);
661                 prs_mem_free(&buf );
662
663                 cli_connection_unlink(con);
664         }
665
666         if(!rpc_con_pipe_req(con, SPOOLSS_GETPRINTERDRIVERDIRECTORY, &buf, &rbuf)) {
667                 prs_mem_free(&rbuf);
668                 prs_mem_free(&buf );
669
670                 cli_connection_unlink(con);
671         }
672
673         prs_mem_free(&buf );
674         ZERO_STRUCT(r_o);
675
676         prs_switch_type(&buffer->prs, UNMARSHALL);
677         prs_set_offset(&buffer->prs, 0);
678         r_o.buffer=buffer;
679
680         if(!spoolss_io_r_getprinterdriverdir("", &r_o, &rbuf, 0)) {
681                 prs_mem_free(&rbuf);
682                 cli_connection_unlink(con);
683         }
684         *needed=r_o.needed;
685
686         prs_mem_free(&rbuf);
687         prs_mem_free(&buf );
688
689         cli_connection_unlink(con);
690
691         return r_o.status;
692 }
693
694