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