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