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