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