1daa7e55da6ca0459a7d43dd203dc5637d7625d0
[jra/samba/.git] / source / rpc_server / srv_spoolss_nt.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) Jean François Micouleau      1998-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
25 #include "includes.h"
26
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
29
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
32 #endif
33
34 #define PRINTER_HANDLE_IS_PRINTER       0
35 #define PRINTER_HANDLE_IS_PRINTSERVER   1
36
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer{
42         ubi_dlNode Next;
43         ubi_dlNode Prev;
44
45         BOOL open;
46         BOOL document_started;
47         BOOL page_started;
48         int jobid; /* jobid in printing backend */
49         POLICY_HND printer_hnd;
50         BOOL printer_type;
51         union {
52                 fstring printername;
53                 fstring printerservername;
54         } dev;
55         uint32 type;
56         uint32 access;
57         struct {
58                 uint32 flags;
59                 uint32 options;
60                 fstring localmachine; 
61                 uint32 printerlocal;
62                 SPOOL_NOTIFY_OPTION *option;
63         } notify;
64         struct {
65                 fstring machine;
66                 fstring user;
67         } client;
68 } Printer_entry;
69
70 typedef struct _counter_printer_0 {
71         ubi_dlNode Next;
72         ubi_dlNode Prev;
73         
74         int snum;
75         uint32 counter;
76 } counter_printer_0;
77
78 static ubi_dlList Printer_list;
79 static ubi_dlList counter_list;
80
81
82 #define OPEN_HANDLE(pnum)    ((pnum!=NULL) && (pnum->open!=False))
83
84 /* translate between internal status numbers and NT status numbers */
85 static int nt_printj_status(int v)
86 {
87         switch (v) {
88         case LPQ_PAUSED:
89                 return PRINTER_STATUS_PAUSED;
90         case LPQ_QUEUED:
91         case LPQ_SPOOLING:
92         case LPQ_PRINTING:
93                 return 0;
94         }
95         return 0;
96 }
97
98 static int nt_printq_status(int v)
99 {
100         switch (v) {
101         case LPQ_PAUSED:
102                 return PRINTER_STATUS_ERROR;
103         case LPQ_QUEUED:
104         case LPQ_SPOOLING:
105         case LPQ_PRINTING:
106                 return 0;
107         }
108         return 0;
109 }
110
111 /****************************************************************************
112   initialise printer handle states...
113 ****************************************************************************/
114 void init_printer_hnd(void)
115 {
116         ubi_dlInitList(&Printer_list);
117         ubi_dlInitList(&counter_list);
118 }
119
120 /****************************************************************************
121   create a unique printer handle
122 ****************************************************************************/
123 static void create_printer_hnd(POLICY_HND *hnd)
124 {
125         static uint32 prt_hnd_low  = 0;
126         static uint32 prt_hnd_high = 0;
127
128         if (hnd == NULL) return;
129
130         /* i severely doubt that prt_hnd_high will ever be non-zero... */
131         prt_hnd_low++;
132         if (prt_hnd_low == 0) prt_hnd_high++;
133
134         SIVAL(hnd->data, 0 , 0x0);          /* first bit must be null */
135         SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
136         SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
137         SIVAL(hnd->data, 12, time(NULL));   /* something random */
138         SIVAL(hnd->data, 16, getpid());     /* something more random */
139 }
140
141 /****************************************************************************
142   find printer index by handle
143 ****************************************************************************/
144 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
145 {
146         Printer_entry *find_printer;
147
148         find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
149
150         for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
151
152                 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0)
153                 {
154                         DEBUG(4,("Found printer handle \n"));
155                         /*dump_data(4, hnd->data, sizeof(hnd->data));*/
156                         return find_printer;
157                 }
158         }
159         
160         DEBUG(3,("Whoops, Printer handle not found: "));
161         /*dump_data(4, hnd->data, sizeof(hnd->data));*/
162         return NULL;
163 }
164
165 /****************************************************************************
166   clear an handle
167 ****************************************************************************/
168 static void clear_handle(POLICY_HND *hnd)
169 {
170         memset(hnd->data, 0, POLICY_HND_SIZE);
171 }
172
173 /****************************************************************************
174   close printer index by handle
175 ****************************************************************************/
176 static BOOL close_printer_handle(POLICY_HND *hnd)
177 {
178         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
179
180         if (!OPEN_HANDLE(Printer))
181         {
182                 DEBUG(3,("Error closing printer handle\n"));
183                 return False;
184         }
185
186         Printer->open=False;
187         Printer->notify.flags=0;
188         Printer->notify.options=0;
189         Printer->notify.localmachine[0]='\0';
190         Printer->notify.printerlocal=0;
191         safe_free(Printer->notify.option);
192         Printer->notify.option=NULL;
193         
194         clear_handle(hnd);
195
196         ubi_dlRemThis(&Printer_list, Printer);
197
198         safe_free(Printer);
199
200         return True;
201 }       
202
203 /****************************************************************************
204   return the snum of a printer corresponding to an handle
205 ****************************************************************************/
206 static BOOL get_printer_snum(const POLICY_HND *hnd, int *number)
207 {
208         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
209                 
210         if (!OPEN_HANDLE(Printer)) {
211                 DEBUG(3,("Error getting printer - take a nap quickly !\n"));
212                 return False;
213         }
214         
215         switch (Printer->printer_type) {
216         case PRINTER_HANDLE_IS_PRINTER:            
217                 DEBUG(4,("short name:%s\n", Printer->dev.printername));                 
218                 *number = print_queue_snum(Printer->dev.printername);
219                 return (*number != -1);
220         case PRINTER_HANDLE_IS_PRINTSERVER:
221                 return False;
222                 break;
223         default:
224                 return False;
225                 break;
226         }
227 }
228
229 /****************************************************************************
230   find first available printer slot. creates a printer handle for you.
231  ****************************************************************************/
232 static BOOL open_printer_hnd(POLICY_HND *hnd)
233 {
234         Printer_entry *new_printer;
235
236         if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
237                 return False;
238
239         ZERO_STRUCTP(new_printer);
240         
241         new_printer->open = True;
242         new_printer->notify.option=NULL;
243                                 
244         memcpy(&(new_printer->printer_hnd), hnd, sizeof(*hnd));
245         
246         ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
247
248         return True;
249 }
250
251 /****************************************************************************
252   set printer handle type.
253 ****************************************************************************/
254 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
255 {
256         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
257
258         if (!OPEN_HANDLE(Printer)) {
259                 DEBUG(4,("Error setting printer type=%x", access_required));
260                 return False;
261         }
262
263         DEBUG(4,("Setting printer access=%x\n", access_required));
264         Printer->access = access_required;
265         return True;            
266 }
267
268 /****************************************************************************
269   set printer handle type.
270   check if it's \\server or \\server\printer
271 ****************************************************************************/
272 static BOOL set_printer_hnd_printertype(POLICY_HND *hnd, char *printername)
273 {
274         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
275                 
276         if (!OPEN_HANDLE(Printer)) {
277                 DEBUGADD(4,("Error setting printer name %s", printername));
278                 return False;
279         }
280         
281         DEBUG(3,("Setting printer type=%s\n", printername));
282
283         if ( strlen(printername) < 3 ) {
284                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", printername));
285                 return False;
286         }
287
288         /* it's a print server */
289         if (!strchr(printername+2, '\\')) {
290                 DEBUGADD(4,("Printer is a print server\n"));
291                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;          
292                 return True;
293         }
294         /* it's a printer */
295         else {
296                 DEBUGADD(4,("Printer is a printer\n"));
297                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
298                 return True;
299         }
300
301         return False;
302 }
303
304 /****************************************************************************
305   set printer handle printername.
306 ****************************************************************************/
307 static BOOL set_printer_hnd_printername(POLICY_HND *hnd, char *printername)
308 {
309         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
310         NT_PRINTER_INFO_LEVEL printer;
311         int snum;
312         int n_services=lp_numservices();
313         char *aprinter;
314         BOOL found=False;
315         
316         if (!OPEN_HANDLE(Printer)) {
317                 DEBUG(0,("Error setting printer name=%s\n", printername));
318                 return False;
319         }
320
321         DEBUG(4,("Setting printer name=%s (len=%d)\n", printername, strlen(printername)));
322
323         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
324                 ZERO_STRUCT(Printer->dev.printerservername);
325                 strncpy(Printer->dev.printerservername, printername, strlen(printername));
326                 return True;
327         }
328
329         if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
330                 return False;
331         
332         aprinter=strchr(printername+2, '\\');
333         aprinter++;
334
335         DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
336
337         /*
338          * store the Samba share name in it
339          * in back we have the long printer name
340          * need to iterate all the snum and do a
341          * get_a_printer each time to find the printer
342          * faster to do it here than later.
343          */
344
345         for (snum=0;snum<n_services && found==False;snum++) {
346         
347                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
348                         continue;
349                 
350                 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
351
352                 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
353                         continue;
354
355                 DEBUG(10,("set_printer_hnd_printername: printername [%s], aprinter [%s]\n", 
356                                 printer.info_2->printername, aprinter ));
357
358                 if ( strlen(printer.info_2->printername) != strlen(aprinter) ) {
359                         free_a_printer(printer, 2);
360                         continue;
361                 }
362                 
363                 if ( strncasecmp(printer.info_2->printername, aprinter, strlen(aprinter)))  {
364                         free_a_printer(printer, 2);
365                         continue;
366                 }
367                 
368                 found=True;
369         }
370
371         /* 
372          * if we haven't found a printer with the given printername
373          * then it can be a share name as you can open both \\server\printer and
374          * \\server\share
375          */
376
377         /*
378          * we still check if the printer description file exists as NT won't be happy
379          * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
380          */
381
382         if (found==False) {
383                 DEBUGADD(5,("Printer not found, checking for share now\n"));
384         
385                 for (snum=0;snum<n_services && found==False;snum++) {
386         
387                         if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
388                                 continue;
389                 
390                         DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
391
392                         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
393                                 continue;
394
395                         DEBUG(10,("set_printer_hnd_printername: printername [%s], aprinter [%s]\n", 
396                                         printer.info_2->printername, aprinter ));
397
398                         if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
399                                 free_a_printer(printer, 2);
400                                 continue;
401                         }
402                 
403                         if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter)))  {
404                                 free_a_printer(printer, 2);
405                                 continue;
406                         }
407                 
408                         found=True;
409                 }
410         }
411                 
412         if (found==False) {
413                 DEBUGADD(4,("Printer not found\n"));
414                 return False;
415         }
416         
417         snum--;
418         DEBUGADD(4,("Printer found: %s -> %s[%x]\n",printer.info_2->printername, lp_servicename(snum),snum));
419         ZERO_STRUCT(Printer->dev.printername);
420         strncpy(Printer->dev.printername, lp_servicename(snum), strlen(lp_servicename(snum)));
421         free_a_printer(printer, 2);
422         
423         return True;
424 }
425
426 /********************************************************************
427  Return True is the handle is a print server.
428  ********************************************************************/
429 static BOOL handle_is_printserver(const POLICY_HND *handle)
430 {
431         Printer_entry *Printer=find_printer_index_by_hnd(handle);
432
433         if (!OPEN_HANDLE(Printer))
434                 return False;
435                 
436         if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
437                 return False;
438         
439         return True;
440 }
441
442 /****************************************************************************
443  allocate more memory for a BUFFER.
444 ****************************************************************************/
445 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
446 {
447         prs_struct *ps;
448         uint32 extra_space;
449         uint32 old_offset;
450         
451         ps=&(buffer->prs);
452
453         /* damn, I'm doing the reverse operation of prs_grow() :) */
454         if (buffer_size < prs_data_size(ps))
455                 extra_space=0;
456         else    
457                 extra_space = buffer_size - prs_data_size(ps);
458
459         /* 
460          * save the offset and move to the end of the buffer
461          * prs_grow() checks the extra_space against the offset 
462          */
463         old_offset=prs_offset(ps);      
464         prs_set_offset(ps, prs_data_size(ps));
465         
466         if (!prs_grow(ps, extra_space))
467                 return False;
468
469         prs_set_offset(ps, old_offset);
470
471         buffer->string_at_end=prs_data_size(ps);
472
473         return True;
474 }
475
476 /********************************************************************
477  * spoolss_open_printer
478  *
479  * called from the spoolss dispatcher
480  ********************************************************************/
481 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername,
482                                  const PRINTER_DEFAULT *printer_default,
483                                  uint32  user_switch, SPOOL_USER_CTR user_ctr,
484                                  POLICY_HND *handle)
485 {
486         fstring name;
487         
488         clear_handle(handle);
489         
490         if (printername == NULL)
491                 return ERROR_INVALID_PRINTER_NAME;
492
493         /* some sanity check because you can open a printer or a print server */
494         /* aka: \\server\printer or \\server */
495         unistr2_to_ascii(name, printername, sizeof(name)-1);
496
497         DEBUGADD(3,("checking name: %s\n",name));
498
499         create_printer_hnd(handle);
500
501         open_printer_hnd(handle);
502         
503         if (!set_printer_hnd_printertype(handle, name)) {
504                 close_printer_handle(handle);
505                 return ERROR_INVALID_PRINTER_NAME;
506         }
507         
508         if (!set_printer_hnd_printername(handle, name)) {
509                 close_printer_handle(handle);
510                 return ERROR_INVALID_PRINTER_NAME;
511         }
512
513 /*
514         if (printer_default->datatype_ptr != NULL)
515         {
516                 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
517                 set_printer_hnd_datatype(handle, datatype);
518         }
519         else
520                 set_printer_hnd_datatype(handle, "");
521 */
522         
523         if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
524                 close_printer_handle(handle);
525                 return ERROR_ACCESS_DENIED;
526         }
527                 
528         return NT_STATUS_NO_PROBLEMO;
529 }
530
531 /****************************************************************************
532 ****************************************************************************/
533 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
534                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
535 {
536         switch (level) {
537                 case 2: 
538                         uni_2_asc_printer_info_2(uni->info_2, &(printer->info_2));
539                         break;
540                 default:
541                         break;
542         }
543
544         return True;
545 }
546
547 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
548                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
549 {
550         switch (level) {
551                 case 3: 
552                         printer->info_3=NULL;
553                         uni_2_asc_printer_driver_3(uni->info_3, &(printer->info_3));                                            
554                         break;
555                 default:
556                         break;
557         }
558
559         return True;
560 }
561
562 static BOOL convert_devicemode(DEVICEMODE devmode, NT_DEVICEMODE *nt_devmode)
563 {
564         unistr_to_ascii(nt_devmode->devicename, (char *)devmode.devicename.buffer, 31);
565         unistr_to_ascii(nt_devmode->formname, (char *)devmode.formname.buffer, 31);
566
567         nt_devmode->specversion=devmode.specversion;
568         nt_devmode->driverversion=devmode.driverversion;
569         nt_devmode->size=devmode.size;
570         nt_devmode->driverextra=devmode.driverextra;
571         nt_devmode->fields=devmode.fields;
572         nt_devmode->orientation=devmode.orientation;
573         nt_devmode->papersize=devmode.papersize;
574         nt_devmode->paperlength=devmode.paperlength;
575         nt_devmode->paperwidth=devmode.paperwidth;
576         nt_devmode->scale=devmode.scale;
577         nt_devmode->copies=devmode.copies;
578         nt_devmode->defaultsource=devmode.defaultsource;
579         nt_devmode->printquality=devmode.printquality;
580         nt_devmode->color=devmode.color;
581         nt_devmode->duplex=devmode.duplex;
582         nt_devmode->yresolution=devmode.yresolution;
583         nt_devmode->ttoption=devmode.ttoption;
584         nt_devmode->collate=devmode.collate;
585
586         nt_devmode->logpixels=devmode.logpixels;
587         nt_devmode->bitsperpel=devmode.bitsperpel;
588         nt_devmode->pelswidth=devmode.pelswidth;
589         nt_devmode->pelsheight=devmode.pelsheight;
590         nt_devmode->displayflags=devmode.displayflags;
591         nt_devmode->displayfrequency=devmode.displayfrequency;
592         nt_devmode->icmmethod=devmode.icmmethod;
593         nt_devmode->icmintent=devmode.icmintent;
594         nt_devmode->mediatype=devmode.mediatype;
595         nt_devmode->dithertype=devmode.dithertype;
596         nt_devmode->reserved1=devmode.reserved1;
597         nt_devmode->reserved2=devmode.reserved2;
598         nt_devmode->panningwidth=devmode.panningwidth;
599         nt_devmode->panningheight=devmode.panningheight;
600
601         if (nt_devmode->driverextra != 0) 
602         {
603                 /* if we had a previous private delete it and make a new one */
604                 if (nt_devmode->private != NULL)
605                         free(nt_devmode->private);
606                 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
607                         return False;
608                 memcpy(nt_devmode->private, devmode.private, nt_devmode->driverextra);
609         }
610
611         return True;
612 }
613
614 /********************************************************************
615  * api_spoolss_closeprinter
616  ********************************************************************/
617 uint32 _spoolss_closeprinter(POLICY_HND *handle)
618 {
619         if (!close_printer_handle(handle))
620                 return ERROR_INVALID_HANDLE;    
621                 
622         return NT_STATUS_NO_PROBLEMO;
623 }
624
625 /********************************************************************
626  GetPrinterData on a printer server Handle.
627 ********************************************************************/
628 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
629 {               
630         int i;
631         
632         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
633                 
634         if (!strcmp(value, "BeepEnabled"))
635         {
636                 *type = 0x4;
637                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
638                         return False;
639                 SIVAL(*data, 0, 0x01);
640                 *needed = 0x4;                  
641                 return True;
642         }
643
644         if (!strcmp(value, "EventLog"))
645         {
646                 *type = 0x4;
647                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
648                         return False;
649                 SIVAL(*data, 0, 0x1B);
650                 *needed = 0x4;                  
651                 return True;
652         }
653
654         if (!strcmp(value, "NetPopup"))
655         {
656                 *type = 0x4;
657                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
658                         return False;
659                 SIVAL(*data, 0, 0x01);
660                 *needed = 0x4;
661                 return True;
662         }
663
664         if (!strcmp(value, "MajorVersion"))
665         {
666                 *type = 0x4;
667                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
668                         return False;
669                 SIVAL(*data, 0, 0x02);
670                 *needed = 0x4;
671                 return True;
672         }
673
674         if (!strcmp(value, "DefaultSpoolDirectory"))
675         {
676                 pstring string="You are using a Samba server";
677                 *type = 0x1;                    
678                 *needed = 2*(strlen(string)+1);         
679                 if((*data  = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
680                         return False;
681                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
682                 
683                 /* it's done by hand ready to go on the wire */
684                 for (i=0; i<strlen(string); i++)
685                 {
686                         (*data)[2*i]=string[i];
687                         (*data)[2*i+1]='\0';
688                 }                       
689                 return True;
690         }
691
692         if (!strcmp(value, "Architecture"))
693         {                       
694                 pstring string="Windows NT x86";
695                 *type = 0x1;                    
696                 *needed = 2*(strlen(string)+1); 
697                 if((*data  = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
698                         return False;
699                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
700                 for (i=0; i<strlen(string); i++)
701                 {
702                         (*data)[2*i]=string[i];
703                         (*data)[2*i+1]='\0';
704                 }                       
705                 return True;
706         }
707         
708         return False;
709 }
710
711 /********************************************************************
712  GetPrinterData on a printer Handle.
713 ********************************************************************/
714 static BOOL getprinterdata_printer(const POLICY_HND *handle,
715                                 fstring value, uint32 *type, 
716                                 uint8 **data, uint32 *needed, uint32 in_size )
717 {
718         NT_PRINTER_INFO_LEVEL printer;
719         int snum=0;
720         uint8 *idata=NULL;
721         uint32 len;
722         Printer_entry *Printer = find_printer_index_by_hnd(handle);
723         
724         DEBUG(5,("getprinterdata_printer\n"));
725
726         if (!OPEN_HANDLE(Printer))
727                 return False;
728
729         if(!get_printer_snum(handle, &snum))
730                 return False;
731
732         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
733                 return False;
734
735         if (!get_specific_param(printer, 2, value, &idata, type, &len)) {
736                 free_a_printer(printer, 2);
737                 return False;
738         }
739
740         DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
741
742         if((*data  = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
743                 free_a_printer(printer, 2);
744                 return False;
745         }
746
747         memset(*data, 0, in_size *sizeof(uint8));
748         /* copy the min(in_size, len) */
749         memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
750
751         *needed = len;
752         
753         DEBUG(5,("getprinterdata_printer:copy done\n"));
754                         
755         free_a_printer(printer, 2);
756         safe_free(idata);
757         
758         return True;
759 }       
760
761 /********************************************************************
762  * spoolss_getprinterdata
763  ********************************************************************/
764 uint32 _spoolss_getprinterdata(const POLICY_HND *handle, UNISTR2 *valuename,
765                                 uint32 in_size,
766                                 uint32 *type,
767                                 uint32 *out_size,
768                                 uint8 **data,
769                                 uint32 *needed)
770 {
771         fstring value;
772         BOOL found=False;
773         Printer_entry *Printer = find_printer_index_by_hnd(handle);
774         
775         /* 
776          * Reminder: when it's a string, the length is in BYTES
777          * even if UNICODE is negociated.
778          *
779          * JFM, 4/19/1999
780          */
781
782         *out_size=in_size;
783
784         /* in case of problem, return some default values */
785         *needed=0;
786         *type=0;
787         
788         DEBUG(4,("_spoolss_getprinterdata\n"));
789         
790         if (!OPEN_HANDLE(Printer)) {
791                 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
792                         return ERROR_NOT_ENOUGH_MEMORY;
793                 return ERROR_INVALID_HANDLE;
794         }
795         
796         unistr2_to_ascii(value, valuename, sizeof(value)-1);
797         
798         if (handle_is_printserver(handle))
799                 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
800         else
801                 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
802
803         if (found==False) {
804                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
805                 /* reply this param doesn't exist */
806                 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
807                         return ERROR_NOT_ENOUGH_MEMORY;
808                 memset(*data, 0x0, *out_size*sizeof(uint8));
809                 return ERROR_INVALID_PARAMETER;
810         }
811         
812         if (*needed > *out_size)
813                 return ERROR_INSUFFICIENT_BUFFER;
814         else
815                 return NT_STATUS_NO_PROBLEMO;
816 }
817
818 /********************************************************************
819  * _spoolss_rffpcnex
820  * ReplyFindFirstPrinterChangeNotifyEx
821  *
822  * jfmxxxx: before replying OK: status=0
823  * should do a rpc call to the workstation asking ReplyOpenPrinter
824  * have to code it, later.
825  *
826  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
827  * called from api_spoolss_rffpcnex 
828  ********************************************************************/
829 uint32 _spoolss_rffpcnex(const POLICY_HND *handle, uint32 flags, uint32 options,
830                          const UNISTR2 *localmachine, uint32 printerlocal,
831                          SPOOL_NOTIFY_OPTION *option)
832 {
833         /* store the notify value in the printer struct */
834
835         Printer_entry *Printer=find_printer_index_by_hnd(handle);
836
837         if (!OPEN_HANDLE(Printer))
838                 return ERROR_INVALID_HANDLE;
839
840         Printer->notify.flags=flags;
841         Printer->notify.options=options;
842         Printer->notify.printerlocal=printerlocal;
843         Printer->notify.option=option;
844         unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
845
846         return NT_STATUS_NO_PROBLEMO;
847 }
848
849 /*******************************************************************
850  * fill a notify_info_data with the servername
851  ********************************************************************/
852 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
853 {
854         pstring temp_name;
855
856         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
857
858         data->notify_data.data.length=strlen(temp_name);
859         ascii_to_unistr((char *)data->notify_data.data.string, temp_name, sizeof(data->notify_data.data.string)-1);
860 }
861
862 /*******************************************************************
863  * fill a notify_info_data with the servicename
864  * jfmxxxx: it's incorrect should be long_printername
865  ********************************************************************/
866 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
867 {
868 /*
869         data->notify_data.data.length=strlen(lp_servicename(snum));
870         ascii_to_unistr(data->notify_data.data.string, lp_servicename(snum), sizeof(data->notify_data.data.string)-1);
871 */
872         data->notify_data.data.length=strlen(printer->info_2->printername);
873         ascii_to_unistr((char *)data->notify_data.data.string, 
874                         printer->info_2->printername, 
875                         sizeof(data->notify_data.data.string)-1);
876 }
877
878 /*******************************************************************
879  * fill a notify_info_data with the servicename
880  ********************************************************************/
881 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
882 {
883         data->notify_data.data.length=strlen(lp_servicename(snum));
884         ascii_to_unistr((char *)data->notify_data.data.string,
885                         lp_servicename(snum), 
886                         sizeof(data->notify_data.data.string)-1);
887 }
888
889 /*******************************************************************
890  * fill a notify_info_data with the port name
891  ********************************************************************/
892 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
893 {
894         /* even if it's strange, that's consistant in all the code */
895
896         data->notify_data.data.length=strlen(lp_servicename(snum));
897         ascii_to_unistr((char *)data->notify_data.data.string,
898                         lp_servicename(snum), 
899                         sizeof(data->notify_data.data.string)-1);
900 }
901
902 /*******************************************************************
903  * fill a notify_info_data with the printername
904  * jfmxxxx: it's incorrect, should be lp_printerdrivername()
905  * but it doesn't exist, have to see what to do
906  ********************************************************************/
907 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
908 {
909         data->notify_data.data.length=strlen(printer->info_2->drivername);
910         ascii_to_unistr((char *)data->notify_data.data.string, 
911                         printer->info_2->drivername, 
912                         sizeof(data->notify_data.data.string)-1);
913 }
914
915 /*******************************************************************
916  * fill a notify_info_data with the comment
917  ********************************************************************/
918 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
919 {
920         data->notify_data.data.length=strlen(lp_comment(snum));
921         ascii_to_unistr((char *)data->notify_data.data.string,
922                         lp_comment(snum),
923                         sizeof(data->notify_data.data.string)-1);
924 }
925
926 /*******************************************************************
927  * fill a notify_info_data with the comment
928  * jfm:xxxx incorrect, have to create a new smb.conf option
929  * location = "Room 1, floor 2, building 3"
930  ********************************************************************/
931 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
932 {
933         data->notify_data.data.length=strlen(printer->info_2->location);
934         ascii_to_unistr((char *)data->notify_data.data.string, 
935                         printer->info_2->location, 
936                         sizeof(data->notify_data.data.string)-1);
937 }
938
939 /*******************************************************************
940  * fill a notify_info_data with the device mode
941  * jfm:xxxx don't to it for know but that's a real problem !!!
942  ********************************************************************/
943 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
944 {
945 }
946
947 /*******************************************************************
948  * fill a notify_info_data with the separator file name
949  * jfm:xxxx just return no file could add an option to smb.conf
950  * separator file = "separator.txt"
951  ********************************************************************/
952 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
953 {
954         data->notify_data.data.length=strlen(printer->info_2->sepfile);
955         ascii_to_unistr((char *)data->notify_data.data.string, 
956                         printer->info_2->sepfile, 
957                         sizeof(data->notify_data.data.string)-1);
958 }
959
960 /*******************************************************************
961  * fill a notify_info_data with the print processor
962  * jfm:xxxx return always winprint to indicate we don't do anything to it
963  ********************************************************************/
964 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
965 {
966         data->notify_data.data.length=strlen(printer->info_2->printprocessor);
967         ascii_to_unistr((char *)data->notify_data.data.string, 
968                         printer->info_2->printprocessor, 
969                         sizeof(data->notify_data.data.string)-1);
970 }
971
972 /*******************************************************************
973  * fill a notify_info_data with the print processor options
974  * jfm:xxxx send an empty string
975  ********************************************************************/
976 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
977 {
978         data->notify_data.data.length=strlen(printer->info_2->parameters);
979         ascii_to_unistr((char *)data->notify_data.data.string, 
980                         printer->info_2->parameters, 
981                         sizeof(data->notify_data.data.string)-1);
982 }
983
984 /*******************************************************************
985  * fill a notify_info_data with the data type
986  * jfm:xxxx always send RAW as data type
987  ********************************************************************/
988 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
989 {
990         data->notify_data.data.length=strlen(printer->info_2->datatype);
991         ascii_to_unistr((char *)data->notify_data.data.string, 
992                         printer->info_2->datatype, 
993                         sizeof(data->notify_data.data.string)-1);
994 }
995
996 /*******************************************************************
997  * fill a notify_info_data with the security descriptor
998  * jfm:xxxx send an null pointer to say no security desc
999  * have to implement security before !
1000  ********************************************************************/
1001 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1002 {
1003         data->notify_data.data.length=0;
1004         data->notify_data.data.string[0]=0x00;
1005 }
1006
1007 /*******************************************************************
1008  * fill a notify_info_data with the attributes
1009  * jfm:xxxx a samba printer is always shared
1010  ********************************************************************/
1011 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1012 {
1013         data->notify_data.value[0] =   PRINTER_ATTRIBUTE_SHARED   \
1014                                      | PRINTER_ATTRIBUTE_NETWORK  \
1015                                      | PRINTER_ATTRIBUTE_RAW_ONLY ;
1016 }
1017
1018 /*******************************************************************
1019  * fill a notify_info_data with the priority
1020  ********************************************************************/
1021 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1022 {
1023         data->notify_data.value[0] = printer->info_2->priority;
1024 }
1025
1026 /*******************************************************************
1027  * fill a notify_info_data with the default priority
1028  ********************************************************************/
1029 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1030 {
1031         data->notify_data.value[0] = printer->info_2->default_priority;
1032 }
1033
1034 /*******************************************************************
1035  * fill a notify_info_data with the start time
1036  ********************************************************************/
1037 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1038 {
1039         data->notify_data.value[0] = printer->info_2->starttime;
1040 }
1041
1042 /*******************************************************************
1043  * fill a notify_info_data with the until time
1044  ********************************************************************/
1045 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1046 {
1047         data->notify_data.value[0] = printer->info_2->untiltime;
1048 }
1049
1050 /*******************************************************************
1051  * fill a notify_info_data with the status
1052  ********************************************************************/
1053 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1054 {
1055         int count;
1056         print_queue_struct *q=NULL;
1057         print_status_struct status;
1058
1059         memset(&status, 0, sizeof(status));
1060         count = print_queue_status(snum, &q, &status);
1061         data->notify_data.value[0]=(uint32) status.status;
1062         safe_free(q);
1063 }
1064
1065 /*******************************************************************
1066  * fill a notify_info_data with the number of jobs queued
1067  ********************************************************************/
1068 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1069 {
1070         print_queue_struct *q=NULL;
1071         print_status_struct status;
1072
1073         memset(&status, 0, sizeof(status));
1074         data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1075         safe_free(q);
1076 }
1077
1078 /*******************************************************************
1079  * fill a notify_info_data with the average ppm
1080  ********************************************************************/
1081 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1082 {
1083         /* always respond 8 pages per minutes */
1084         /* a little hard ! */
1085         data->notify_data.value[0] = printer->info_2->averageppm;
1086 }
1087
1088 /*******************************************************************
1089  * fill a notify_info_data with 
1090  ********************************************************************/
1091 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1092 {
1093         data->notify_data.data.length=strlen(queue->user);
1094         ascii_to_unistr((char *)data->notify_data.data.string, queue->user, sizeof(data->notify_data.data.string)-1);
1095 }
1096
1097 /*******************************************************************
1098  * fill a notify_info_data with 
1099  ********************************************************************/
1100 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1101 {
1102         data->notify_data.value[0]=nt_printj_status(queue->status);
1103 }
1104
1105 /*******************************************************************
1106  * fill a notify_info_data with 
1107  ********************************************************************/
1108 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1109 {
1110         data->notify_data.data.length=strlen(queue->file);
1111         ascii_to_unistr((char *)data->notify_data.data.string, queue->file, sizeof(data->notify_data.data.string)-1);
1112 }
1113
1114 /*******************************************************************
1115  * fill a notify_info_data with 
1116  ********************************************************************/
1117 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1118 {
1119         char *p = "unknown";
1120         switch (queue->status) {
1121         case LPQ_QUEUED:
1122                 p = "QUEUED";
1123                 break;
1124         case LPQ_PAUSED:
1125                 p = "PAUSED";
1126                 break;
1127         case LPQ_SPOOLING:
1128                 p = "SPOOLING";
1129                 break;
1130         case LPQ_PRINTING:
1131                 p = "PRINTING";
1132                 break;
1133         }
1134         data->notify_data.data.length=strlen(p);
1135         ascii_to_unistr((char *)data->notify_data.data.string, p, sizeof(data->notify_data.data.string)-1);
1136 }
1137
1138 /*******************************************************************
1139  * fill a notify_info_data with 
1140  ********************************************************************/
1141 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1142 {
1143         data->notify_data.value[0]=0x0;
1144 }
1145
1146 /*******************************************************************
1147  * fill a notify_info_data with 
1148  ********************************************************************/
1149 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1150 {
1151         data->notify_data.value[0]=queue->size;
1152 }
1153
1154 /*******************************************************************
1155  * fill a notify_info_data with 
1156  ********************************************************************/
1157 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1158 {
1159         data->notify_data.value[0]=queue->job;
1160 }
1161
1162 #define END 65535
1163
1164 struct s_notify_info_data_table notify_info_data_table[] =
1165 {
1166 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         POINTER,   spoolss_notify_server_name },
1167 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        POINTER,   spoolss_notify_printer_name },
1168 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          POINTER,   spoolss_notify_share_name },
1169 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           POINTER,   spoolss_notify_port_name },
1170 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         POINTER,   spoolss_notify_driver_name },
1171 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             POINTER,   spoolss_notify_comment },
1172 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            POINTER,   spoolss_notify_location },
1173 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             POINTER,   spoolss_notify_devmode },
1174 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             POINTER,   spoolss_notify_sepfile },
1175 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     POINTER,   spoolss_notify_print_processor },
1176 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          POINTER,   spoolss_notify_parameters },
1177 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            POINTER,   spoolss_notify_datatype },
1178 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER,   spoolss_notify_security_desc },
1179 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          ONE_VALUE, spoolss_notify_attributes },
1180 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            ONE_VALUE, spoolss_notify_priority },
1181 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    ONE_VALUE, spoolss_notify_default_priority },
1182 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          ONE_VALUE, spoolss_notify_start_time },
1183 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          ONE_VALUE, spoolss_notify_until_time },
1184 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              ONE_VALUE, spoolss_notify_status },
1185 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       POINTER,   NULL },
1186 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               ONE_VALUE, spoolss_notify_cjobs },
1187 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         ONE_VALUE, spoolss_notify_average_ppm },
1188 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         POINTER,   NULL },
1189 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       POINTER,   NULL },
1190 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         POINTER,   NULL },
1191 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       POINTER,   NULL },
1192 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            POINTER,   spoolss_notify_printer_name },
1193 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            POINTER,   spoolss_notify_server_name },
1194 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               POINTER,   spoolss_notify_port_name },
1195 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               POINTER,   spoolss_notify_username },
1196 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             POINTER,   spoolss_notify_username },
1197 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                POINTER,   spoolss_notify_datatype },
1198 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         POINTER,   spoolss_notify_print_processor },
1199 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              POINTER,   spoolss_notify_parameters },
1200 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             POINTER,   spoolss_notify_driver_name },
1201 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 POINTER,   spoolss_notify_devmode },
1202 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  ONE_VALUE, spoolss_notify_job_status },
1203 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           POINTER,   spoolss_notify_job_status_string },
1204 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     POINTER,   NULL },
1205 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                POINTER,   spoolss_notify_job_name },
1206 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                ONE_VALUE, spoolss_notify_priority },
1207 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                ONE_VALUE, spoolss_notify_job_position },
1208 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               POINTER,   NULL },
1209 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              ONE_VALUE, spoolss_notify_start_time },
1210 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              ONE_VALUE, spoolss_notify_until_time },
1211 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    ONE_VALUE, spoolss_notify_job_time },
1212 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             ONE_VALUE, NULL },
1213 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           ONE_VALUE, NULL },
1214 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             ONE_VALUE, spoolss_notify_job_size },
1215 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_BYTES_PRINTED,           "JOB_NOTIFY_BYTES_PRINTED",           ONE_VALUE, NULL },
1216 { END,                 END,                                "",                                   END,       NULL }
1217 };
1218
1219 /*******************************************************************
1220 return the size of info_data structure
1221 ********************************************************************/  
1222 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1223 {
1224         int i=0;
1225
1226         while (notify_info_data_table[i].type != END)
1227         {
1228                 if ( (notify_info_data_table[i].type == type ) &&
1229                      (notify_info_data_table[i].field == field ) )
1230                 {
1231                         return (notify_info_data_table[i].size);
1232                         continue;
1233                 }
1234                 i++;
1235         }
1236         return (65535);
1237 }
1238
1239 /*******************************************************************
1240 return the type of notify_info_data
1241 ********************************************************************/  
1242 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1243 {
1244         int i=0;
1245
1246         while (notify_info_data_table[i].type != END)
1247         {
1248                 if ( (notify_info_data_table[i].type == type ) &&
1249                      (notify_info_data_table[i].field == field ) )
1250                 {
1251                         if (notify_info_data_table[i].size == POINTER)
1252                         {
1253                                 return (False);
1254                         }
1255                         else
1256                         {
1257                                 return (True);
1258                         }
1259                         continue;
1260                 }
1261                 i++;
1262         }
1263         return (False);
1264 }
1265
1266 /****************************************************************************
1267 ****************************************************************************/
1268 static int search_notify(uint16 type, uint16 field, int *value)
1269 {       
1270         int j;
1271         BOOL found;
1272
1273         for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1274         {
1275                 if ( (notify_info_data_table[j].type  == type  ) &&
1276                      (notify_info_data_table[j].field == field ) )
1277                         found=True;
1278         }
1279         *value=--j;
1280
1281         if ( found && (notify_info_data_table[j].fn != NULL) )
1282                 return True;
1283         else
1284                 return False;   
1285 }
1286
1287 /****************************************************************************
1288 ****************************************************************************/
1289 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1290 {
1291         info_data->type     = type;
1292         info_data->field    = field;
1293         info_data->reserved = 0;
1294         info_data->id       = id;
1295         info_data->size     = size_of_notify_info_data(type, field);
1296         info_data->enc_type = type_of_notify_info_data(type, field);
1297 }
1298
1299
1300 /*******************************************************************
1301  *
1302  * fill a notify_info struct with info asked
1303  * 
1304  ********************************************************************/
1305 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1306 {
1307         int field_num,j;
1308         uint16 type;
1309         uint16 field;
1310
1311         SPOOL_NOTIFY_INFO_DATA *current_data;
1312         NT_PRINTER_INFO_LEVEL printer;
1313         print_queue_struct *queue=NULL;
1314         
1315         DEBUG(4,("construct_notify_printer_info\n"));
1316         
1317         type=option_type->type;
1318
1319         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1320                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"), 
1321                 option_type->count, lp_servicename(snum)));
1322         
1323         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1324         {
1325                 return False;
1326         }
1327
1328         for(field_num=0; field_num<option_type->count; field_num++)
1329         {
1330                 field = option_type->fields[field_num];
1331                 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1332
1333                 if (!search_notify(type, field, &j) )
1334                         continue;
1335                 
1336                 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1337                         free_a_printer(printer, 2);
1338                         return False;
1339                 }
1340                 current_data=&(info->data[info->count]);
1341
1342                 construct_info_data(current_data, type, field, id);             
1343                 notify_info_data_table[j].fn(snum, current_data, queue, &printer);
1344
1345                 info->count++;
1346         }
1347
1348         free_a_printer(printer, 2);
1349         return True;
1350 }
1351
1352 /*******************************************************************
1353  *
1354  * fill a notify_info struct with info asked
1355  * 
1356  ********************************************************************/
1357 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1358 {
1359         int field_num,j;
1360         uint16 type;
1361         uint16 field;
1362
1363         SPOOL_NOTIFY_INFO_DATA *current_data;
1364         NT_PRINTER_INFO_LEVEL printer;
1365         
1366         DEBUG(4,("construct_notify_jobs_info\n"));
1367         
1368         type = option_type->type;
1369
1370         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1371                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"), 
1372                 option_type->count));
1373
1374         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1375         {       
1376                 return False;
1377         }
1378         
1379         for(field_num=0; field_num<option_type->count; field_num++)
1380         {
1381                 field = option_type->fields[field_num];
1382
1383                 if (!search_notify(type, field, &j) )
1384                         continue;
1385
1386                 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1387                         free_a_printer(printer, 2);
1388                         return False;
1389                 }
1390
1391                 current_data=&(info->data[info->count]);
1392
1393                 construct_info_data(current_data, type, field, id);
1394                 notify_info_data_table[j].fn(snum, current_data, queue, &printer);
1395                 info->count++;
1396         }
1397         
1398         free_a_printer(printer, 2);
1399         
1400         return True;
1401 }
1402
1403 /*
1404  * JFM: The enumeration is not that simple, it's even non obvious.
1405  *
1406  * let's take an example: I want to monitor the PRINTER SERVER for
1407  * the printer's name and the number of jobs currently queued.
1408  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1409  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1410  * 
1411  * I have 3 printers on the back of my server.
1412  *
1413  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1414  * structures.
1415  *   Number     Data                    Id
1416  *      1       printer 1 name          1
1417  *      2       printer 1 cjob          1
1418  *      3       printer 2 name          2
1419  *      4       printer 2 cjob          2
1420  *      5       printer 3 name          3
1421  *      6       printer 3 name          3
1422  *
1423  * that's the print server case, the printer case is even worse.
1424  */
1425
1426
1427
1428 /*******************************************************************
1429  *
1430  * enumerate all printers on the printserver
1431  * fill a notify_info struct with info asked
1432  * 
1433  ********************************************************************/
1434 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1435 {
1436         int snum;
1437         Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1438         int n_services=lp_numservices();
1439         int i;
1440         uint32 id;
1441         SPOOL_NOTIFY_OPTION *option;
1442         SPOOL_NOTIFY_OPTION_TYPE *option_type;
1443
1444         DEBUG(4,("printserver_notify_info\n"));
1445         
1446         option=Printer->notify.option;
1447         id=1;
1448         info->version=2;
1449         info->data=NULL;
1450         info->count=0;
1451
1452         for (i=0; i<option->count; i++)
1453         {
1454                 option_type=&(option->ctr.type[i]);
1455                 
1456                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1457                         continue;
1458                 
1459                 for (snum=0; snum<n_services; snum++)
1460                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1461                                 if (construct_notify_printer_info(info, snum, option_type, id))
1462                                         id++;
1463         }
1464                         
1465         /*
1466          * Debugging information, don't delete.
1467          */
1468         /* 
1469         DEBUG(1,("dumping the NOTIFY_INFO\n"));
1470         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1471         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1472         
1473         for (i=0; i<info->count; i++)
1474         {
1475                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1476                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1477                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1478         }
1479         */
1480         
1481         return NT_STATUS_NO_PROBLEMO;
1482 }
1483
1484 /*******************************************************************
1485  *
1486  * fill a notify_info struct with info asked
1487  * 
1488  ********************************************************************/
1489 static uint32 printer_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1490 {
1491         int snum;
1492         Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1493         int i;
1494         uint32 id;
1495         SPOOL_NOTIFY_OPTION *option;
1496         SPOOL_NOTIFY_OPTION_TYPE *option_type;
1497         int count,j;
1498         print_queue_struct *queue=NULL;
1499         print_status_struct status;
1500         
1501         DEBUG(4,("printer_notify_info\n"));
1502
1503         option=Printer->notify.option;
1504         id=0xffffffff;
1505         info->version=2;
1506         info->data=NULL;
1507         info->count=0;
1508
1509         get_printer_snum(hnd, &snum);
1510
1511         for (i=0; i<option->count; i++)
1512         {
1513                 option_type=&(option->ctr.type[i]);
1514                 
1515                 switch ( option_type->type ) {
1516                 case PRINTER_NOTIFY_TYPE:
1517                         if(construct_notify_printer_info(info, snum, option_type, id))
1518                                 id--;
1519                         break;
1520                         
1521                 case JOB_NOTIFY_TYPE:
1522                         memset(&status, 0, sizeof(status));     
1523                         count = print_queue_status(snum, &queue, &status);
1524                         for (j=0; j<count; j++)
1525                                 construct_notify_jobs_info(&(queue[j]), info, snum, option_type, queue[j].job);
1526                         safe_free(queue);
1527                         break;
1528                 }
1529         }
1530         
1531         /*
1532          * Debugging information, don't delete.
1533          */
1534         /* 
1535         DEBUG(1,("dumping the NOTIFY_INFO\n"));
1536         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1537         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1538         
1539         for (i=0; i<info->count; i++)
1540         {
1541                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1542                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1543                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1544         }
1545         */
1546         return NT_STATUS_NO_PROBLEMO;
1547 }
1548
1549 /********************************************************************
1550  * spoolss_rfnpcnex
1551  ********************************************************************/
1552 uint32 _spoolss_rfnpcnex( const POLICY_HND *handle, uint32 change,
1553                           SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1554 {
1555         Printer_entry *Printer=find_printer_index_by_hnd(handle);
1556
1557         if (!OPEN_HANDLE(Printer))
1558                 return ERROR_INVALID_HANDLE;
1559
1560         DEBUG(4,("Printer type %x\n",Printer->printer_type));
1561
1562         /* jfm: the change value isn't used right now.
1563          *      we will honour it when
1564          *      a) we'll be able to send notification to the client
1565          *      b) we'll have a way to communicate between the spoolss process.
1566          *
1567          *      same thing for option->flags
1568          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as 
1569          *      I don't have a global notification system, I'm sending back all the
1570          *      informations even when _NOTHING_ has changed.
1571          */
1572
1573         /* just discard the SPOOL_NOTIFY_OPTION */
1574         if (option!=NULL)
1575                 safe_free(option->ctr.type);
1576         
1577         switch (Printer->printer_type) {
1578                 case PRINTER_HANDLE_IS_PRINTSERVER:
1579                         return printserver_notify_info(handle, info);
1580                         break;
1581                 case PRINTER_HANDLE_IS_PRINTER:
1582                         return printer_notify_info(handle, info);
1583                         break;
1584         }
1585
1586         return ERROR_INVALID_HANDLE;
1587 }
1588
1589 /********************************************************************
1590  * construct_printer_info_0
1591  * fill a printer_info_1 struct
1592  ********************************************************************/
1593 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, fstring servername)
1594 {
1595         pstring chaine;
1596         int count;
1597         NT_PRINTER_INFO_LEVEL ntprinter;
1598         counter_printer_0 *session_counter;
1599         uint32 global_counter;
1600         struct tm *t;
1601
1602         print_queue_struct *queue=NULL;
1603         print_status_struct status;
1604         
1605         memset(&status, 0, sizeof(status));     
1606
1607         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1608                 return False;
1609
1610         count = print_queue_status(snum, &queue, &status);
1611
1612         /* check if we already have a counter for this printer */       
1613         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1614
1615         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1616                 if (session_counter->snum == snum)
1617                         break;
1618         }
1619
1620         /* it's the first time, add it to the list */
1621         if (session_counter==NULL) {
1622                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL)
1623                         return False;
1624                 ZERO_STRUCTP(session_counter);
1625                 session_counter->snum=snum;
1626                 session_counter->counter=0;
1627                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1628         }
1629         
1630         /* increment it */
1631         session_counter->counter++;
1632         
1633         /* JFM:
1634          * the global_counter should be stored in a TDB as it's common to all the clients
1635          * and should be zeroed on samba startup
1636          */
1637         global_counter=session_counter->counter;
1638         
1639         /* the description and the name are of the form \\server\share */
1640         slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter.info_2->printername);
1641                                                             
1642         init_unistr(&(printer->printername), chaine);
1643         
1644         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername);
1645         init_unistr(&(printer->servername), chaine);
1646         
1647         printer->cjobs = count;
1648         printer->total_jobs = 0;
1649         printer->total_bytes = 0;
1650
1651         t=gmtime(&ntprinter.info_2->setuptime);
1652
1653         printer->year = t->tm_year+1900;
1654         printer->month = t->tm_mon+1;
1655         printer->dayofweek = t->tm_wday;
1656         printer->day = t->tm_mday;
1657         printer->hour = t->tm_hour;
1658         printer->minute = t->tm_min;
1659         printer->second = t->tm_sec;
1660         printer->milliseconds = 0;
1661
1662         printer->global_counter = global_counter;
1663         printer->total_pages = 0;
1664         printer->major_version = 0x0004;        /* NT 4 */
1665         printer->build_version = 0x0565;        /* build 1381 */
1666         printer->unknown7 = 0x1;
1667         printer->unknown8 = 0x0;
1668         printer->unknown9 = 0x0;
1669         printer->session_counter = session_counter->counter;
1670         printer->unknown11 = 0x0;
1671         printer->printer_errors = 0x0;          /* number of print failure */
1672         printer->unknown13 = 0x0;
1673         printer->unknown14 = 0x1;
1674         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
1675         printer->unknown16 = 0x0;
1676         printer->change_id = ntprinter.info_2->changeid; /* ChangeID in milliseconds*/
1677         printer->unknown18 = 0x0;
1678         printer->status = nt_printq_status(status.status);
1679         printer->unknown20 = 0x0;
1680         printer->c_setprinter = ntprinter.info_2->c_setprinter; /* how many times setprinter has been called */
1681         printer->unknown22 = 0x0;
1682         printer->unknown23 = 0x6;               /* 6  ???*/
1683         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
1684         printer->unknown25 = 0;
1685         printer->unknown26 = 0;
1686         printer->unknown27 = 0;
1687         printer->unknown28 = 0;
1688         printer->unknown29 = 0;
1689         
1690         safe_free(queue);
1691
1692         free_a_printer(ntprinter, 2);
1693         return (True);  
1694 }
1695
1696 /********************************************************************
1697  * construct_printer_info_1
1698  * fill a printer_info_1 struct
1699  ********************************************************************/
1700 static BOOL construct_printer_info_1(fstring server, uint32 flags, PRINTER_INFO_1 *printer, int snum)
1701 {
1702         pstring chaine;
1703         pstring chaine2;
1704         NT_PRINTER_INFO_LEVEL ntprinter;
1705
1706         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1707                 return False;
1708
1709         printer->flags=flags;
1710
1711         snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter.info_2->printername,
1712                 ntprinter.info_2->drivername, lp_comment(snum));
1713                 
1714         snprintf(chaine2,sizeof(chaine)-1,"%s%s", server, ntprinter.info_2->printername);
1715
1716         init_unistr(&printer->description, chaine);
1717         init_unistr(&printer->name, chaine2);   
1718         init_unistr(&printer->comment, lp_comment(snum));
1719         
1720         free_a_printer(ntprinter, 2);
1721
1722         return True;
1723 }
1724
1725 /****************************************************************************
1726 ****************************************************************************/
1727 static BOOL construct_dev_mode(DEVICEMODE *devmode, int snum, char *servername)
1728 {
1729         char adevice[32];
1730         char aform[32];
1731         NT_PRINTER_INFO_LEVEL printer;  
1732         NT_DEVICEMODE *ntdevmode;
1733
1734         DEBUG(7,("construct_dev_mode\n"));
1735         
1736         memset(&(devmode->devicename), 0, 2*sizeof(adevice));
1737         memset(&(devmode->formname), 0, 2*sizeof(aform));
1738
1739         DEBUGADD(8,("getting printer characteristics\n"));
1740
1741         get_a_printer(&printer, 2, lp_servicename(snum));
1742         ntdevmode=(printer.info_2)->devmode;
1743
1744         DEBUGADD(8,("loading DEVICEMODE\n"));
1745         snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, 
1746                                                          printer.info_2->printername);
1747         init_unistr(&(devmode->devicename), adevice);
1748
1749         snprintf(aform, sizeof(aform), ntdevmode->formname);
1750         init_unistr(&(devmode->formname), aform);
1751
1752         devmode->specversion      = ntdevmode->specversion;
1753         devmode->driverversion    = ntdevmode->driverversion;
1754         devmode->size             = ntdevmode->size;
1755         devmode->driverextra      = ntdevmode->driverextra;
1756         devmode->fields           = ntdevmode->fields;
1757                                     
1758         devmode->orientation      = ntdevmode->orientation;     
1759         devmode->papersize        = ntdevmode->papersize;
1760         devmode->paperlength      = ntdevmode->paperlength;
1761         devmode->paperwidth       = ntdevmode->paperwidth;
1762         devmode->scale            = ntdevmode->scale;
1763         devmode->copies           = ntdevmode->copies;
1764         devmode->defaultsource    = ntdevmode->defaultsource;
1765         devmode->printquality     = ntdevmode->printquality;
1766         devmode->color            = ntdevmode->color;
1767         devmode->duplex           = ntdevmode->duplex;
1768         devmode->yresolution      = ntdevmode->yresolution;
1769         devmode->ttoption         = ntdevmode->ttoption;
1770         devmode->collate          = ntdevmode->collate;
1771         devmode->icmmethod        = ntdevmode->icmmethod;
1772         devmode->icmintent        = ntdevmode->icmintent;
1773         devmode->mediatype        = ntdevmode->mediatype;
1774         devmode->dithertype       = ntdevmode->dithertype;
1775
1776         if (ntdevmode->private != NULL)
1777         {
1778                 if((devmode->private=(uint8 *)malloc(devmode->driverextra*sizeof(uint8))) == NULL) {
1779                         free_a_printer(printer, 2);
1780                         return False;
1781                 }
1782                 memcpy(devmode->private, ntdevmode->private, devmode->driverextra);
1783         }
1784
1785         free_a_printer(printer, 2);
1786
1787         return True;
1788 }
1789
1790 /********************************************************************
1791  * construct_printer_info_2
1792  * fill a printer_info_2 struct
1793  ********************************************************************/
1794 static BOOL construct_printer_info_2(fstring servername, PRINTER_INFO_2 *printer, int snum)
1795 {
1796         pstring chaine;
1797         pstring chaine2;
1798         pstring sl;
1799         int count;
1800         DEVICEMODE *devmode;
1801         NT_PRINTER_INFO_LEVEL ntprinter;
1802
1803         print_queue_struct *queue=NULL;
1804         print_status_struct status;
1805         memset(&status, 0, sizeof(status));     
1806
1807         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
1808                 return False;
1809                 
1810         memset(&status, 0, sizeof(status));             
1811         count = print_queue_status(snum, &queue, &status);
1812
1813         snprintf(chaine, sizeof(chaine)-1, "%s", servername);
1814
1815         if (strlen(servername)!=0)
1816                 fstrcpy(sl, "\\");
1817         else
1818                 fstrcpy(sl, '\0');
1819
1820         snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter.info_2->printername);
1821
1822         init_unistr(&printer->servername, chaine);                              /* servername*/
1823         init_unistr(&printer->printername, chaine2);                            /* printername*/
1824         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
1825         init_unistr(&printer->portname, lp_servicename(snum));                  /* port */      
1826         init_unistr(&printer->drivername, ntprinter.info_2->drivername);        /* drivername */
1827         init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
1828         init_unistr(&printer->location, ntprinter.info_2->location);            /* location */  
1829         init_unistr(&printer->sepfile, ntprinter.info_2->sepfile);              /* separator file */
1830         init_unistr(&printer->printprocessor, ntprinter.info_2->printprocessor);/* print processor */
1831         init_unistr(&printer->datatype, ntprinter.info_2->datatype);            /* datatype */  
1832         init_unistr(&printer->parameters, ntprinter.info_2->parameters);        /* parameters (of print processor) */   
1833
1834         printer->attributes =   PRINTER_ATTRIBUTE_SHARED   \
1835                               | PRINTER_ATTRIBUTE_LOCAL  \
1836                               | PRINTER_ATTRIBUTE_RAW_ONLY ;                    /* attributes */
1837
1838         printer->priority = ntprinter.info_2->priority;                         /* priority */  
1839         printer->defaultpriority = ntprinter.info_2->default_priority;          /* default priority */
1840         printer->starttime = ntprinter.info_2->starttime;                       /* starttime */
1841         printer->untiltime = ntprinter.info_2->untiltime;                       /* untiltime */
1842         printer->status = nt_printq_status(status.status);                      /* status */
1843         printer->cjobs = count;                                                 /* jobs */
1844         printer->averageppm = ntprinter.info_2->averageppm;                     /* average pages per minute */
1845                         
1846         if((devmode=(DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) 
1847                 goto err;
1848
1849         ZERO_STRUCTP(devmode);  
1850
1851         if(!construct_dev_mode(devmode, snum, servername)) 
1852                 goto err;
1853
1854         printer->devmode=devmode;
1855         
1856         safe_free(queue);
1857         free_a_printer(ntprinter, 2);
1858         return True;
1859
1860   err:
1861
1862         safe_free(queue);
1863         free_a_printer(ntprinter, 2);
1864         return False;
1865 }
1866
1867 /********************************************************************
1868  Spoolss_enumprinters.
1869 ********************************************************************/
1870 static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
1871 {
1872         int snum;
1873         int i;
1874         int n_services=lp_numservices();
1875         PRINTER_INFO_1 *printers=NULL;
1876         PRINTER_INFO_1 current_prt;
1877         
1878         DEBUG(4,("enum_all_printers_info_1\n"));        
1879
1880         for (snum=0; snum<n_services; snum++) {
1881                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
1882                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
1883                                 
1884                         if (construct_printer_info_1(server, flags, &current_prt, snum)) {
1885                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
1886                                         *returned=0;
1887                                         return ERROR_NOT_ENOUGH_MEMORY;
1888                                 }
1889                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
1890                                 memcpy(&(printers[*returned]), &current_prt, sizeof(PRINTER_INFO_1));
1891                                 (*returned)++;
1892                         }
1893                 }
1894         }
1895                 
1896         /* check the required size. */  
1897         for (i=0; i<*returned; i++)
1898                 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
1899
1900         if (!alloc_buffer_size(buffer, *needed))
1901                 return ERROR_INSUFFICIENT_BUFFER;
1902
1903         /* fill the buffer with the structures */
1904         for (i=0; i<*returned; i++)
1905                 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);       
1906
1907         /* clear memory */
1908         safe_free(printers);
1909
1910         if (*needed > offered) {
1911                 *returned=0;
1912                 return ERROR_INSUFFICIENT_BUFFER;
1913         }
1914         else
1915                 return NT_STATUS_NO_PROBLEMO;
1916 }
1917
1918 /********************************************************************
1919  enum_all_printers_info_1_local.
1920 *********************************************************************/
1921 static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
1922 {
1923         fstring temp;
1924         DEBUG(4,("enum_all_printers_info_1_local\n"));  
1925         
1926         fstrcpy(temp, "\\\\");
1927         fstrcat(temp, global_myname);
1928
1929         if (!strcmp(name, temp)) {
1930                 fstrcat(temp, "\\");
1931                 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
1932         }
1933         else
1934                 return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
1935 }
1936
1937 /********************************************************************
1938  enum_all_printers_info_1_name.
1939 *********************************************************************/
1940 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
1941 {
1942         fstring temp;
1943         DEBUG(4,("enum_all_printers_info_1_name\n"));   
1944         
1945         fstrcpy(temp, "\\\\");
1946         fstrcat(temp, global_myname);
1947
1948         if (!strcmp(name, temp)) {
1949                 fstrcat(temp, "\\");
1950                 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
1951         }
1952         else
1953                 return ERROR_INVALID_NAME;
1954 }
1955
1956 /********************************************************************
1957  enum_all_printers_info_1_remote.
1958 *********************************************************************/
1959 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
1960 {
1961         PRINTER_INFO_1 *printer;
1962         fstring printername;
1963         fstring desc;
1964         fstring comment;
1965         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
1966
1967         /* JFM: currently it's more a place holder than anything else.
1968          * In the spooler world there is a notion of server registration.
1969          * the print servers are registring (sp ?) on the PDC (in the same domain)
1970          * 
1971          * We should have a TDB here. The registration is done thru an undocumented RPC call.
1972          */
1973         
1974         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
1975                 return ERROR_NOT_ENOUGH_MEMORY;
1976
1977         *returned=1;
1978         
1979         snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);               
1980         snprintf(desc, sizeof(desc)-1,"%s", global_myname);
1981         snprintf(comment, sizeof(comment)-1, "Logged on Domain");
1982
1983         init_unistr(&printer->description, desc);
1984         init_unistr(&printer->name, printername);       
1985         init_unistr(&printer->comment, comment);
1986         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
1987                 
1988         /* check the required size. */  
1989         *needed += spoolss_size_printer_info_1(printer);
1990
1991         if (!alloc_buffer_size(buffer, *needed)) {
1992                 safe_free(printer);
1993                 return ERROR_INSUFFICIENT_BUFFER;
1994         }
1995
1996         /* fill the buffer with the structures */
1997         new_smb_io_printer_info_1("", buffer, printer, 0);      
1998
1999         /* clear memory */
2000         safe_free(printer);
2001
2002         if (*needed > offered) {
2003                 *returned=0;
2004                 return ERROR_INSUFFICIENT_BUFFER;
2005         }
2006         else
2007                 return NT_STATUS_NO_PROBLEMO;
2008 }
2009
2010 /********************************************************************
2011  enum_all_printers_info_1_network.
2012 *********************************************************************/
2013 static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2014 {
2015         fstring temp;
2016         DEBUG(4,("enum_all_printers_info_1_network\n"));        
2017         
2018         fstrcpy(temp, "\\\\");
2019         fstrcat(temp, global_myname);
2020         fstrcat(temp, "\\");
2021         return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2022 }
2023
2024 /********************************************************************
2025  * api_spoolss_enumprinters
2026  *
2027  * called from api_spoolss_enumprinters (see this to understand)
2028  ********************************************************************/
2029 static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2030 {
2031         int snum;
2032         int i;
2033         int n_services=lp_numservices();
2034         PRINTER_INFO_2 *printers=NULL;
2035         PRINTER_INFO_2 current_prt;
2036
2037         for (snum=0; snum<n_services; snum++) {
2038                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2039                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2040                                 
2041                         if (construct_printer_info_2(servername, &current_prt, snum)) {
2042                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2043                                         return ERROR_NOT_ENOUGH_MEMORY;
2044                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
2045                                 memcpy(&(printers[*returned]), &current_prt, sizeof(PRINTER_INFO_2));
2046                                 (*returned)++;
2047                         }
2048                 }
2049         }
2050         
2051         /* check the required size. */  
2052         for (i=0; i<*returned; i++)
2053                 (*needed) += spoolss_size_printer_info_2(&(printers[i]));
2054
2055         if (!alloc_buffer_size(buffer, *needed)) {
2056                 for (i=0; i<*returned; i++) {
2057                         safe_free(printers[i].devmode->private);
2058                         safe_free(printers[i].devmode);
2059                 }
2060                 safe_free(printers);
2061                 return ERROR_INSUFFICIENT_BUFFER;
2062         }
2063
2064         /* fill the buffer with the structures */
2065         for (i=0; i<*returned; i++)
2066                 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);       
2067         
2068         /* clear memory */
2069         for (i=0; i<*returned; i++) {
2070                 safe_free(printers[i].devmode->private);
2071                 safe_free(printers[i].devmode);
2072         }
2073         safe_free(printers);
2074
2075         if (*needed > offered) {
2076                 *returned=0;
2077                 return ERROR_INSUFFICIENT_BUFFER;
2078         }
2079         else
2080                 return NT_STATUS_NO_PROBLEMO;
2081 }
2082
2083 /********************************************************************
2084  * handle enumeration of printers at level 1
2085  ********************************************************************/
2086 static uint32 enumprinters_level1( uint32 flags, fstring name,
2087                                  NEW_BUFFER *buffer, uint32 offered,
2088                                  uint32 *needed, uint32 *returned)
2089 {
2090         /* Not all the flags are equals */
2091
2092         if (flags & PRINTER_ENUM_LOCAL)
2093                 return enum_all_printers_info_1_local(name, buffer, offered, needed, returned);
2094
2095         if (flags & PRINTER_ENUM_NAME)
2096                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2097
2098         if (flags & PRINTER_ENUM_REMOTE)
2099                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2100
2101         if (flags & PRINTER_ENUM_NETWORK)
2102                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
2103
2104         return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2105 }
2106
2107 /********************************************************************
2108  * handle enumeration of printers at level 2
2109  ********************************************************************/
2110 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2111                                  NEW_BUFFER *buffer, uint32 offered,
2112                                  uint32 *needed, uint32 *returned)
2113 {
2114         fstring temp;
2115         
2116         fstrcpy(temp, "\\\\");
2117         fstrcat(temp, global_myname);
2118
2119         if (flags & PRINTER_ENUM_LOCAL) {
2120                 if (!strcmp(servername, temp))
2121                         return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2122                 else
2123                         return enum_all_printers_info_2("", buffer, offered, needed, returned);
2124         }
2125
2126         if (flags & PRINTER_ENUM_NAME) {
2127                 if (!strcmp(servername, temp))
2128                         return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2129                 else
2130                         return ERROR_INVALID_NAME;
2131         }
2132
2133         if (flags & PRINTER_ENUM_REMOTE)
2134                 return ERROR_INVALID_LEVEL;
2135
2136         return NT_STATUS_NO_PROBLEMO;
2137 }
2138
2139 /********************************************************************
2140  * handle enumeration of printers at level 5
2141  ********************************************************************/
2142 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2143                                  NEW_BUFFER *buffer, uint32 offered,
2144                                  uint32 *needed, uint32 *returned)
2145 {
2146 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2147         return NT_STATUS_NO_PROBLEMO;
2148 }
2149
2150 /********************************************************************
2151  * api_spoolss_enumprinters
2152  *
2153  * called from api_spoolss_enumprinters (see this to understand)
2154  ********************************************************************/
2155 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2156                               NEW_BUFFER *buffer, uint32 offered,
2157                               uint32 *needed, uint32 *returned)
2158 {
2159         fstring name;
2160         
2161         DEBUG(4,("_spoolss_enumprinters\n"));
2162
2163         *needed=0;
2164         *returned=0;
2165         
2166         /*
2167          * Level 1: 
2168          *          flags==PRINTER_ENUM_NAME
2169          *           if name=="" then enumerates all printers
2170          *           if name!="" then enumerate the printer
2171          *          flags==PRINTER_ENUM_REMOTE
2172          *          name is NULL, enumerate printers
2173          * Level 2: name!="" enumerates printers, name can't be NULL
2174          * Level 3: doesn't exist
2175          * Level 4: does a local registry lookup
2176          * Level 5: same as Level 2
2177          */
2178
2179         unistr2_to_ascii(name, servername, sizeof(name)-1);
2180         strupper(name);
2181
2182         switch (level) {
2183         case 1:
2184                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2185                 break;
2186         case 2:
2187                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2188                 break;                          
2189         case 5:
2190                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2191                 break;                          
2192         case 3:
2193         case 4:
2194         default:
2195                 return ERROR_INVALID_LEVEL;
2196                 break;
2197         }
2198 }
2199
2200 /****************************************************************************
2201 ****************************************************************************/
2202 static uint32 getprinter_level_0(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2203 {
2204         PRINTER_INFO_0 *printer=NULL;
2205
2206         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2207                 return ERROR_NOT_ENOUGH_MEMORY;
2208
2209         construct_printer_info_0(printer, snum, servername);
2210         
2211         /* check the required size. */  
2212         *needed += spoolss_size_printer_info_0(printer);
2213
2214         if (!alloc_buffer_size(buffer, *needed)) {
2215                 safe_free(printer);
2216                 return ERROR_INSUFFICIENT_BUFFER;
2217         }
2218
2219         /* fill the buffer with the structures */
2220         new_smb_io_printer_info_0("", buffer, printer, 0);      
2221         
2222         /* clear memory */
2223         safe_free(printer);
2224
2225         if (*needed > offered) {
2226                 return ERROR_INSUFFICIENT_BUFFER;
2227         }
2228         else
2229                 return NT_STATUS_NO_PROBLEMO;   
2230 }
2231
2232 /****************************************************************************
2233 ****************************************************************************/
2234 static uint32 getprinter_level_1(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2235 {
2236         PRINTER_INFO_1 *printer=NULL;
2237
2238         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2239                 return ERROR_NOT_ENOUGH_MEMORY;
2240
2241         construct_printer_info_1(servername, PRINTER_ENUM_ICON8, printer, snum);
2242         
2243         /* check the required size. */  
2244         *needed += spoolss_size_printer_info_1(printer);
2245
2246         if (!alloc_buffer_size(buffer, *needed)) {
2247                 safe_free(printer);
2248                 return ERROR_INSUFFICIENT_BUFFER;
2249         }
2250
2251         /* fill the buffer with the structures */
2252         new_smb_io_printer_info_1("", buffer, printer, 0);      
2253         
2254         /* clear memory */
2255         safe_free(printer);
2256
2257         if (*needed > offered) {
2258                 return ERROR_INSUFFICIENT_BUFFER;
2259         }
2260         else
2261                 return NT_STATUS_NO_PROBLEMO;   
2262 }
2263
2264 /****************************************************************************
2265 ****************************************************************************/
2266 static uint32 getprinter_level_2(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2267 {
2268         PRINTER_INFO_2 *printer=NULL;
2269         fstring temp;
2270
2271         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2272                 return ERROR_NOT_ENOUGH_MEMORY;
2273         
2274         fstrcpy(temp, "\\\\");
2275         fstrcat(temp, servername);
2276         construct_printer_info_2(temp, printer, snum);
2277         
2278         /* check the required size. */  
2279         *needed += spoolss_size_printer_info_2(printer);
2280
2281         if (!alloc_buffer_size(buffer, *needed)) {
2282                 safe_free(printer);
2283                 return ERROR_INSUFFICIENT_BUFFER;
2284         }
2285
2286         /* fill the buffer with the structures */
2287         new_smb_io_printer_info_2("", buffer, printer, 0);      
2288         
2289         /* clear memory */
2290         safe_free(printer->devmode->private);
2291         safe_free(printer->devmode);
2292         safe_free(printer);
2293
2294         if (*needed > offered) {
2295                 return ERROR_INSUFFICIENT_BUFFER;
2296         }
2297         else
2298                 return NT_STATUS_NO_PROBLEMO;   
2299 }
2300
2301 /****************************************************************************
2302 ****************************************************************************/
2303 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2304                            NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2305 {
2306         int snum;
2307         fstring servername;
2308         
2309         *needed=0;
2310
2311         pstrcpy(servername, global_myname);
2312
2313         if (!get_printer_snum(handle, &snum))
2314                 return ERROR_INVALID_HANDLE;
2315
2316         switch (level) {
2317         case 0:
2318                 return getprinter_level_0(servername, snum, buffer, offered, needed);
2319                 break;
2320         case 1:
2321                 return getprinter_level_1(servername,snum, buffer, offered, needed);
2322                 break;
2323         case 2:         
2324                 return getprinter_level_2(servername,snum, buffer, offered, needed);
2325                 break;
2326         default:
2327                 return ERROR_INVALID_LEVEL;
2328                 break;
2329         }
2330 }       
2331                 
2332 /********************************************************************
2333  * construct_printer_driver_info_1
2334  * fill a construct_printer_driver_info_1 struct
2335  ********************************************************************/
2336 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, 
2337                                        NT_PRINTER_DRIVER_INFO_LEVEL driver, 
2338                                        fstring servername, fstring architecture)
2339 {
2340         init_unistr( &(info->name), driver.info_3->name);
2341 }
2342
2343 static void construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, 
2344                                             fstring servername, fstring architecture)
2345 {       
2346         NT_PRINTER_INFO_LEVEL printer;
2347         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2348
2349         get_a_printer(&printer, 2, lp_servicename(snum) );
2350         get_a_printer_driver(&driver, 3, printer.info_2->drivername, architecture);     
2351         
2352         fill_printer_driver_info_1(info, driver, servername, architecture);
2353         
2354         free_a_printer_driver(driver, 3);
2355         free_a_printer(printer, 2);
2356 }
2357
2358 /********************************************************************
2359  * construct_printer_driver_info_2
2360  * fill a printer_info_2 struct
2361  ********************************************************************/
2362 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, 
2363                                        NT_PRINTER_DRIVER_INFO_LEVEL driver, 
2364                                        fstring servername, fstring architecture)
2365 {
2366         pstring where;
2367         pstring temp_driverpath;
2368         pstring temp_datafile;
2369         pstring temp_configfile;
2370         fstring short_archi;
2371
2372         get_short_archi(short_archi,architecture);
2373         
2374         snprintf(where,sizeof(where)-1,"\\\\%s\\print$\\%s\\", servername, short_archi);
2375
2376         info->version=driver.info_3->cversion;
2377
2378         init_unistr( &(info->name),         driver.info_3->name );
2379         init_unistr( &(info->architecture), architecture );
2380         
2381         snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "%s%s", where, 
2382                  driver.info_3->driverpath);
2383         init_unistr( &(info->driverpath),   temp_driverpath );
2384
2385         snprintf(temp_datafile,   sizeof(temp_datafile)-1, "%s%s", where, 
2386                  driver.info_3->datafile);
2387         init_unistr( &(info->datafile),     temp_datafile );
2388
2389         snprintf(temp_configfile, sizeof(temp_configfile)-1, "%s%s", where, 
2390                  driver.info_3->configfile);
2391         init_unistr( &(info->configfile),   temp_configfile );  
2392 }
2393
2394 /********************************************************************
2395  * construct_printer_driver_info_2
2396  * fill a printer_info_2 struct
2397  ********************************************************************/
2398 static void construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture)
2399 {
2400         NT_PRINTER_INFO_LEVEL printer;
2401         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2402         
2403         get_a_printer(&printer, 2, lp_servicename(snum) );
2404         get_a_printer_driver(&driver, 3, printer.info_2->drivername, architecture);     
2405
2406         fill_printer_driver_info_2(info, driver, servername, architecture);
2407
2408         free_a_printer_driver(driver, 3);
2409         free_a_printer(printer, 2);
2410 }
2411
2412 /********************************************************************
2413  * copy a strings array and convert to UNICODE
2414  *
2415  * convert an array of ascii string to a UNICODE string
2416  ********************************************************************/
2417 static void init_unistr_array(uint16 **uni_array, char **char_array, char *where)
2418 {
2419         int i=0;
2420         int j=0;
2421         char *v;
2422         pstring line;
2423
2424         DEBUG(6,("init_unistr_array\n"));
2425         *uni_array=NULL;
2426
2427         for (v=char_array[i]; *v!='\0'; v=char_array[i]) {
2428                 snprintf(line, sizeof(line)-1, "%s%s", where, v);
2429                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2430                 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2431                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
2432                         return;
2433                 }
2434                 ascii_to_unistr((char *)(*uni_array+j), line , 2*strlen(line));
2435                 j+=strlen(line)+1;                      
2436                 i++;
2437         }
2438         
2439         (*uni_array)[j]=0x0000;
2440         
2441         DEBUGADD(6,("last one:done\n"));
2442 }
2443
2444 /********************************************************************
2445  * construct_printer_info_3
2446  * fill a printer_info_3 struct
2447  ********************************************************************/
2448 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, 
2449                                        NT_PRINTER_DRIVER_INFO_LEVEL driver, 
2450                                        fstring servername, fstring architecture)
2451 {
2452         pstring where;
2453         pstring temp_driverpath;
2454         pstring temp_datafile;
2455         pstring temp_configfile;
2456         pstring temp_helpfile;
2457         fstring short_archi;
2458         
2459         get_short_archi(short_archi, architecture);
2460         
2461         snprintf(where,sizeof(where)-1,"\\\\%s\\print$\\%s\\", servername, short_archi);
2462         
2463         info->version=driver.info_3->cversion;
2464
2465         init_unistr( &(info->name),         driver.info_3->name );      
2466         init_unistr( &(info->architecture), architecture );
2467         
2468         snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "%s%s", where, driver.info_3->driverpath);          
2469         init_unistr( &(info->driverpath), temp_driverpath );
2470         
2471         snprintf(temp_datafile,   sizeof(temp_datafile)-1,   "%s%s", where, driver.info_3->datafile); 
2472         init_unistr( &(info->datafile), temp_datafile );
2473         
2474         snprintf(temp_configfile, sizeof(temp_configfile)-1, "%s%s", where, driver.info_3->configfile);
2475         init_unistr( &(info->configfile), temp_configfile );    
2476         
2477         snprintf(temp_helpfile,   sizeof(temp_helpfile)-1,   "%s%s", where, driver.info_3->helpfile);
2478         init_unistr( &(info->helpfile), temp_helpfile );
2479
2480         init_unistr( &(info->monitorname), driver.info_3->monitorname );
2481         init_unistr( &(info->defaultdatatype), driver.info_3->defaultdatatype );
2482
2483         info->dependentfiles=NULL;
2484         init_unistr_array(&(info->dependentfiles), driver.info_3->dependentfiles, where);
2485 }
2486
2487 /********************************************************************
2488  * construct_printer_info_3
2489  * fill a printer_info_3 struct
2490  ********************************************************************/
2491 static void construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, 
2492                                             fstring servername, fstring architecture)
2493 {       
2494         NT_PRINTER_INFO_LEVEL printer;
2495         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2496         
2497         get_a_printer(&printer, 2, lp_servicename(snum) );      
2498         get_a_printer_driver(&driver, 3, printer.info_2->drivername, architecture);     
2499
2500         fill_printer_driver_info_3(info, driver, servername, architecture);
2501
2502         free_a_printer_driver(driver, 3);
2503         free_a_printer(printer, 2);
2504 }
2505
2506 /****************************************************************************
2507 ****************************************************************************/
2508 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2509 {
2510         DRIVER_INFO_1 *info=NULL;
2511         
2512         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2513                 return ERROR_NOT_ENOUGH_MEMORY;
2514         
2515         construct_printer_driver_info_1(info, snum, servername, architecture);
2516
2517         /* check the required size. */  
2518         *needed += spoolss_size_printer_driver_info_1(info);
2519
2520         if (!alloc_buffer_size(buffer, *needed)) {
2521                 safe_free(info);
2522                 return ERROR_INSUFFICIENT_BUFFER;
2523         }
2524
2525         /* fill the buffer with the structures */
2526         new_smb_io_printer_driver_info_1("", buffer, info, 0);  
2527
2528         /* clear memory */
2529         safe_free(info);
2530
2531         if (*needed > offered)
2532                 return ERROR_INSUFFICIENT_BUFFER;
2533         else
2534                 return NT_STATUS_NO_PROBLEMO;
2535 }
2536
2537 /****************************************************************************
2538 ****************************************************************************/
2539 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2540 {
2541         DRIVER_INFO_2 *info=NULL;
2542         
2543         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
2544                 return ERROR_NOT_ENOUGH_MEMORY;
2545         
2546         construct_printer_driver_info_2(info, snum, servername, architecture);
2547
2548         /* check the required size. */  
2549         *needed += spoolss_size_printer_driver_info_2(info);
2550
2551         if (!alloc_buffer_size(buffer, *needed)) {
2552                 safe_free(info);
2553                 return ERROR_INSUFFICIENT_BUFFER;
2554         }
2555
2556         /* fill the buffer with the structures */
2557         new_smb_io_printer_driver_info_2("", buffer, info, 0);  
2558
2559         /* clear memory */
2560         safe_free(info);
2561
2562         if (*needed > offered)
2563                 return ERROR_INSUFFICIENT_BUFFER;
2564         else
2565                 return NT_STATUS_NO_PROBLEMO;
2566 }
2567
2568 /****************************************************************************
2569 ****************************************************************************/
2570 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2571 {
2572         DRIVER_INFO_3 *info=NULL;
2573         
2574         if((info=(DRIVER_INFO_3 *)malloc(sizeof(DRIVER_INFO_3)))==NULL)
2575                 return ERROR_NOT_ENOUGH_MEMORY;
2576         
2577         construct_printer_driver_info_3(info, snum, servername, architecture);
2578
2579         /* check the required size. */  
2580         *needed += spoolss_size_printer_driver_info_3(info);
2581
2582         if (!alloc_buffer_size(buffer, *needed)) {
2583                 safe_free(info);
2584                 return ERROR_INSUFFICIENT_BUFFER;
2585         }
2586
2587         /* fill the buffer with the structures */
2588         new_smb_io_printer_driver_info_3("", buffer, info, 0);  
2589
2590         /* clear memory */
2591         safe_free(info->dependentfiles);
2592         safe_free(info);
2593
2594         if (*needed > offered)
2595                 return ERROR_INSUFFICIENT_BUFFER;
2596         else
2597                 return NT_STATUS_NO_PROBLEMO;
2598 }
2599
2600 /****************************************************************************
2601 ****************************************************************************/
2602 uint32 _spoolss_getprinterdriver2(const POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level, 
2603                                 uint32 clientmajorversion, uint32 clientminorversion,
2604                                 NEW_BUFFER *buffer, uint32 offered,
2605                                 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
2606 {
2607         fstring servername;
2608         fstring architecture;
2609         int snum;
2610
2611         DEBUG(4,("_spoolss_getprinterdriver2\n"));
2612
2613         *needed=0;
2614         *servermajorversion=0;
2615         *serverminorversion=0;
2616
2617         pstrcpy(servername, global_myname);
2618         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
2619
2620         if (!get_printer_snum(handle, &snum))
2621                 return ERROR_INVALID_HANDLE;
2622
2623         switch (level) {
2624         case 1:
2625                 return getprinterdriver2_level1(servername, architecture, snum, buffer, offered, needed);
2626                 break;
2627         case 2:
2628                 return getprinterdriver2_level2(servername, architecture, snum, buffer, offered, needed);
2629                 break;                          
2630         case 3:
2631                 return getprinterdriver2_level3(servername, architecture, snum, buffer, offered, needed);
2632                 break;                          
2633         default:
2634                 return ERROR_INVALID_LEVEL;
2635                 break;
2636         }
2637 }
2638
2639 /****************************************************************************
2640 ****************************************************************************/
2641 uint32 _spoolss_startpageprinter(const POLICY_HND *handle)
2642 {
2643         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2644
2645         if (OPEN_HANDLE(Printer))
2646         {
2647                 Printer->page_started=True;
2648                 return 0x0;
2649         }
2650
2651         DEBUG(3,("Error in startpageprinter printer handle\n"));
2652         return ERROR_INVALID_HANDLE;
2653 }
2654
2655 /****************************************************************************
2656 ****************************************************************************/
2657 uint32 _spoolss_endpageprinter(const POLICY_HND *handle)
2658 {
2659         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2660
2661         if (!OPEN_HANDLE(Printer))
2662         {
2663                 DEBUG(3,("Error in endpageprinter printer handle\n"));
2664                 return ERROR_INVALID_HANDLE;
2665         }
2666         
2667         Printer->page_started=False;
2668
2669         return NT_STATUS_NO_PROBLEMO;
2670 }
2671
2672
2673 /********************************************************************
2674  * api_spoolss_getprinter
2675  * called from the spoolss dispatcher
2676  *
2677  ********************************************************************/
2678 uint32 _spoolss_startdocprinter( const POLICY_HND *handle, uint32 level,
2679                                 DOC_INFO *docinfo, uint32 *jobid)
2680 {
2681         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
2682         int snum;
2683         pstring jobname;
2684         fstring datatype;
2685         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2686
2687         if (!OPEN_HANDLE(Printer))
2688         {
2689                 return ERROR_INVALID_HANDLE;
2690         }
2691
2692         /*
2693          * a nice thing with NT is it doesn't listen to what you tell it.
2694          * when asked to send _only_ RAW datas, it tries to send datas
2695          * in EMF format.
2696          *
2697          * So I add checks like in NT Server ...
2698          *
2699          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
2700          * there's a bug in NT client-side code, so we'll fix it in the
2701          * server-side code. *nnnnnggggh!*
2702          */
2703         
2704         if (info_1->p_datatype != 0)
2705         {
2706                 unistr2_to_ascii(datatype, &(info_1->docname), sizeof(datatype));
2707                 if (strcmp(datatype, "RAW") != 0)
2708                 {
2709                         (*jobid)=0;
2710                         return ERROR_INVALID_DATATYPE;
2711                 }               
2712         }                
2713         
2714         /* get the share number of the printer */
2715         if (!get_printer_snum(handle, &snum))
2716         {
2717                 return ERROR_INVALID_HANDLE;
2718         }
2719
2720         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
2721         
2722         Printer->jobid = print_job_start(snum, jobname);
2723
2724         /* need to map error codes properly - for now give out of
2725            memory as I don't know the correct codes (tridge) */
2726         if (Printer->jobid == -1) {
2727                 return ERROR_NOT_ENOUGH_MEMORY;
2728         }
2729         
2730         Printer->document_started=True;
2731         (*jobid) = Printer->jobid;
2732
2733         return 0x0;
2734 }
2735
2736 /********************************************************************
2737  * api_spoolss_getprinter
2738  * called from the spoolss dispatcher
2739  *
2740  ********************************************************************/
2741 uint32 _spoolss_enddocprinter(const POLICY_HND *handle)
2742 {
2743         Printer_entry *Printer=find_printer_index_by_hnd(handle);
2744         
2745         if (!OPEN_HANDLE(Printer))
2746         {
2747                 DEBUG(3,("Error in enddocprinter handle\n"));
2748                 return ERROR_INVALID_HANDLE;
2749         }
2750         
2751         Printer->document_started=False;
2752         print_job_end(Printer->jobid);
2753         /* error codes unhandled so far ... */
2754
2755         return 0x0;
2756 }
2757
2758 /****************************************************************************
2759 ****************************************************************************/
2760 uint32 _spoolss_writeprinter( const POLICY_HND *handle,
2761                                 uint32 buffer_size,
2762                                 const uint8 *buffer,
2763                                 uint32 *buffer_written)
2764 {
2765         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2766         
2767         if (!OPEN_HANDLE(Printer))
2768         {
2769                 DEBUG(3,("Error in writeprinter handle\n"));
2770                 return ERROR_INVALID_HANDLE;
2771         }
2772
2773         (*buffer_written) = print_job_write(Printer->jobid, buffer, buffer_size);
2774
2775         return 0x0;
2776 }
2777
2778 /********************************************************************
2779  * api_spoolss_getprinter
2780  * called from the spoolss dispatcher
2781  *
2782  ********************************************************************/
2783 static uint32 control_printer(const POLICY_HND *handle, uint32 command)
2784 {
2785         int snum;
2786         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2787
2788         if (!OPEN_HANDLE(Printer))
2789                 return ERROR_INVALID_HANDLE;
2790
2791         if (!get_printer_snum(handle, &snum) )   
2792                 return ERROR_INVALID_HANDLE;
2793
2794         switch (command) {
2795         case PRINTER_CONTROL_PAUSE:
2796                 if (print_queue_pause(snum)) {
2797                         return 0;
2798                 }
2799                 break;
2800         case PRINTER_CONTROL_RESUME:
2801         case PRINTER_CONTROL_UNPAUSE:
2802                 if (print_queue_resume(snum)) {
2803                         return 0;
2804                 }
2805                 break;
2806         case PRINTER_CONTROL_PURGE:
2807                 if (print_queue_purge(snum)) {
2808                         return 0;
2809                 }
2810                 break;
2811         }
2812
2813         return ERROR_INVALID_FUNCTION;
2814 }
2815
2816 /********************************************************************
2817  * called by spoolss_api_setprinter
2818  * when updating a printer description
2819  ********************************************************************/
2820 static uint32 update_printer(const POLICY_HND *handle, uint32 level,
2821                            const SPOOL_PRINTER_INFO_LEVEL *info,
2822                            const DEVICEMODE *devmode)
2823 {
2824         int snum;
2825         NT_PRINTER_INFO_LEVEL printer;
2826         NT_DEVICEMODE *nt_devmode;
2827         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2828
2829         nt_devmode=NULL;
2830         
2831         DEBUG(8,("update_printer\n"));
2832         
2833         if (level!=2) {
2834                 DEBUG(0,("Send a mail to jfm@samba.org\n"));
2835                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
2836                 return ERROR_INVALID_LEVEL;
2837         }
2838
2839         if (!OPEN_HANDLE(Printer))
2840                 return ERROR_INVALID_HANDLE;
2841
2842         if (!get_printer_snum(handle, &snum) )
2843                 return ERROR_INVALID_HANDLE;
2844         
2845         get_a_printer(&printer, 2, lp_servicename(snum));
2846
2847         DEBUGADD(8,("Converting info_2 struct\n"));
2848         convert_printer_info(info, &printer, level);
2849         
2850         if ((info->info_2)->devmode_ptr != 0) {
2851                 /* we have a valid devmode
2852                    convert it and link it*/
2853                 
2854                 /* the nt_devmode memory is already alloced
2855                  * while doing the get_a_printer call
2856                  * but the devmode private part is not
2857                  * it's done by convert_devicemode
2858                  */
2859                 DEBUGADD(8,("Converting the devicemode struct\n"));
2860                 nt_devmode=printer.info_2->devmode;
2861                 
2862                 init_devicemode(nt_devmode);
2863                                 
2864                 convert_devicemode(*devmode, nt_devmode);
2865         }
2866         else {
2867                 if (printer.info_2->devmode != NULL)
2868                         free(printer.info_2->devmode);
2869                 printer.info_2->devmode=NULL;
2870         }
2871                         
2872         if (add_a_printer(printer, 2)!=0) {
2873                 free_a_printer(printer, 2);
2874                 
2875                 /* I don't really know what to return here !!! */
2876                 return ERROR_ACCESS_DENIED;
2877         }
2878
2879         free_a_printer(printer, 2);
2880
2881         return NT_STATUS_NO_PROBLEMO;
2882 }
2883
2884 /****************************************************************************
2885 ****************************************************************************/
2886 uint32 _spoolss_setprinter(const POLICY_HND *handle, uint32 level,
2887                            const SPOOL_PRINTER_INFO_LEVEL *info,
2888                            const DEVMODE_CTR devmode_ctr,
2889                            uint32 command)
2890 {
2891         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2892         
2893         if (!OPEN_HANDLE(Printer))
2894                 return ERROR_INVALID_HANDLE;
2895
2896         /* check the level */   
2897         switch (level) {
2898                 case 0:
2899                         return control_printer(handle, command);
2900                         break;
2901                 case 2:
2902                         return update_printer(handle, level, info, devmode_ctr.devmode);
2903                         break;
2904                 default:
2905                         return ERROR_INVALID_LEVEL;
2906                         break;
2907         }
2908 }
2909
2910 /****************************************************************************
2911 ****************************************************************************/
2912 uint32 _spoolss_fcpn(const POLICY_HND *handle)
2913 {
2914         Printer_entry *Printer= find_printer_index_by_hnd(handle);
2915         
2916         if (!OPEN_HANDLE(Printer))
2917                 return ERROR_INVALID_HANDLE;
2918         
2919         Printer->notify.flags=0;
2920         Printer->notify.options=0;
2921         Printer->notify.localmachine[0]='\0';
2922         Printer->notify.printerlocal=0;
2923         safe_free(Printer->notify.option);
2924         Printer->notify.option=NULL;
2925         
2926         return NT_STATUS_NO_PROBLEMO;
2927 }
2928
2929 /****************************************************************************
2930 ****************************************************************************/
2931 uint32 _spoolss_addjob(const POLICY_HND *handle, uint32 level,
2932                         NEW_BUFFER *buffer, uint32 offered)
2933 {
2934         return NT_STATUS_NO_PROBLEMO;
2935 }
2936
2937 /****************************************************************************
2938 ****************************************************************************/
2939 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
2940                             int position, int snum)
2941 {
2942         pstring temp_name;
2943         
2944         struct tm *t;
2945         time_t unixdate = time(NULL);
2946         
2947         t=gmtime(&unixdate);
2948         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
2949
2950         job_info->jobid=queue->job;     
2951         init_unistr(&(job_info->printername), lp_servicename(snum));
2952         init_unistr(&(job_info->machinename), temp_name);
2953         init_unistr(&(job_info->username), queue->user);
2954         init_unistr(&(job_info->document), queue->file);
2955         init_unistr(&(job_info->datatype), "RAW");
2956         init_unistr(&(job_info->text_status), "");
2957         job_info->status=nt_printj_status(queue->status);
2958         job_info->priority=queue->priority;
2959         job_info->position=position;
2960         job_info->totalpages=0;
2961         job_info->pagesprinted=0;
2962
2963         make_systemtime(&(job_info->submitted), t);
2964 }
2965
2966 /****************************************************************************
2967 ****************************************************************************/
2968 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
2969                             int position, int snum)
2970 {
2971         pstring temp_name;
2972         DEVICEMODE *devmode;
2973         NT_PRINTER_INFO_LEVEL ntprinter;
2974         pstring chaine;
2975
2976         struct tm *t;
2977         time_t unixdate = time(NULL);
2978
2979         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2980                 return False;
2981         
2982         t=gmtime(&unixdate);
2983         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
2984
2985         job_info->jobid=queue->job;
2986         
2987         snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter.info_2->printername);
2988         init_unistr(&(job_info->printername), chaine);
2989         
2990         init_unistr(&(job_info->machinename), temp_name);
2991         init_unistr(&(job_info->username), queue->user);
2992         init_unistr(&(job_info->document), queue->file);
2993         init_unistr(&(job_info->notifyname), queue->user);
2994         init_unistr(&(job_info->datatype), "RAW");
2995         init_unistr(&(job_info->printprocessor), "winprint");
2996         init_unistr(&(job_info->parameters), "");
2997         init_unistr(&(job_info->text_status), "");
2998         
2999 /* and here the security descriptor */
3000
3001         job_info->status=nt_printj_status(queue->status);
3002         job_info->priority=queue->priority;
3003         job_info->position=position;
3004         job_info->starttime=0;
3005         job_info->untiltime=0;
3006         job_info->totalpages=0;
3007         job_info->size=queue->size;
3008         make_systemtime(&(job_info->submitted), t);
3009         job_info->timeelapsed=0;
3010         job_info->pagesprinted=0;
3011
3012         if((devmode=(DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3013                 free_a_printer(ntprinter, 2);
3014                 return False;
3015         }
3016
3017         ZERO_STRUCTP(devmode);  
3018         if(!construct_dev_mode(devmode, snum, global_myname)) {
3019                 free_a_printer(ntprinter, 2);
3020                 return False;
3021         }
3022         job_info->devmode=devmode;
3023
3024         free_a_printer(ntprinter, 2);
3025         return (True);
3026 }
3027
3028 /****************************************************************************
3029  Enumjobs at level 1.
3030 ****************************************************************************/
3031 static uint32 enumjobs_level1(print_queue_struct *queue, int snum, 
3032                               NEW_BUFFER *buffer, uint32 offered, 
3033                               uint32 *needed, uint32 *returned)
3034 {
3035         JOB_INFO_1 *info;
3036         int i;
3037         
3038         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3039         if (info==NULL) {
3040                 safe_free(queue);
3041                 *returned=0;
3042                 return ERROR_NOT_ENOUGH_MEMORY;
3043         }
3044         
3045         for (i=0; i<*returned; i++)
3046                 fill_job_info_1(&(info[i]), &(queue[i]), i, snum);
3047
3048         safe_free(queue);
3049
3050         /* check the required size. */  
3051         for (i=0; i<*returned; i++)
3052                 (*needed) += spoolss_size_job_info_1(&(info[i]));
3053
3054         if (!alloc_buffer_size(buffer, *needed)) {
3055                 safe_free(info);
3056                 return ERROR_INSUFFICIENT_BUFFER;
3057         }
3058
3059         /* fill the buffer with the structures */
3060         for (i=0; i<*returned; i++)
3061                 new_smb_io_job_info_1("", buffer, &(info[i]), 0);       
3062
3063         /* clear memory */
3064         safe_free(info);
3065
3066         if (*needed > offered) {
3067                 *returned=0;
3068                 return ERROR_INSUFFICIENT_BUFFER;
3069         }
3070         else
3071                 return NT_STATUS_NO_PROBLEMO;
3072 }
3073
3074 /****************************************************************************
3075  Enumjobs at level 2.
3076 ****************************************************************************/
3077 static uint32 enumjobs_level2(print_queue_struct *queue, int snum, 
3078                               NEW_BUFFER *buffer, uint32 offered, 
3079                               uint32 *needed, uint32 *returned)
3080 {
3081         JOB_INFO_2 *info;
3082         int i;
3083         
3084         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
3085         if (info==NULL) {
3086                 safe_free(queue);
3087                 *returned=0;
3088                 return ERROR_NOT_ENOUGH_MEMORY;
3089         }
3090         
3091         for (i=0; i<*returned; i++)
3092                 fill_job_info_2(&(info[i]), &(queue[i]), i, snum);
3093
3094         safe_free(queue);
3095
3096         /* check the required size. */  
3097         for (i=0; i<*returned; i++)
3098                 (*needed) += spoolss_size_job_info_2(&(info[i]));
3099
3100         if (!alloc_buffer_size(buffer, *needed)) {
3101                 safe_free(info);
3102                 return ERROR_INSUFFICIENT_BUFFER;
3103         }
3104
3105         /* fill the buffer with the structures */
3106         for (i=0; i<*returned; i++)
3107                 new_smb_io_job_info_2("", buffer, &(info[i]), 0);       
3108
3109         /* clear memory */
3110         safe_free(info);
3111
3112         if (*needed > offered) {
3113                 *returned=0;
3114                 return ERROR_INSUFFICIENT_BUFFER;
3115         }
3116         else
3117                 return NT_STATUS_NO_PROBLEMO;
3118 }
3119
3120 /****************************************************************************
3121  Enumjobs.
3122 ****************************************************************************/
3123 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,                    
3124                           NEW_BUFFER *buffer, uint32 offered,
3125                           uint32 *needed, uint32 *returned)
3126 {       
3127         int snum;
3128         print_queue_struct *queue=NULL;
3129         print_status_struct prt_status;
3130
3131         DEBUG(4,("_spoolss_enumjobs\n"));
3132
3133         ZERO_STRUCT(prt_status);
3134
3135         *needed=0;
3136         *returned=0;
3137
3138         if (!get_printer_snum(handle, &snum))
3139                 return ERROR_INVALID_HANDLE;
3140
3141         *returned = print_queue_status(snum, &queue, &prt_status);
3142         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
3143
3144         switch (level) {
3145         case 1:
3146                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
3147                 break;
3148         case 2:
3149                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
3150                 break;                          
3151         default:
3152                 safe_free(queue);
3153                 *returned=0;
3154                 return ERROR_INVALID_LEVEL;
3155                 break;
3156         }
3157 }
3158
3159
3160 /****************************************************************************
3161 ****************************************************************************/
3162 uint32 _spoolss_schedulejob( const POLICY_HND *handle, uint32 jobid)
3163 {
3164         return 0x0;
3165 }
3166
3167 /****************************************************************************
3168 ****************************************************************************/
3169 uint32 _spoolss_setjob( const POLICY_HND *handle,
3170                                 uint32 jobid,
3171                                 uint32 level,
3172                                 JOB_INFO *ctr,
3173                                 uint32 command)
3174
3175 {
3176         int snum;
3177         print_status_struct prt_status;
3178                 
3179         memset(&prt_status, 0, sizeof(prt_status));
3180
3181         if (!get_printer_snum(handle, &snum)) {
3182                 return ERROR_INVALID_HANDLE;
3183         }
3184
3185         if (!print_job_exists(jobid)) {
3186                 return ERROR_INVALID_PRINTER_NAME;
3187         }
3188         
3189         switch (command) {
3190         case JOB_CONTROL_CANCEL:
3191         case JOB_CONTROL_DELETE:
3192                 if (print_job_delete(jobid)) return 0x0;
3193                 break;
3194         case JOB_CONTROL_PAUSE:
3195                 if (print_job_pause(jobid)) return 0x0;
3196                 break;
3197         case JOB_CONTROL_RESUME:
3198                 if (print_job_resume(jobid)) return 0x0;
3199                 break;
3200         default:
3201                 return ERROR_INVALID_LEVEL;
3202         }
3203
3204         return ERROR_INVALID_HANDLE;
3205 }
3206
3207 /****************************************************************************
3208  Enumerates all printer drivers at level 1.
3209 ****************************************************************************/
3210 static uint32 enumprinterdrivers_level1(fstring *list, fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3211 {
3212         int i;
3213         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3214         DRIVER_INFO_1 *driver_info_1=NULL;
3215
3216         if((driver_info_1=(DRIVER_INFO_1 *)malloc(*returned * sizeof(DRIVER_INFO_1))) == NULL)
3217                 return ERROR_NOT_ENOUGH_MEMORY;
3218
3219         for (i=0; i<*returned; i++) {
3220                 get_a_printer_driver(&driver, 3, list[i], architecture);
3221                 fill_printer_driver_info_1(&(driver_info_1[i]), driver, servername, architecture );
3222                 free_a_printer_driver(driver, 3);
3223         }
3224         
3225         safe_free(list);
3226         
3227         /* check the required size. */
3228         for (i=0; i<*returned; i++) {
3229                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3230                 *needed += spoolss_size_printer_driver_info_1(&(driver_info_1[i]));
3231         }
3232
3233         if (!alloc_buffer_size(buffer, *needed)) {
3234                 safe_free(driver_info_1);
3235                 return ERROR_INSUFFICIENT_BUFFER;
3236         }
3237
3238         /* fill the buffer with the form structures */
3239         for (i=0; i<*returned; i++) {
3240                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
3241                 new_smb_io_printer_driver_info_1("", buffer, &(driver_info_1[i]), 0);
3242         }
3243
3244         safe_free(driver_info_1);
3245
3246         if (*needed > offered) {
3247                 *returned=0;
3248                 return ERROR_INSUFFICIENT_BUFFER;
3249         }
3250         else
3251                 return NT_STATUS_NO_PROBLEMO;
3252 }
3253
3254 /****************************************************************************
3255  Enumerates all printer drivers at level 2.
3256 ****************************************************************************/
3257 static uint32 enumprinterdrivers_level2(fstring *list, fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3258 {
3259         int i;
3260         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3261         DRIVER_INFO_2 *driver_info_2=NULL;
3262
3263         if (*returned > 0 && 
3264             !(driver_info_2=(DRIVER_INFO_2 *)malloc(*returned * sizeof(DRIVER_INFO_2))))
3265                 return ERROR_NOT_ENOUGH_MEMORY;
3266
3267         for (i=0; i<*returned; i++) {
3268                 get_a_printer_driver(&driver, 3, list[i], architecture);
3269                 fill_printer_driver_info_2(&(driver_info_2[i]), driver, servername, architecture );
3270                 free_a_printer_driver(driver, 3);
3271         }
3272         
3273         safe_free(list);
3274         
3275         /* check the required size. */
3276         for (i=0; i<*returned; i++) {
3277                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3278                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
3279         }
3280
3281         if (!alloc_buffer_size(buffer, *needed)) {
3282                 safe_free(driver_info_2);
3283                 return ERROR_INSUFFICIENT_BUFFER;
3284         }
3285
3286         /* fill the buffer with the form structures */
3287         for (i=0; i<*returned; i++) {
3288                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
3289                 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
3290         }
3291
3292         safe_free(driver_info_2);
3293
3294         if (*needed > offered) {
3295                 *returned=0;
3296                 return ERROR_INSUFFICIENT_BUFFER;
3297         }
3298         else
3299                 return NT_STATUS_NO_PROBLEMO;
3300 }
3301
3302 /****************************************************************************
3303  Enumerates all printer drivers at level 3.
3304 ****************************************************************************/
3305 static uint32 enumprinterdrivers_level3(fstring *list, fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3306 {
3307         int i;
3308         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3309         DRIVER_INFO_3 *driver_info_3=NULL;
3310
3311         if((driver_info_3=(DRIVER_INFO_3 *)malloc((*returned)*sizeof(DRIVER_INFO_3))) == NULL)
3312                 return ERROR_NOT_ENOUGH_MEMORY;
3313
3314         for (i=0; i<*returned; i++) {
3315                 get_a_printer_driver(&driver, 3, list[i], architecture);
3316                 fill_printer_driver_info_3(&(driver_info_3[i]), driver, servername, architecture );
3317                 free_a_printer_driver(driver, 3);
3318         }
3319         
3320         safe_free(list);
3321         
3322         /* check the required size. */
3323         for (i=0; i<*returned; i++) {
3324                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3325                 *needed += spoolss_size_printer_driver_info_3(&(driver_info_3[i]));
3326         }
3327
3328         if (!alloc_buffer_size(buffer, *needed)) {
3329                 safe_free(driver_info_3);
3330                 return ERROR_INSUFFICIENT_BUFFER;
3331         }
3332         
3333         /* fill the buffer with the form structures */
3334         for (i=0; i<*returned; i++) {
3335                 DEBUGADD(6,("adding form [%d] to buffer\n",i));
3336                 new_smb_io_printer_driver_info_3("", buffer, &(driver_info_3[i]), 0);
3337         }
3338
3339         for (i=0; i<*returned; i++)
3340                 safe_free(driver_info_3[i].dependentfiles);
3341         
3342         safe_free(driver_info_3);
3343         
3344         if (*needed > offered) {
3345                 *returned=0;
3346                 return ERROR_INSUFFICIENT_BUFFER;
3347         }
3348         else
3349                 return NT_STATUS_NO_PROBLEMO;
3350 }
3351
3352 /****************************************************************************
3353  Enumerates all printer drivers.
3354 ****************************************************************************/
3355 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
3356                                     NEW_BUFFER *buffer, uint32 offered,
3357                                     uint32 *needed, uint32 *returned)
3358 {
3359         int i;
3360         fstring *list;
3361         fstring servername;
3362         fstring architecture;
3363
3364         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
3365         fstrcpy(servername, global_myname);
3366         *needed=0;
3367         *returned=0;
3368
3369         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
3370         *returned=get_ntdrivers(&list, architecture);
3371
3372         DEBUGADD(4,("we have: [%d] drivers in environment [%s]\n", *returned, architecture));
3373         if(*returned == -1)
3374                 return ERROR_NOT_ENOUGH_MEMORY;
3375
3376         for (i=0; i<*returned; i++)
3377                 DEBUGADD(5,("driver: [%s]\n", list[i]));
3378         
3379         switch (level) {
3380         case 1:
3381                 return enumprinterdrivers_level1(list, servername, architecture, buffer, offered, needed, returned);
3382                 break;
3383         case 2:
3384                 return enumprinterdrivers_level2(list, servername, architecture, buffer, offered, needed, returned);
3385                 break;
3386         case 3:
3387                 return enumprinterdrivers_level3(list, servername, architecture, buffer, offered, needed, returned);
3388                 break;
3389         default:
3390                 return ERROR_INVALID_LEVEL;
3391                 break;
3392         }
3393 }
3394
3395 /****************************************************************************
3396 ****************************************************************************/
3397 static void fill_form_1(FORM_1 *form, nt_forms_struct *list, int position)
3398 {
3399         form->flag=list->flag;
3400         init_unistr(&(form->name), list->name);
3401         form->width=list->width;
3402         form->length=list->length;
3403         form->left=list->left;
3404         form->top=list->top;
3405         form->right=list->right;
3406         form->bottom=list->bottom;      
3407 }
3408         
3409 /****************************************************************************
3410 ****************************************************************************/
3411 uint32 _new_spoolss_enumforms( const POLICY_HND *handle, uint32 level, 
3412                                NEW_BUFFER *buffer, uint32 offered, 
3413                                uint32 *needed, uint32 *numofforms)
3414 {
3415         nt_forms_struct *list=NULL;
3416         FORM_1 *forms_1;
3417         int buffer_size=0;
3418         int i;
3419
3420         DEBUG(4,("_new_spoolss_enumforms\n"));
3421         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
3422         DEBUGADD(5,("Info level [%d]\n",          level));
3423
3424         *numofforms = get_ntforms(&list);
3425         DEBUGADD(5,("Number of forms [%d]\n",     *numofforms));
3426
3427         switch (level) {
3428         case 1:
3429                 if((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
3430                         *numofforms=0;
3431                         return ERROR_NOT_ENOUGH_MEMORY;
3432                 }
3433
3434                 /* construct the list of form structures */
3435                 for (i=0; i<*numofforms; i++) {
3436                         DEBUGADD(6,("Filling form number [%d]\n",i));
3437                         fill_form_1(&(forms_1[i]), &(list[i]), i);
3438                 }
3439                 
3440                 safe_free(list);
3441
3442                 /* check the required size. */
3443                 for (i=0; i<*numofforms; i++) {
3444                         DEBUGADD(6,("adding form [%d]'s size\n",i));
3445                         buffer_size += spoolss_size_form_1(&(forms_1[i]));
3446                 }
3447
3448                 *needed=buffer_size;            
3449                 
3450                 if (!alloc_buffer_size(buffer, buffer_size)){
3451                         safe_free(forms_1);
3452                         return ERROR_INSUFFICIENT_BUFFER;
3453                 }
3454
3455                 /* fill the buffer with the form structures */
3456                 for (i=0; i<*numofforms; i++) {
3457                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
3458                         new_smb_io_form_1("", buffer, &(forms_1[i]), 0);
3459                 }
3460
3461                 safe_free(forms_1);
3462
3463                 if (*needed > offered) {
3464                         *numofforms=0;
3465                         return ERROR_INSUFFICIENT_BUFFER;
3466                 }
3467                 else
3468                         return NT_STATUS_NO_PROBLEMO;
3469                         
3470         default:
3471                 safe_free(list);
3472                 return ERROR_INVALID_LEVEL;
3473         }
3474
3475 }
3476
3477 /****************************************************************************
3478 ****************************************************************************/
3479 static void fill_port_1(PORT_INFO_1 *port, char *name)
3480 {
3481         init_unistr(&(port->port_name), name);
3482 }
3483
3484 /****************************************************************************
3485 ****************************************************************************/
3486 static void fill_port_2(PORT_INFO_2 *port, char *name)
3487 {
3488         init_unistr(&(port->port_name), name);
3489         init_unistr(&(port->monitor_name), "Moniteur Local");
3490         init_unistr(&(port->description), "Local Port");
3491 #define PORT_TYPE_WRITE 1
3492         port->port_type=PORT_TYPE_WRITE;
3493         port->reserved=0x0;     
3494 }
3495
3496 /****************************************************************************
3497  enumports level 1.
3498 ****************************************************************************/
3499 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3500 {
3501         int n_services=lp_numservices();
3502         int snum;
3503         int i=0;
3504         
3505         PORT_INFO_1 *ports=NULL;
3506
3507         for (snum=0; snum<n_services; snum++)
3508                 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3509                         (*returned)++;
3510
3511         if((ports=(PORT_INFO_1 *)malloc( (*returned+1) * sizeof(PORT_INFO_1) )) == NULL)
3512                 return ERROR_NOT_ENOUGH_MEMORY;
3513         
3514         for (snum=0; snum<n_services; snum++) {
3515                 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3516                         DEBUGADD(6,("Filling port number [%d]\n", i));
3517                         fill_port_1(&(ports[i]), lp_servicename(snum));
3518                         i++;
3519                 }
3520         }
3521
3522         /* check the required size. */
3523         for (i=0; i<*returned; i++) {
3524                 DEBUGADD(6,("adding port [%d]'s size\n", i));
3525                 *needed += spoolss_size_port_info_1(&(ports[i]));
3526         }
3527                 
3528         if (!alloc_buffer_size(buffer, *needed)) {
3529                 safe_free(ports);
3530                 return ERROR_INSUFFICIENT_BUFFER;
3531         }
3532
3533         /* fill the buffer with the ports structures */
3534         for (i=0; i<*returned; i++) {
3535                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
3536                 new_smb_io_port_1("", buffer, &(ports[i]), 0);
3537         }
3538
3539         safe_free(ports);
3540
3541         if (*needed > offered) {
3542                 *returned=0;
3543                 return ERROR_INSUFFICIENT_BUFFER;
3544         }
3545         else
3546                 return NT_STATUS_NO_PROBLEMO;
3547 }
3548
3549
3550 /****************************************************************************
3551  enumports level 2.
3552 ****************************************************************************/
3553 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3554 {
3555         int n_services=lp_numservices();
3556         int snum;
3557         int i=0;
3558         
3559         PORT_INFO_2 *ports=NULL;
3560
3561         for (snum=0; snum<n_services; snum++)
3562                 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3563                         (*returned)++;
3564
3565         if((ports=(PORT_INFO_2 *)malloc( (*returned+1) * sizeof(PORT_INFO_2) )) == NULL)
3566                 return ERROR_NOT_ENOUGH_MEMORY;
3567         
3568         for (snum=0; snum<n_services; snum++) {
3569                 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3570                         DEBUGADD(6,("Filling port number [%d]\n", i));
3571                         fill_port_2(&(ports[i]), lp_servicename(snum));
3572                         i++;
3573                 }
3574         }
3575
3576         /* check the required size. */
3577         for (i=0; i<*returned; i++) {
3578                 DEBUGADD(6,("adding port [%d]'s size\n", i));
3579                 *needed += spoolss_size_port_info_2(&(ports[i]));
3580         }
3581                 
3582         if (!alloc_buffer_size(buffer, *needed)) {
3583                 safe_free(ports);
3584                 return ERROR_INSUFFICIENT_BUFFER;
3585         }
3586
3587         /* fill the buffer with the ports structures */
3588         for (i=0; i<*returned; i++) {
3589                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
3590                 new_smb_io_port_2("", buffer, &(ports[i]), 0);
3591         }
3592
3593         safe_free(ports);
3594
3595         if (*needed > offered) {
3596                 *returned=0;
3597                 return ERROR_INSUFFICIENT_BUFFER;
3598         }
3599         else
3600                 return NT_STATUS_NO_PROBLEMO;
3601 }
3602
3603 /****************************************************************************
3604  enumports.
3605 ****************************************************************************/
3606 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level, 
3607                            NEW_BUFFER *buffer, uint32 offered, 
3608                            uint32 *needed, uint32 *returned)
3609 {
3610         DEBUG(4,("_spoolss_enumports\n"));
3611         
3612         *returned=0;
3613         *needed=0;
3614         
3615         switch (level) {
3616         case 1:
3617                 return enumports_level_1(buffer, offered, needed, returned);
3618                 break;
3619         case 2:
3620                 return enumports_level_2(buffer, offered, needed, returned);
3621                 break;
3622         default:
3623                 return ERROR_INVALID_LEVEL;
3624                 break;
3625         }
3626 }
3627
3628 /****************************************************************************
3629 ****************************************************************************/
3630 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
3631                                 const SPOOL_PRINTER_INFO_LEVEL *info,
3632                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
3633                                 uint32 user_switch, const SPOOL_USER_CTR *user,
3634                                 POLICY_HND *handle)
3635 {
3636         NT_PRINTER_INFO_LEVEL printer;  
3637         fstring name;
3638         fstring share_name;
3639
3640         clear_handle(handle);
3641         
3642         /* NULLify info_2 here */
3643         /* don't put it in convert_printer_info as it's used also with non-NULL values */
3644         printer.info_2=NULL;
3645
3646         /* convert from UNICODE to ASCII */
3647         convert_printer_info(info, &printer, 2);
3648
3649         unistr2_to_ascii(share_name, &((info->info_2)->printername), sizeof(share_name)-1);
3650         
3651         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname, share_name);
3652
3653         /* write the ASCII on disk */
3654         if (add_a_printer(printer, 2) != 0x0)
3655                 return ERROR_ACCESS_DENIED;
3656
3657         create_printer_hnd(handle);
3658
3659         open_printer_hnd(handle);
3660
3661         if (!set_printer_hnd_printertype(handle, name)) {
3662                 close_printer_handle(handle);
3663                 return ERROR_ACCESS_DENIED;
3664         }
3665
3666         if (!set_printer_hnd_printername(handle, name)) {
3667                 close_printer_handle(handle);
3668                 return ERROR_ACCESS_DENIED;
3669         }
3670
3671         return NT_STATUS_NO_PROBLEMO;
3672 }
3673
3674 /****************************************************************************
3675 ****************************************************************************/
3676 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
3677                                 const SPOOL_PRINTER_INFO_LEVEL *info,
3678                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
3679                                 uint32 user_switch, const SPOOL_USER_CTR *user,
3680                                 POLICY_HND *handle)
3681 {
3682         switch (level) {
3683                 case 1:
3684                         /* we don't handle yet */
3685                         /* but I know what to do ... */
3686                         return ERROR_INVALID_LEVEL;
3687                         break;
3688                 case 2:
3689                         return spoolss_addprinterex_level_2(uni_srv_name, info, 
3690                                                             unk0, unk1, unk2, unk3,
3691                                                             user_switch, user, handle);
3692                         break;
3693                 default:
3694                         return ERROR_INVALID_LEVEL;
3695                         break;
3696         }
3697 }
3698
3699
3700 /****************************************************************************
3701 ****************************************************************************/
3702 uint32 _spoolss_addprinterdriver( const UNISTR2 *server_name,
3703                                 uint32 level,
3704                                 const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
3705 {
3706         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3707         
3708         convert_printer_driver_info(info, &driver, level);
3709
3710         if (add_a_printer_driver(driver, level)!=0)
3711                 return ERROR_ACCESS_DENIED;
3712
3713         return NT_STATUS_NO_PROBLEMO;
3714 }
3715
3716 /****************************************************************************
3717 ****************************************************************************/
3718 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
3719 {
3720         init_unistr(&(info->name), name);
3721 }
3722
3723 /****************************************************************************
3724 ****************************************************************************/
3725 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3726 {
3727         pstring chaine;
3728         pstring long_archi;
3729         pstring short_archi;
3730         DRIVER_DIRECTORY_1 *info=NULL;
3731         
3732         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
3733                 return ERROR_NOT_ENOUGH_MEMORY;
3734         
3735         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
3736         get_short_archi(short_archi, long_archi);
3737                 
3738         slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
3739
3740         DEBUG(4,("printer driver directory: [%s]\n", chaine));
3741
3742         fill_driverdir_1(info, chaine);
3743         
3744         *needed += spoolss_size_driverdir_info_1(info);                                                     
3745
3746         if (!alloc_buffer_size(buffer, *needed)) {
3747                 safe_free(info);
3748                 return ERROR_INSUFFICIENT_BUFFER;
3749         }
3750
3751         new_smb_io_driverdir_1("", buffer, info, 0);
3752
3753         safe_free(info);
3754         
3755         if (*needed > offered)
3756                 return ERROR_INSUFFICIENT_BUFFER;
3757         else
3758                 return NT_STATUS_NO_PROBLEMO;
3759 }
3760
3761 /****************************************************************************
3762 ****************************************************************************/
3763 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
3764                                         NEW_BUFFER *buffer, uint32 offered, 
3765                                         uint32 *needed)
3766 {
3767         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
3768
3769         *needed=0;
3770
3771         switch(level) {
3772         case 1:
3773                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
3774                 break;
3775         default:
3776                 return ERROR_INVALID_LEVEL;
3777                 break;
3778         }
3779 }
3780         
3781 /****************************************************************************
3782 ****************************************************************************/
3783 uint32 _spoolss_enumprinterdata(const POLICY_HND *handle, uint32 idx,
3784                                 uint32 in_value_len, uint32 in_data_len,
3785                                 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
3786                                 uint32 *out_type,
3787                                 uint32 *out_max_data_len, uint8  **data_out, uint32 *out_data_len)
3788 {
3789         NT_PRINTER_INFO_LEVEL printer;
3790         
3791         fstring value;
3792         
3793         uint32 param_index;
3794         uint32 biggest_valuesize;
3795         uint32 biggest_datasize;
3796         uint32 data_len;
3797         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3798         int snum;
3799         uint8 *data=NULL;
3800         uint32 type;
3801
3802         ZERO_STRUCT(printer);
3803         
3804         *out_max_value_len=0;
3805         *out_value=NULL;
3806         *out_value_len=0;
3807
3808         *out_type=0;
3809
3810         *out_max_data_len=0;
3811         *data_out=NULL;
3812         *out_data_len=0;
3813
3814         DEBUG(5,("spoolss_enumprinterdata\n"));
3815
3816         if (!OPEN_HANDLE(Printer))
3817                 return ERROR_INVALID_HANDLE;
3818
3819         if (!get_printer_snum(handle, &snum))
3820                 return ERROR_INVALID_HANDLE;
3821         
3822         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0x0)
3823                 return ERROR_INVALID_HANDLE;
3824
3825         /* 
3826          * The NT machine wants to know the biggest size of value and data
3827          *
3828          * cf: MSDN EnumPrinterData remark section
3829          */
3830         if ( (in_value_len==0) && (in_data_len==0) ) {
3831                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
3832                 
3833                 param_index=0;
3834                 biggest_valuesize=0;
3835                 biggest_datasize=0;
3836                 
3837                 while (get_specific_param_by_index(printer, 2, param_index, value, &data, &type, &data_len)) {
3838                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
3839                         if (data_len > biggest_datasize) biggest_datasize=data_len;
3840
3841                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
3842
3843                         safe_free(data);
3844                         param_index++;
3845                 }
3846
3847                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
3848                 *out_value_len=2*(1+biggest_valuesize);
3849                 *out_data_len=biggest_datasize;
3850
3851                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
3852
3853                 free_a_printer(printer, 2);             
3854                 return NT_STATUS_NO_PROBLEMO;
3855         }
3856         
3857         /* 
3858          * the value len is wrong in NT sp3
3859          * that's the number of bytes not the number of unicode chars
3860          */
3861
3862         if (!get_specific_param_by_index(printer, 2, idx, value, &data, &type, &data_len)) {
3863                 free_a_printer(printer, 2);
3864                 safe_free(data);
3865                 return ERROR_NO_MORE_ITEMS;
3866         }
3867
3868         /* 
3869          * the value is:
3870          * - counted in bytes in the request
3871          * - counted in UNICODE chars in the max reply
3872          * - counted in bytes in the real size
3873          *
3874          * take a pause *before* coding not *during* coding
3875          */
3876          
3877         *out_max_value_len=in_value_len;
3878         if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
3879                 free_a_printer(printer, 2);
3880                 safe_free(data);
3881                 return ERROR_NOT_ENOUGH_MEMORY;
3882         }
3883         ascii_to_unistr((char *)*out_value, value, *out_max_value_len);
3884         *out_value_len=2*(1+strlen(value));
3885
3886         *out_type=type;
3887
3888         /* the data is counted in bytes */
3889         *out_max_data_len=in_data_len;
3890         if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
3891                 free_a_printer(printer, 2);
3892                 safe_free(data);
3893                 return ERROR_NOT_ENOUGH_MEMORY;
3894         }
3895         memcpy(*data_out, data, data_len);
3896         *out_data_len=data_len;
3897
3898         safe_free(data);
3899         
3900         free_a_printer(printer, 2);
3901         return NT_STATUS_NO_PROBLEMO;
3902 }
3903
3904 /****************************************************************************
3905 ****************************************************************************/
3906 uint32 _spoolss_setprinterdata( const POLICY_HND *handle,
3907                                 const UNISTR2 *value,
3908                                 uint32 type,
3909                                 uint32 max_len,
3910                                 const uint8 *data,
3911                                 uint32 real_len,
3912                                 uint32 numeric_data)
3913 {
3914         NT_PRINTER_INFO_LEVEL printer;
3915         NT_PRINTER_PARAM *param = NULL;
3916                 
3917         int snum=0;
3918         uint32 status = 0x0;
3919         Printer_entry *Printer=find_printer_index_by_hnd(handle);
3920         
3921         DEBUG(5,("spoolss_setprinterdata\n"));
3922
3923         
3924         if (!OPEN_HANDLE(Printer))
3925                 return ERROR_INVALID_HANDLE;
3926
3927         if (!get_printer_snum(handle, &snum))
3928                 return ERROR_INVALID_HANDLE;
3929
3930         status = get_a_printer(&printer, 2, lp_servicename(snum));
3931         if (status != 0x0)
3932                 return ERROR_INVALID_NAME;
3933
3934         convert_specific_param(&param, value , type, data, real_len);
3935         unlink_specific_param_if_exist(printer.info_2, param);
3936         
3937         if (!add_a_specific_param(printer.info_2, param))
3938                 status = ERROR_INVALID_PARAMETER;
3939         else
3940                 status = add_a_printer(printer, 2);
3941
3942         free_a_printer(printer, 2);
3943         
3944         return status;
3945 }
3946
3947 /****************************************************************************
3948 ****************************************************************************/
3949 uint32 _spoolss_addform( const POLICY_HND *handle,
3950                                 uint32 level,
3951                                 const FORM *form)
3952 {
3953         int count=0;
3954         nt_forms_struct *list=NULL;
3955         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3956
3957         DEBUG(5,("spoolss_addform\n"));
3958
3959         if (!OPEN_HANDLE(Printer))
3960                 return ERROR_INVALID_HANDLE;
3961
3962         count=get_ntforms(&list);
3963         if(!add_a_form(&list, form, &count))
3964                 return ERROR_NOT_ENOUGH_MEMORY;
3965         write_ntforms(&list, count);
3966
3967         safe_free(list);
3968
3969         return 0x0;
3970 }
3971
3972 /****************************************************************************
3973 ****************************************************************************/
3974 uint32 _spoolss_setform( const POLICY_HND *handle,
3975                                 const UNISTR2 *uni_name,
3976                                 uint32 level,
3977                                 const FORM *form)
3978 {
3979         int count=0;
3980         nt_forms_struct *list=NULL;
3981         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3982
3983         DEBUG(5,("spoolss_setform\n"));
3984
3985         if (!OPEN_HANDLE(Printer))
3986         {
3987                 return ERROR_INVALID_HANDLE;
3988         }
3989         count=get_ntforms(&list);
3990         update_a_form(&list, form, count);
3991         write_ntforms(&list, count);
3992
3993         safe_free(list);
3994
3995         return 0x0;
3996 }
3997
3998 /****************************************************************************
3999  enumprintprocessors level 1.
4000 ****************************************************************************/
4001 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4002 {
4003         PRINTPROCESSOR_1 *info_1=NULL;
4004         
4005         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
4006                 return ERROR_NOT_ENOUGH_MEMORY;
4007
4008         (*returned) = 0x1;
4009         
4010         init_unistr(&(info_1->name), "winprint");
4011
4012         *needed += spoolss_size_printprocessor_info_1(info_1);
4013
4014         if (!alloc_buffer_size(buffer, *needed))
4015                 return ERROR_INSUFFICIENT_BUFFER;
4016
4017         smb_io_printprocessor_info_1("", buffer, info_1, 0);
4018
4019         safe_free(info_1);
4020
4021         if (*needed > offered) {
4022                 *returned=0;
4023                 return ERROR_INSUFFICIENT_BUFFER;
4024         }
4025         else
4026                 return NT_STATUS_NO_PROBLEMO;
4027 }
4028
4029 /****************************************************************************
4030 ****************************************************************************/
4031 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
4032                                     NEW_BUFFER *buffer, uint32 offered, 
4033                                     uint32 *needed, uint32 *returned)
4034 {
4035         DEBUG(5,("spoolss_enumprintprocessors\n"));
4036
4037         /* 
4038          * Enumerate the print processors ...
4039          *
4040          * Just reply with "winprint", to keep NT happy
4041          * and I can use my nice printer checker.
4042          */
4043         
4044         *returned=0;
4045         *needed=0;
4046         
4047         switch (level) {
4048         case 1:
4049                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
4050                 break;
4051         default:
4052                 return ERROR_INVALID_LEVEL;
4053                 break;
4054         }
4055 }
4056
4057 /****************************************************************************
4058  enumprintprocdatatypes level 1.
4059 ****************************************************************************/
4060 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4061 {
4062         PRINTPROCDATATYPE_1 *info_1=NULL;
4063         
4064         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
4065                 return ERROR_NOT_ENOUGH_MEMORY;
4066
4067         (*returned) = 0x1;
4068         
4069         init_unistr(&(info_1->name), "RAW");
4070
4071         *needed += spoolss_size_printprocdatatype_info_1(info_1);
4072
4073         if (!alloc_buffer_size(buffer, *needed))
4074                 return ERROR_INSUFFICIENT_BUFFER;
4075
4076         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
4077
4078         safe_free(info_1);
4079
4080         if (*needed > offered) {
4081                 *returned=0;
4082                 return ERROR_INSUFFICIENT_BUFFER;
4083         }
4084         else
4085                 return NT_STATUS_NO_PROBLEMO;
4086 }
4087
4088 /****************************************************************************
4089 ****************************************************************************/
4090 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
4091                                         NEW_BUFFER *buffer, uint32 offered, 
4092                                         uint32 *needed, uint32 *returned)
4093 {
4094         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
4095         
4096         *returned=0;
4097         *needed=0;
4098         
4099         switch (level) {
4100         case 1:
4101                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
4102                 break;
4103         default:
4104                 return ERROR_INVALID_LEVEL;
4105                 break;
4106         }
4107 }
4108
4109 /****************************************************************************
4110  enumprintmonitors level 1.
4111 ****************************************************************************/
4112 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4113 {
4114         PRINTMONITOR_1 *info_1=NULL;
4115         
4116         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
4117                 return ERROR_NOT_ENOUGH_MEMORY;
4118
4119         (*returned) = 0x1;
4120         
4121         init_unistr(&(info_1->name), "Local Port");
4122
4123         *needed += spoolss_size_printmonitor_info_1(info_1);
4124
4125         if (!alloc_buffer_size(buffer, *needed))
4126                 return ERROR_INSUFFICIENT_BUFFER;
4127
4128         smb_io_printmonitor_info_1("", buffer, info_1, 0);
4129
4130         safe_free(info_1);
4131
4132         if (*needed > offered) {
4133                 *returned=0;
4134                 return ERROR_INSUFFICIENT_BUFFER;
4135         }
4136         else
4137                 return NT_STATUS_NO_PROBLEMO;
4138 }
4139
4140 /****************************************************************************
4141  enumprintmonitors level 2.
4142 ****************************************************************************/
4143 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4144 {
4145         PRINTMONITOR_2 *info_2=NULL;
4146         
4147         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
4148                 return ERROR_NOT_ENOUGH_MEMORY;
4149
4150         (*returned) = 0x1;
4151         
4152         init_unistr(&(info_2->name), "Local Port");
4153         init_unistr(&(info_2->environment), "Windows NT X86");
4154         init_unistr(&(info_2->dll_name), "localmon.dll");
4155
4156         *needed += spoolss_size_printmonitor_info_2(info_2);
4157
4158         if (!alloc_buffer_size(buffer, *needed))
4159                 return ERROR_INSUFFICIENT_BUFFER;
4160
4161         smb_io_printmonitor_info_2("", buffer, info_2, 0);
4162
4163         safe_free(info_2);
4164
4165         if (*needed > offered) {
4166                 *returned=0;
4167                 return ERROR_INSUFFICIENT_BUFFER;
4168         }
4169         else
4170                 return NT_STATUS_NO_PROBLEMO;
4171 }
4172
4173 /****************************************************************************
4174 ****************************************************************************/
4175 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
4176                                     NEW_BUFFER *buffer, uint32 offered, 
4177                                     uint32 *needed, uint32 *returned)
4178 {
4179         DEBUG(5,("spoolss_enumprintmonitors\n"));
4180
4181         /* 
4182          * Enumerate the print monitors ...
4183          *
4184          * Just reply with "Local Port", to keep NT happy
4185          * and I can use my nice printer checker.
4186          */
4187         
4188         *returned=0;
4189         *needed=0;
4190         
4191         switch (level) {
4192         case 1:
4193                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
4194                 break;          
4195         case 2:
4196                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
4197                 break;
4198         default:
4199                 return ERROR_INVALID_LEVEL;
4200                 break;
4201         }
4202 }
4203
4204 /****************************************************************************
4205 ****************************************************************************/
4206 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4207 {
4208         int i=0;
4209         BOOL found=False;
4210         JOB_INFO_1 *info_1=NULL;
4211
4212         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
4213
4214         if (info_1 == NULL) {
4215                 safe_free(queue);
4216                 return ERROR_NOT_ENOUGH_MEMORY;
4217         }
4218                 
4219         for (i=0; i<count && found==False; i++) {
4220                 if (queue[i].job==(int)jobid)
4221                         found=True;
4222         }
4223         
4224         if (found==False) {
4225                 safe_free(queue);
4226                 safe_free(info_1);
4227                 /* I shoud reply something else ... I can't find the good one */
4228                 return NT_STATUS_NO_PROBLEMO;
4229         }
4230         
4231         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
4232         
4233         safe_free(queue);
4234         
4235         *needed += spoolss_size_job_info_1(info_1);
4236
4237         if (!alloc_buffer_size(buffer, *needed)) {
4238                 safe_free(info_1);
4239                 return ERROR_INSUFFICIENT_BUFFER;
4240         }
4241
4242         new_smb_io_job_info_1("", buffer, info_1, 0);
4243
4244         safe_free(info_1);
4245
4246         if (*needed > offered)
4247                 return ERROR_INSUFFICIENT_BUFFER;
4248         else
4249                 return NT_STATUS_NO_PROBLEMO;
4250 }
4251
4252
4253 /****************************************************************************
4254 ****************************************************************************/
4255 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4256 {
4257         int i=0;
4258         BOOL found=False;
4259         JOB_INFO_2 *info_2=NULL;
4260         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
4261
4262         if (info_2 == NULL) {
4263                 safe_free(queue);
4264                 return ERROR_NOT_ENOUGH_MEMORY;
4265         }
4266
4267         for (i=0; i<count && found==False; i++) {
4268                 if (queue[i].job==(int)jobid)
4269                         found=True;
4270         }
4271         
4272         if (found==False) {
4273                 safe_free(queue);
4274                 safe_free(info_2);
4275                 /* I shoud reply something else ... I can't find the good one */
4276                 return NT_STATUS_NO_PROBLEMO;
4277         }
4278         
4279         fill_job_info_2(info_2, &(queue[i-1]), i, snum);
4280         
4281         safe_free(queue);
4282         
4283         *needed += spoolss_size_job_info_2(info_2);
4284
4285         if (!alloc_buffer_size(buffer, *needed)) {
4286                 safe_free(info_2);
4287                 return ERROR_INSUFFICIENT_BUFFER;
4288         }
4289
4290         new_smb_io_job_info_2("", buffer, info_2, 0);
4291
4292         safe_free(info_2);
4293
4294         if (*needed > offered)
4295                 return ERROR_INSUFFICIENT_BUFFER;
4296         else
4297                 return NT_STATUS_NO_PROBLEMO;
4298 }
4299
4300 /****************************************************************************
4301 ****************************************************************************/
4302 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
4303                         NEW_BUFFER *buffer, uint32 offered, 
4304                         uint32 *needed)
4305 {
4306         int snum;
4307         int count;
4308         print_queue_struct *queue=NULL;
4309         print_status_struct prt_status;
4310
4311         DEBUG(5,("spoolss_getjob\n"));
4312         
4313         memset(&prt_status, 0, sizeof(prt_status));
4314
4315         *needed=0;
4316         
4317         if (!get_printer_snum(handle, &snum))
4318                 return ERROR_INVALID_HANDLE;
4319         
4320         count = print_queue_status(snum, &queue, &prt_status);
4321         
4322         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
4323                      count, prt_status.status, prt_status.message));
4324                 
4325         switch (level) {
4326         case 1:
4327                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
4328                 break;
4329         case 2:
4330                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
4331                 break;
4332         default:
4333                 safe_free(queue);
4334                 return ERROR_INVALID_LEVEL;
4335                 break;
4336         }
4337 }
4338