FIxed some unmarshalling problems with relstr and unistr arrays
[samba.git] / source / rpc_client / msrpc_spoolss.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NT Domain Authentication SMB / MSRPC client
5    Copyright (C) Andrew Tridgell              1994-2000
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
7    Copyright (C) Jean-Francois Micouleau      1999-2000
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "nterr.h"
26 #include "rpc_parse.h"
27 #include "rpc_client.h"
28 #include "rpcclient.h"
29
30 extern int DEBUGLEVEL;
31
32 #define DEBUG_TESTING
33
34 extern FILE* out_hnd;
35
36 extern struct user_creds *usr_creds;
37
38 /********************************************************************
39 initialize a spoolss NEW_BUFFER.
40 ********************************************************************/
41 void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
42 {
43         buffer->ptr = (size!=0)? 1:0;
44         buffer->size=size;
45         buffer->string_at_end=size;
46         prs_init(&buffer->prs, size, 4, ctx, MARSHALL);
47         buffer->struct_start = prs_offset(&buffer->prs);
48 }
49
50 static void decode_printer_info_0(NEW_BUFFER *buffer, uint32 returned, 
51                                   PRINTER_INFO_0 **info)
52 {
53         uint32 i;
54         PRINTER_INFO_0  *inf;
55
56         inf=(PRINTER_INFO_0 *)malloc(returned*sizeof(PRINTER_INFO_0));
57
58         buffer->prs.data_offset=0;
59
60         for (i=0; i<returned; i++) {
61                 new_smb_io_printer_info_0("", buffer, &(inf[i]), 0);
62         }
63
64         *info=inf;
65 }
66
67 static void decode_printer_info_1(NEW_BUFFER *buffer, uint32 returned, 
68                                   PRINTER_INFO_1 **info)
69 {
70         uint32 i;
71         PRINTER_INFO_1  *inf;
72
73         inf=(PRINTER_INFO_1 *)malloc(returned*sizeof(PRINTER_INFO_1));
74
75         buffer->prs.data_offset=0;
76
77         for (i=0; i<returned; i++) {
78                 new_smb_io_printer_info_1("", buffer, &(inf[i]), 0);
79         }
80
81         *info=inf;
82 }
83
84 static void decode_printer_info_2(NEW_BUFFER *buffer, uint32 returned, 
85                                   PRINTER_INFO_2 **info)
86 {
87         uint32 i;
88         PRINTER_INFO_2  *inf;
89
90         inf=(PRINTER_INFO_2 *)malloc(returned*sizeof(PRINTER_INFO_2));
91
92         buffer->prs.data_offset=0;
93
94         for (i=0; i<returned; i++) {
95                 /* a little initialization as we go */
96                 inf[i].secdesc = NULL;
97                 new_smb_io_printer_info_2("", buffer, &(inf[i]), 0);
98         }
99
100         *info=inf;
101 }
102
103 static void decode_printer_info_3(NEW_BUFFER *buffer, uint32 returned, 
104                                   PRINTER_INFO_3 **info)
105 {
106         uint32 i;
107         PRINTER_INFO_3  *inf;
108
109         inf=(PRINTER_INFO_3 *)malloc(returned*sizeof(PRINTER_INFO_3));
110
111         buffer->prs.data_offset=0;
112
113         for (i=0; i<returned; i++) {
114                 new_smb_io_printer_info_3("", buffer, &(inf[i]), 0);
115         }
116
117         *info=inf;
118 }
119
120 static void decode_printer_driver_1(NEW_BUFFER *buffer, uint32 returned, 
121                                     DRIVER_INFO_1 **info)
122 {
123         uint32 i;
124         DRIVER_INFO_1 *inf;
125
126         inf=(DRIVER_INFO_1 *)malloc(returned*sizeof(DRIVER_INFO_1));
127
128         buffer->prs.data_offset=0;
129
130         for (i=0; i<returned; i++) {
131                 new_smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0);
132         }
133
134         *info=inf;
135 }
136
137 static void decode_printer_driver_2(NEW_BUFFER *buffer, uint32 returned, 
138                                     DRIVER_INFO_2 **info)
139 {
140         uint32 i;
141         DRIVER_INFO_2 *inf;
142
143         inf=(DRIVER_INFO_2 *)malloc(returned*sizeof(DRIVER_INFO_2));
144
145         buffer->prs.data_offset=0;
146
147         for (i=0; i<returned; i++) {
148                 new_smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0);
149         }
150
151         *info=inf;
152 }
153
154 static void decode_printer_driver_3(NEW_BUFFER *buffer, uint32 returned, 
155                                     DRIVER_INFO_3 **info)
156 {
157         uint32 i;
158         DRIVER_INFO_3 *inf;
159
160         inf=(DRIVER_INFO_3 *)malloc(returned*sizeof(DRIVER_INFO_3));
161
162         buffer->prs.data_offset=0;
163
164         for (i=0; i<returned; i++) {
165                 new_smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0);
166         }
167
168         *info=inf;
169 }
170
171 static void decode_printerdriverdir_info_1(NEW_BUFFER *buffer, DRIVER_DIRECTORY_1 *info)
172 {
173 /*      DRIVER_DIRECTORY_1 *inf;
174
175         inf=(DRIVER_DIRECTORY_1 *)malloc(returned*sizeof(DRIVER_DIRECTORY_1));
176 */
177         prs_set_offset(&buffer->prs, 0);
178
179         new_smb_io_driverdir_1("", buffer, info, 0);
180
181 /*      *info=inf;*/
182 }
183
184 /**********************************************************************
185  Decode a PORT_INFO_1 struct from a NEW_BUFFER 
186 **********************************************************************/
187 void decode_port_info_1(NEW_BUFFER *buffer, uint32 returned, 
188                         PORT_INFO_1 **info)
189 {
190         uint32 i;
191         PORT_INFO_1 *inf;
192
193         inf=(PORT_INFO_1*)malloc(returned*sizeof(PORT_INFO_1));
194
195         prs_set_offset(&buffer->prs, 0);
196
197         for (i=0; i<returned; i++) {
198                 new_smb_io_port_info_1("", buffer, &(inf[i]), 0);
199         }
200
201         *info=inf;
202 }
203
204 /**********************************************************************
205  Decode a PORT_INFO_2 struct from a NEW_BUFFER 
206 **********************************************************************/
207 void decode_port_info_2(NEW_BUFFER *buffer, uint32 returned, 
208                         PORT_INFO_2 **info)
209 {
210         uint32 i;
211         PORT_INFO_2 *inf;
212
213         inf=(PORT_INFO_2*)malloc(returned*sizeof(PORT_INFO_2));
214
215         prs_set_offset(&buffer->prs, 0);
216
217         for (i=0; i<returned; i++) {
218                 new_smb_io_port_info_2("", buffer, &(inf[i]), 0);
219         }
220
221         *info=inf;
222 }
223
224
225 /****************************************************************************
226 nt spoolss query
227 ****************************************************************************/
228 BOOL msrpc_spoolss_enum_printers(char* srv_name, uint32 flags, 
229                                  uint32 level, PRINTER_INFO_CTR ctr)
230 {
231         uint32 status;
232         NEW_BUFFER buffer;
233         uint32 needed;
234         uint32 returned;
235         TALLOC_CTX *mem_ctx = NULL;
236         
237         if ((mem_ctx=talloc_init()) == NULL)
238         {
239                 DEBUG(0,("msrpc_spoolss_enum_printers: talloc_init failed!\n"));
240                 return False;
241         }
242         init_buffer(&buffer, 0, mem_ctx);
243         
244         /* send a NULL buffer first */
245         status=spoolss_enum_printers(flags, srv_name, level, &buffer, 0, 
246                                      &needed, &returned);
247         
248         if (status==ERROR_INSUFFICIENT_BUFFER) {
249                 init_buffer(&buffer, needed, mem_ctx);
250                 status=spoolss_enum_printers(flags, srv_name, level, &buffer, 
251                                              needed, &needed, &returned);
252         }
253         
254         if (status!=NT_STATUS_NO_PROBLEMO)
255         {
256                 DEBUG(0,("spoolss_enum_printers: %s\n", get_nt_error_msg(status)));
257                 if (mem_ctx)
258                         talloc_destroy(mem_ctx);
259                 return False;
260         }
261                 
262         /* is there anything to process? */
263         if (returned != 0)
264         {
265                 switch (level) {
266                 case 1:
267                         decode_printer_info_1(&buffer, returned, &(ctr.printers_1));
268                         break;
269                 case 2:
270                         decode_printer_info_2(&buffer, returned, &(ctr.printers_2));
271                         break;
272                 case 3:
273                         decode_printer_info_3(&buffer, returned, &(ctr.printers_3));
274                         break;
275                 }               
276
277                 display_printer_info_ctr(out_hnd, ACTION_HEADER   , level, returned, ctr);
278                 display_printer_info_ctr(out_hnd, ACTION_ENUMERATE, level, returned, ctr);
279                 display_printer_info_ctr(out_hnd, ACTION_FOOTER   , level, returned, ctr);
280         }
281
282         if (mem_ctx)
283                 talloc_destroy(mem_ctx);
284                 
285         return True;
286 }
287
288 /****************************************************************************
289 nt spoolss query
290 ****************************************************************************/
291 BOOL msrpc_spoolss_enum_ports(char* srv_name, 
292                                  uint32 level, PORT_INFO_CTR *ctr)
293 {
294         uint32 status;
295         NEW_BUFFER buffer;
296         uint32 needed;
297         uint32 returned;
298         TALLOC_CTX *mem_ctx = NULL;
299         
300         if ((mem_ctx=talloc_init()) == NULL)
301         {
302                 DEBUG(0,("msrpc_spoolss_enum_ports: talloc_init failed!\n"));
303                 return False;
304         }
305         
306         init_buffer(&buffer, 0, mem_ctx);
307         
308         /* send a NULL buffer first */
309         status=spoolss_enum_ports(srv_name, level, &buffer, 0, 
310                                      &needed, &returned);
311         
312         if (status==ERROR_INSUFFICIENT_BUFFER) {
313                 init_buffer(&buffer, needed, mem_ctx);
314                 status=spoolss_enum_ports(srv_name, level, &buffer, 
315                                           needed, &needed, &returned);
316         }
317         
318         report(out_hnd, "\tstatus:[%d (%x)]\n", status, status);
319         
320         if (status!=NT_STATUS_NO_PROBLEMO)
321         {
322                 if (mem_ctx)
323                         talloc_destroy(mem_ctx);
324                 return False;
325         }
326                 
327         /* is there anything to process? */
328         if (returned != 0)
329         {
330                 switch (level) {
331                 case 1:
332                         decode_port_info_1(&buffer, returned, &ctr->port.info_1);
333                         break;
334                 case 2:
335                         decode_port_info_2(&buffer, returned, &ctr->port.info_2);
336                         break;
337                 default:
338                         DEBUG(0,("Unable to decode unknown PORT_INFO_%d\n", level));
339                         break;
340                 }               
341
342                 display_port_info_ctr(out_hnd, ACTION_HEADER   , level, returned, ctr);
343                 display_port_info_ctr(out_hnd, ACTION_ENUMERATE, level, returned, ctr);
344                 display_port_info_ctr(out_hnd, ACTION_FOOTER   , level, returned, ctr);
345         }
346         if (mem_ctx)
347                 talloc_destroy(mem_ctx);
348
349
350
351         return True;
352 }
353
354 /****************************************************************************
355 nt spoolss query
356 ****************************************************************************/
357 uint32 msrpc_spoolss_getprinterdata( const char* printer_name,
358                                 const char* station,
359                                 const char* user_name,
360                                 const char* value_name,
361                                 uint32 *type,
362                                 NEW_BUFFER *buffer,
363                                 void *fn)
364 {
365         POLICY_HND hnd;
366         uint32 status;
367         uint32 needed;
368         uint32 size;
369         char *data;
370         UNISTR2 uni_val_name;
371         TALLOC_CTX *mem_ctx = NULL;
372         
373         DEBUG(4,("spoolgetdata - printer: %s server: %s user: %s value: %s\n",
374                 printer_name, station, user_name, value_name));
375
376         if(!spoolss_open_printer_ex( printer_name, 0, 0, station, user_name,
377                                 &hnd))
378         {
379                 return NT_STATUS_ACCESS_DENIED;
380         }
381
382         init_unistr2(&uni_val_name, value_name, 0);
383         size = 0;
384         data = NULL;
385
386         if ((mem_ctx=talloc_init()) == NULL)
387         {
388                 DEBUG(0,("msrpc_spoolss_getprinterdata: talloc_init failed!\n"));
389                 return False;
390         }
391         init_buffer(buffer, size, mem_ctx);
392
393         status = spoolss_getprinterdata(&hnd, &uni_val_name, size, type, &size,
394                         data, &needed);
395
396         if (status == ERROR_INSUFFICIENT_BUFFER)
397         {
398                 size = needed;
399                 init_buffer(buffer, size, mem_ctx);
400                 data = prs_data_p(&buffer->prs);
401                 status = spoolss_getprinterdata(&hnd, &uni_val_name,
402                                 size, type, &size,
403                                 data, &needed);
404         }
405         
406         if (mem_ctx)
407                 talloc_destroy(mem_ctx);
408
409         if (status != NT_STATUS_NO_PROBLEMO) 
410         {
411                 if (!spoolss_closeprinter(&hnd))
412                         return NT_STATUS_ACCESS_DENIED;
413                 return status;
414         }
415
416 #if  0
417         if (fn != NULL)
418                 fn(printer_name, station, level, returned, *ctr);
419 #endif
420
421         return status;
422 }
423
424 /****************************************************************************
425 nt spoolss query
426 ****************************************************************************/
427 BOOL msrpc_spoolss_enum_jobs( const char* printer_name,
428                                 const char* station, const char* user_name,
429                                 uint32 level,
430                                 void ***ctr, JOB_INFO_FN(fn))
431 {
432         POLICY_HND hnd;
433         uint32 status;
434         NEW_BUFFER buffer;
435         uint32 needed;
436         uint32 returned;
437         uint32 firstjob=0;
438         uint32 numofjobs=0xffff;
439         TALLOC_CTX *mem_ctx = NULL;
440         
441         DEBUG(4,("spoolopen - printer: %s server: %s user: %s\n",
442                 printer_name, station, user_name));
443
444         if(!spoolss_open_printer_ex( printer_name, 0, 0, station, user_name, &hnd))
445                 return False;
446
447         if ((mem_ctx=talloc_init()) == NULL)
448         {
449                 DEBUG(0,("msrpc_spoolss_enum_jobs: talloc_init failed!\n"));
450                 return False;
451         }
452         init_buffer(&buffer, 0, mem_ctx);
453         status = spoolss_enum_jobs(&hnd, firstjob, numofjobs, level, 
454                                    &buffer, 0, &needed, &returned);
455
456         if (status == ERROR_INSUFFICIENT_BUFFER)
457         {
458                 init_buffer(&buffer, needed, mem_ctx);
459                 status = spoolss_enum_jobs( &hnd, firstjob, numofjobs, level, 
460                                             &buffer, needed, &needed, &returned);
461         }
462
463         if (mem_ctx)
464                 talloc_destroy(mem_ctx);
465                 
466         if (status!=NT_STATUS_NO_PROBLEMO) {
467                 if (!spoolss_closeprinter(&hnd))
468                         return False;
469                 return False;
470         }
471
472         if (fn != NULL)
473                 fn(printer_name, station, level, returned, *ctr);
474
475         return True;
476 }
477
478
479 /****************************************************************************
480 nt spoolss query
481 ****************************************************************************/
482 BOOL msrpc_spoolss_enum_printerdata( const char* printer_name, 
483                 const char* station, const char* user_name )
484 {
485         POLICY_HND hnd;
486         uint32 status;
487         uint32 idx;
488         uint32 valuelen;
489         uint16 *value;
490         uint32 rvaluelen;
491         uint32 type;
492         uint32 datalen;
493         uint8  *data;
494         uint32 rdatalen;
495         uint32 maxvaluelen;
496         uint32 maxdatalen;
497         
498         DEBUG(4,("msrpc_spoolss_enum_printerdata - printer: %s\n", printer_name));
499
500         if(!spoolss_open_printer_ex( printer_name, 0, 0, station, user_name, &hnd))
501                 return False;
502
503         
504         idx=0;
505         valuelen=0;
506         rvaluelen=0;
507         type=0;
508         datalen=0;
509         rdatalen=0;
510         
511         status = spoolss_enum_printerdata(&hnd, idx, &valuelen, value, 
512                                           &rvaluelen, &type, &datalen, 
513                                           data, &rdatalen);
514
515         DEBUG(4,("spoolenum_printerdata - got size: biggest value:[%d], biggest data:[%d]\n", rvaluelen, rdatalen));
516
517         maxvaluelen=valuelen=rvaluelen;
518         maxdatalen=datalen=rdatalen;
519
520         value=(uint16 *)malloc(valuelen*sizeof(uint16));
521         data=(uint8 *)malloc(datalen*sizeof(uint8));
522
523         display_printer_enumdata(out_hnd, ACTION_HEADER, idx, valuelen, 
524                                  value, rvaluelen, type, datalen, data, rdatalen);
525         
526         do {
527                 valuelen=maxvaluelen;
528                 datalen=maxdatalen;
529
530                 status = spoolss_enum_printerdata(&hnd, idx, &valuelen, 
531                                                   value, &rvaluelen, &type, 
532                                                   &datalen, data, &rdatalen);
533                 display_printer_enumdata(out_hnd, ACTION_ENUMERATE, idx, 
534                                          valuelen, value, rvaluelen, type, 
535                                          datalen, data, rdatalen);
536                 idx++;
537
538         } while (status != 0x0103); /* NO_MORE_ITEMS */
539
540         display_printer_enumdata(out_hnd, ACTION_FOOTER, idx, valuelen, 
541                                  value, rvaluelen, type, datalen, data, rdatalen);
542
543         
544         if (status!=NT_STATUS_NO_PROBLEMO) {
545                 /* 
546                  * the check on this if statement is redundant
547                  * since is the status is bad we're going to 
548                  * return False anyways.  The caller will be 
549                  * unable to determine if there really was a problem
550                  * with the spoolss_closeprinter() call  --jerry
551                  */
552                 spoolss_closeprinter(&hnd);
553                 return False;
554         }
555         
556         return True;
557 }
558
559 /****************************************************************************
560 nt spoolss query
561 ****************************************************************************/
562 BOOL msrpc_spoolss_getprinter( const char* printer_name, const uint32 level,
563                 const char* station, const char* user_name,
564                 PRINTER_INFO_CTR ctr)
565 {
566         POLICY_HND hnd;
567         uint32 status=0;
568         NEW_BUFFER buffer;
569         uint32 needed=1000;
570         TALLOC_CTX *mem_ctx = NULL;
571         
572         DEBUG(4,("spoolenum_getprinter - printer: %s\n", printer_name));
573
574         if(!spoolss_open_printer_ex( printer_name, "", PRINTER_ALL_ACCESS, station, user_name, &hnd))
575                 return False;
576
577         if ((mem_ctx=talloc_init()) == NULL)
578         {
579                 DEBUG(0,("msrpc_spoolss_getprinter: talloc_init failed!\n"));
580                 return False;
581         }
582         init_buffer(&buffer, needed, mem_ctx);
583
584         status = spoolss_getprinter(&hnd, level, &buffer, needed, &needed);
585
586         if (status==ERROR_INSUFFICIENT_BUFFER) {
587                 init_buffer(&buffer, needed, mem_ctx);
588                 status = spoolss_getprinter(&hnd, level, &buffer, needed, &needed);
589         }
590
591         report(out_hnd, "\tstatus:[%d (%x)]\n", status, status);
592
593         if (status!=NT_STATUS_NO_PROBLEMO)
594         {
595                 if (mem_ctx)
596                         talloc_destroy(mem_ctx);
597                 return False;
598         }
599
600         switch (level) {
601         case 0:
602                 decode_printer_info_0(&buffer, 1, &(ctr.printers_0));
603                 break;
604         case 1:
605                 decode_printer_info_1(&buffer, 1, &(ctr.printers_1));
606                 break;
607         case 2:
608                 decode_printer_info_2(&buffer, 1, &(ctr.printers_2));
609                 break;
610         case 3:
611                 decode_printer_info_3(&buffer, 1, &(ctr.printers_3));
612                 break;
613         }
614
615         display_printer_info_ctr(out_hnd, ACTION_HEADER   , level, 1, ctr);
616         display_printer_info_ctr(out_hnd, ACTION_ENUMERATE, level, 1, ctr);
617         display_printer_info_ctr(out_hnd, ACTION_FOOTER   , level, 1, ctr);
618
619         if (mem_ctx)
620                 talloc_destroy(mem_ctx);
621
622         if (status!=NT_STATUS_NO_PROBLEMO) {
623                 if (!spoolss_closeprinter(&hnd))
624                         return False;
625                 return False;
626         }
627
628         return True;
629 }
630
631 /****************************************************************************
632 nt spoolss query
633 ****************************************************************************/
634 BOOL msrpc_spoolss_getprinterdriver( const char* printer_name,
635                 const char *environment, const uint32 level,
636                 const char* station, const char* user_name,
637                 PRINTER_DRIVER_CTR ctr)
638 {
639         POLICY_HND hnd;
640         uint32 status=0;
641         NEW_BUFFER buffer;
642         uint32 needed;
643         TALLOC_CTX *mem_ctx = NULL;
644         
645         DEBUG(4,("msrpc_spoolss_enum_getprinterdriver - printer: %s\n", printer_name));
646
647         if(!spoolss_open_printer_ex( printer_name, "", PRINTER_ALL_ACCESS, station, user_name, &hnd))
648                 return False;
649
650         if ((mem_ctx=talloc_init()) == NULL)
651         {
652                 DEBUG(0,("msrpc_spoolss_getprinterdriver: talloc_init failed!\n"));
653                 return False;
654         }
655         init_buffer(&buffer, 0, mem_ctx);
656
657         status = spoolss_getprinterdriver(&hnd, environment, level, &buffer, 0, &needed);
658
659         if (status==ERROR_INSUFFICIENT_BUFFER) {
660                 init_buffer(&buffer, needed, mem_ctx);
661                 status = spoolss_getprinterdriver(&hnd, environment, level, &buffer, needed, &needed);
662         }
663
664         report(out_hnd, "\tstatus:[%d (%x)]\n", status, status);
665
666         if (status!=NT_STATUS_NO_PROBLEMO)
667         {
668                 if (mem_ctx)
669                         talloc_destroy(mem_ctx);
670                 return False;
671         }
672
673         switch (level) {
674         case 1:
675                 decode_printer_driver_1(&buffer, 1, &(ctr.info1));
676                 break;
677         case 2:
678                 decode_printer_driver_2(&buffer, 1, &(ctr.info2));
679                 break;
680         case 3:
681                 decode_printer_driver_3(&buffer, 1, &(ctr.info3));
682                 break;
683         }
684
685         display_printer_driver_ctr(out_hnd, ACTION_HEADER   , level, 1, ctr);
686         display_printer_driver_ctr(out_hnd, ACTION_ENUMERATE, level, 1, ctr);
687         display_printer_driver_ctr(out_hnd, ACTION_FOOTER   , level, 1, ctr);
688
689         if (mem_ctx)
690                 talloc_destroy(mem_ctx);
691                 
692         if (status!=NT_STATUS_NO_PROBLEMO) {
693                 if (!spoolss_closeprinter(&hnd))
694                         return False;
695                 return False;
696         }
697
698         return True;
699 }
700
701 /****************************************************************************
702 nt spoolss query
703 ****************************************************************************/
704 BOOL msrpc_spoolss_enumprinterdrivers( const char* srv_name,
705                 const char *environment, const uint32 level,
706                 PRINTER_DRIVER_CTR ctr)
707 {
708         uint32 status=0;
709         NEW_BUFFER buffer;
710         uint32 needed;
711         uint32 returned;
712         TALLOC_CTX *mem_ctx = NULL;
713         
714         DEBUG(4,("msrpc_spoolss_enum_enumprinterdrivers - server: %s\n", srv_name));
715
716         if ((mem_ctx=talloc_init()) == NULL)
717         {
718                 DEBUG(0,("msrpc_spoolss_enumprinterdrivers: talloc_init failed!\n"));
719                 return False;
720         }
721         init_buffer(&buffer, 0, mem_ctx);
722
723         status = spoolss_enum_printerdrivers(srv_name, environment,
724                                 level, &buffer, 0, &needed, &returned);
725
726         if (status == ERROR_INSUFFICIENT_BUFFER)
727         {
728                 init_buffer(&buffer, needed, mem_ctx);
729                 status = spoolss_enum_printerdrivers( srv_name, environment,
730                                 level, &buffer, needed, &needed, &returned);
731         }
732
733         report(out_hnd, "\tstatus:[%d (%x)]\n", status, status);
734
735         if (status!=NT_STATUS_NO_PROBLEMO)
736         {
737                 if (mem_ctx)
738                         talloc_destroy(mem_ctx);
739                 return False;
740         }
741
742         switch (level)
743         {
744                 case 1:
745                         decode_printer_driver_1(&buffer, returned, &(ctr.info1));
746                         break;
747                 case 2:
748                         decode_printer_driver_2(&buffer, returned, &(ctr.info2));
749                         break;
750                 case 3:
751                         decode_printer_driver_3(&buffer, returned, &(ctr.info3));
752                         break;
753         }
754
755         display_printer_driver_ctr(out_hnd, ACTION_HEADER   , level, returned, ctr);
756         display_printer_driver_ctr(out_hnd, ACTION_ENUMERATE, level, returned, ctr);
757         display_printer_driver_ctr(out_hnd, ACTION_FOOTER   , level, returned, ctr);
758
759         if (mem_ctx)
760                 talloc_destroy(mem_ctx);
761                 
762         return True;
763 }
764
765 /****************************************************************************
766 nt spoolss query
767 ****************************************************************************/
768 BOOL msrpc_spoolss_getprinterdriverdir(char* srv_name, char* env_name, uint32 level, DRIVER_DIRECTORY_CTR ctr)
769 {
770         uint32 status;
771         NEW_BUFFER buffer;
772         uint32 needed;
773         TALLOC_CTX *mem_ctx = NULL;
774         
775         if ((mem_ctx=talloc_init()) == NULL)
776         {
777                 DEBUG(0,("msrpc_spoolss_getprinterdriverdir: talloc_init failed!\n"));
778                 return False;
779         }
780         init_buffer(&buffer, 0, mem_ctx);
781
782         /* send a NULL buffer first */
783         status=spoolss_getprinterdriverdir(srv_name, env_name, level, &buffer, 0, &needed);
784
785         if (status==ERROR_INSUFFICIENT_BUFFER) {
786                 init_buffer(&buffer, needed, mem_ctx);
787                 status=spoolss_getprinterdriverdir(srv_name, env_name, level, &buffer, needed, &needed);
788         }
789
790         report(out_hnd, "\tstatus:[%d (%x)]\n", status, status);
791
792         if (status!=NT_STATUS_NO_PROBLEMO)
793         {
794                 if (mem_ctx)
795                         talloc_destroy(mem_ctx);
796                 return False;
797         }
798
799         switch (level) {
800         case 1:
801                 decode_printerdriverdir_info_1(&buffer, &(ctr.driver.info_1));
802                 break;
803         }
804
805         display_printerdriverdir_info_ctr(out_hnd, ACTION_HEADER   , level, ctr);
806         display_printerdriverdir_info_ctr(out_hnd, ACTION_ENUMERATE, level, ctr);
807         display_printerdriverdir_info_ctr(out_hnd, ACTION_FOOTER   , level, ctr);
808         
809         if (mem_ctx)
810                 talloc_destroy(mem_ctx);
811
812         return True;
813 }
814