A rather big change set ! (listed in no particular order)
[samba.git] / source3 / 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                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2653
2654         fill_printer_driver_info_3(info, driver, servername);
2655
2656         free_a_printer(&printer,2);
2657
2658         return NT_STATUS_NO_PROBLEMO;
2659 }
2660
2661 /****************************************************************************
2662 ****************************************************************************/
2663
2664 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2665 {
2666         safe_free(info->dependentfiles);
2667 }
2668
2669 /****************************************************************************
2670 ****************************************************************************/
2671 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2672 {
2673         DRIVER_INFO_1 *info=NULL;
2674         uint32 status;
2675         
2676         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2677                 return ERROR_NOT_ENOUGH_MEMORY;
2678         
2679         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2680         if (status != NT_STATUS_NO_PROBLEMO) {
2681                 safe_free(info);
2682                 return status;
2683         }
2684
2685         /* check the required size. */  
2686         *needed += spoolss_size_printer_driver_info_1(info);
2687
2688         if (!alloc_buffer_size(buffer, *needed)) {
2689                 safe_free(info);
2690                 return ERROR_INSUFFICIENT_BUFFER;
2691         }
2692
2693         /* fill the buffer with the structures */
2694         new_smb_io_printer_driver_info_1("", buffer, info, 0);  
2695
2696         /* clear memory */
2697         safe_free(info);
2698
2699         if (*needed > offered)
2700                 return ERROR_INSUFFICIENT_BUFFER;
2701         else
2702                 return NT_STATUS_NO_PROBLEMO;
2703 }
2704
2705 /****************************************************************************
2706 ****************************************************************************/
2707 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2708 {
2709         DRIVER_INFO_2 *info=NULL;
2710         uint32 status;
2711         
2712         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
2713                 return ERROR_NOT_ENOUGH_MEMORY;
2714         
2715         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
2716         if (status != NT_STATUS_NO_PROBLEMO) {
2717                 safe_free(info);
2718                 return status;
2719         }
2720
2721         /* check the required size. */  
2722         *needed += spoolss_size_printer_driver_info_2(info);
2723
2724         if (!alloc_buffer_size(buffer, *needed)) {
2725                 safe_free(info);
2726                 return ERROR_INSUFFICIENT_BUFFER;
2727         }
2728
2729         /* fill the buffer with the structures */
2730         new_smb_io_printer_driver_info_2("", buffer, info, 0);  
2731
2732         /* clear memory */
2733         safe_free(info);
2734
2735         if (*needed > offered)
2736                 return ERROR_INSUFFICIENT_BUFFER;
2737         else
2738                 return NT_STATUS_NO_PROBLEMO;
2739 }
2740
2741 /****************************************************************************
2742 ****************************************************************************/
2743 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2744 {
2745         DRIVER_INFO_3 info;
2746         uint32 status;
2747
2748         ZERO_STRUCT(info);
2749
2750         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
2751         if (status != NT_STATUS_NO_PROBLEMO) {
2752                 return status;
2753         }
2754
2755         /* check the required size. */  
2756         *needed += spoolss_size_printer_driver_info_3(&info);
2757
2758         if (!alloc_buffer_size(buffer, *needed)) {
2759                 free_printer_driver_info_3(&info);
2760                 return ERROR_INSUFFICIENT_BUFFER;
2761         }
2762
2763         /* fill the buffer with the structures */
2764         new_smb_io_printer_driver_info_3("", buffer, &info, 0);
2765
2766         free_printer_driver_info_3(&info);
2767
2768         if (*needed > offered)
2769                 return ERROR_INSUFFICIENT_BUFFER;
2770         else
2771                 return NT_STATUS_NO_PROBLEMO;
2772 }
2773
2774 /****************************************************************************
2775 ****************************************************************************/
2776 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level, 
2777                                 uint32 clientmajorversion, uint32 clientminorversion,
2778                                 NEW_BUFFER *buffer, uint32 offered,
2779                                 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
2780 {
2781         fstring servername;
2782         fstring architecture;
2783         int snum;
2784
2785         DEBUG(4,("_spoolss_getprinterdriver2\n"));
2786
2787         *needed=0;
2788         *servermajorversion=0;
2789         *serverminorversion=0;
2790
2791         pstrcpy(servername, global_myname);
2792         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
2793
2794         if (!get_printer_snum(handle, &snum))
2795                 return ERROR_INVALID_HANDLE;
2796
2797         switch (level) {
2798         case 1:
2799                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
2800                 break;
2801         case 2:
2802                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
2803                 break;                          
2804         case 3:
2805                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
2806                 break;                          
2807         default:
2808                 return ERROR_INVALID_LEVEL;
2809                 break;
2810         }
2811 }
2812
2813 /****************************************************************************
2814 ****************************************************************************/
2815 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
2816 {
2817         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2818
2819         if (OPEN_HANDLE(Printer)) {
2820                 Printer->page_started=True;
2821                 return 0x0;
2822         }
2823
2824         DEBUG(3,("Error in startpageprinter printer handle\n"));
2825         return ERROR_INVALID_HANDLE;
2826 }
2827
2828 /****************************************************************************
2829 ****************************************************************************/
2830 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
2831 {
2832         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2833
2834         if (!OPEN_HANDLE(Printer)) {
2835                 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
2836                 return ERROR_INVALID_HANDLE;
2837         }
2838         
2839         Printer->page_started=False;
2840
2841         return NT_STATUS_NO_PROBLEMO;
2842 }
2843
2844
2845 /********************************************************************
2846  * api_spoolss_getprinter
2847  * called from the spoolss dispatcher
2848  *
2849  ********************************************************************/
2850 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
2851                                 pipes_struct *p, DOC_INFO *docinfo, 
2852                                 uint32 *jobid)
2853 {
2854         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
2855         int snum;
2856         pstring jobname;
2857         fstring datatype;
2858         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2859         struct current_user user;
2860
2861         if (!OPEN_HANDLE(Printer)) {
2862                 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
2863                 return ERROR_INVALID_HANDLE;
2864         }
2865
2866         if (p->ntlmssp_auth_validated) {
2867                 memcpy(&user, &p->pipe_user, sizeof(user));
2868         } else {
2869                 extern struct current_user current_user;
2870                 memcpy(&user, &current_user, sizeof(user));
2871         }
2872
2873         /*
2874          * a nice thing with NT is it doesn't listen to what you tell it.
2875          * when asked to send _only_ RAW datas, it tries to send datas
2876          * in EMF format.
2877          *
2878          * So I add checks like in NT Server ...
2879          *
2880          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
2881          * there's a bug in NT client-side code, so we'll fix it in the
2882          * server-side code. *nnnnnggggh!*
2883          */
2884         
2885         if (info_1->p_datatype != 0)
2886         {
2887                 unistr2_to_ascii(datatype, &(info_1->docname), sizeof(datatype));
2888                 if (strcmp(datatype, "RAW") != 0)
2889                 {
2890                         (*jobid)=0;
2891                         return ERROR_INVALID_DATATYPE;
2892                 }               
2893         }                
2894         
2895         /* get the share number of the printer */
2896         if (!get_printer_snum(handle, &snum))
2897         {
2898                 return ERROR_INVALID_HANDLE;
2899         }
2900
2901         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
2902         
2903         Printer->jobid = print_job_start(&user, snum, jobname);
2904
2905         /* need to map error codes properly - for now give out of
2906            memory as I don't know the correct codes (tridge) */
2907         if (Printer->jobid == -1) {
2908                 return ERROR_NOT_ENOUGH_MEMORY;
2909         }
2910         
2911         Printer->document_started=True;
2912         (*jobid) = Printer->jobid;
2913
2914         return 0x0;
2915 }
2916
2917 /********************************************************************
2918  * api_spoolss_getprinter
2919  * called from the spoolss dispatcher
2920  *
2921  ********************************************************************/
2922 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
2923 {
2924         Printer_entry *Printer=find_printer_index_by_hnd(handle);
2925         
2926         if (!OPEN_HANDLE(Printer)) {
2927                 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
2928                 return ERROR_INVALID_HANDLE;
2929         }
2930         
2931         Printer->document_started=False;
2932         print_job_end(Printer->jobid);
2933         /* error codes unhandled so far ... */
2934
2935         return 0x0;
2936 }
2937
2938 /****************************************************************************
2939 ****************************************************************************/
2940 uint32 _spoolss_writeprinter( POLICY_HND *handle,
2941                                 uint32 buffer_size,
2942                                 uint8 *buffer,
2943                                 uint32 *buffer_written)
2944 {
2945         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2946         
2947         if (!OPEN_HANDLE(Printer)) {
2948                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
2949                 return ERROR_INVALID_HANDLE;
2950         }
2951
2952         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, 
2953                                             buffer_size);
2954
2955         return 0x0;
2956 }
2957
2958 /********************************************************************
2959  * api_spoolss_getprinter
2960  * called from the spoolss dispatcher
2961  *
2962  ********************************************************************/
2963 static uint32 control_printer(POLICY_HND *handle, uint32 command,
2964                               pipes_struct *p)
2965 {
2966         struct current_user user;
2967         int snum;
2968         Printer_entry *Printer = find_printer_index_by_hnd(handle);
2969
2970         if (p->ntlmssp_auth_validated) {
2971                 memcpy(&user, &p->pipe_user, sizeof(user));
2972         } else {
2973                 extern struct current_user current_user;
2974                 memcpy(&user, &current_user, sizeof(user));
2975         }
2976
2977         if (!OPEN_HANDLE(Printer)) {
2978                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
2979                 return ERROR_INVALID_HANDLE;
2980         }
2981
2982         if (!get_printer_snum(handle, &snum) )   
2983                 return ERROR_INVALID_HANDLE;
2984
2985         switch (command) {
2986         case PRINTER_CONTROL_PAUSE:
2987                 if (print_queue_pause(&user, snum)) {
2988                         return 0;
2989                 }
2990                 break;
2991         case PRINTER_CONTROL_RESUME:
2992         case PRINTER_CONTROL_UNPAUSE:
2993                 if (print_queue_resume(&user, snum)) {
2994                         return 0;
2995                 }
2996                 break;
2997         case PRINTER_CONTROL_PURGE:
2998                 if (print_queue_purge(&user, snum)) {
2999                         return 0;
3000                 }
3001                 break;
3002         }
3003
3004         return ERROR_INVALID_FUNCTION;
3005 }
3006
3007 /********************************************************************
3008  * called by spoolss_api_setprinter
3009  * when updating a printer description
3010  ********************************************************************/
3011 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3012                                  const SPOOL_PRINTER_INFO_LEVEL *info,
3013                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3014 {
3015         SEC_DESC_BUF *old_secdesc_ctr = NULL;
3016         struct current_user user;
3017         uint32 acc_granted, status, result;
3018
3019         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3020
3021         if (!OPEN_HANDLE(Printer)) {
3022                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3023                 return ERROR_INVALID_HANDLE;
3024         }
3025
3026         /* Work out which user is performing the operation */
3027
3028         if (p->ntlmssp_auth_validated) {
3029                 memcpy(&user, &p->pipe_user, sizeof(user));
3030         } else {
3031                 extern struct current_user current_user;
3032                 memcpy(&user, &current_user, sizeof(user));
3033         }
3034
3035         /* Get old security descriptor */
3036
3037         if (!nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr)) {
3038                 DEBUG(3, ("could not get old security descriptor for "
3039                           "printer %s", Printer->dev.handlename));
3040                 return ERROR_INVALID_FUNCTION;
3041         }
3042
3043         /* Check the user has permissions to change the security
3044            descriptor.  By experimentation with two NT machines, the user
3045            requires Full Access to the printer to change security
3046            information. */ 
3047
3048         if (!se_access_check(old_secdesc_ctr->sec, &user,
3049                              PRINTER_ACE_FULL_CONTROL, &acc_granted,
3050                              &status)) {
3051                 DEBUG(3, ("security descriptor change denied by existing "
3052                           "security descriptor\n"));
3053                 result = status;
3054                 goto done;
3055         }
3056
3057         result = nt_printing_setsec(Printer->dev.handlename, secdesc_ctr);
3058
3059  done:
3060         free_sec_desc_buf(&old_secdesc_ctr);
3061         return result;
3062 }
3063
3064 /********************************************************************
3065  Do Samba sanity checks on a printer info struct.
3066  ********************************************************************/
3067
3068 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3069 {
3070         /*
3071          * Ensure that this printer is shared under the correct name
3072          * as this is what Samba insists upon.
3073          */
3074
3075         if (!(info->attributes & PRINTER_ATTRIBUTE_SHARED)) {
3076                 DEBUG(10,("check_printer_ok: SHARED check failed (%x).\n", (unsigned int)info->attributes ));
3077                 return False;
3078         }
3079
3080         if (!(info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY)) {
3081                 /* NT forgets to set the raw attribute but sends the correct type. */
3082                 if (strequal(info->datatype, "RAW"))
3083                         info->attributes |= PRINTER_ATTRIBUTE_RAW_ONLY;
3084                 else {
3085                         DEBUG(10,("check_printer_ok: RAW check failed (%x).\n", (unsigned int)info->attributes ));
3086                         return False;
3087                 }
3088         }
3089
3090         if (!strequal(info->sharename, lp_servicename(snum))) {
3091                 DEBUG(10,("check_printer_ok: NAME check failed (%s) (%s).\n", info->sharename, lp_servicename(snum)));
3092                 return False;
3093         }
3094
3095         return True;
3096 }
3097
3098 /********************************************************************
3099  * called by spoolss_api_setprinter
3100  * when updating a printer description
3101  ********************************************************************/
3102
3103 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3104                            const SPOOL_PRINTER_INFO_LEVEL *info,
3105                            DEVICEMODE *devmode)
3106 {
3107         int snum;
3108         NT_PRINTER_INFO_LEVEL *printer = NULL;
3109         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3110         SEC_DESC_BUF *sd = NULL;
3111         uint32 result, acc_granted;
3112         extern struct current_user current_user;
3113
3114         DEBUG(8,("update_printer\n"));
3115         
3116         result = NT_STATUS_NO_PROBLEMO;
3117
3118         /* Check calling user has permission to update printer description */ 
3119
3120 #if 0 /* JFMTEST */
3121         if (!nt_printing_getsec(Printer->dev.handlename, &sd)) {
3122                 DEBUG(3, ("Could not get security descriptor for printer %s",
3123                           Printer->dev.handlename));
3124                 result = ERROR_INVALID_FUNCTION;
3125                 goto done;
3126         }
3127
3128         if (!se_access_check(sd->sec, &current_user,
3129                              PRINTER_ACE_FULL_CONTROL, &acc_granted,
3130                              &result)) {
3131                 DEBUG(3, ("printer property change denied by security "
3132                           "descriptor\n"));
3133                 goto done;
3134         }
3135 #endif
3136         if (level!=2) {
3137                 DEBUG(0,("Send a mail to samba@samba.org\n"));
3138                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3139                 result = ERROR_INVALID_LEVEL;
3140                 goto done;
3141         }
3142
3143         if (!OPEN_HANDLE(Printer)) {
3144                 result = ERROR_INVALID_HANDLE;
3145                 goto done;
3146         }
3147
3148         if (!get_printer_snum(handle, &snum)) {
3149                 result = ERROR_INVALID_HANDLE;
3150                 goto done;
3151         }
3152         
3153         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0) {
3154                 result = ERROR_INVALID_HANDLE;
3155                 goto done;
3156         }
3157
3158         DEBUGADD(8,("Converting info_2 struct\n"));
3159
3160         /*
3161          * convert_printer_info converts the incoming
3162          * info from the client and overwrites the info
3163          * just read from the tdb in the pointer 'printer'.
3164          */
3165
3166         convert_printer_info(info, printer, level);
3167         
3168         if (info->info_2->devmode_ptr != 0) {
3169                 /* we have a valid devmode
3170                    convert it and link it*/
3171
3172                 /*
3173                  * Ensure printer->info_2->devmode is a valid pointer 
3174                  * as we will be overwriting it in convert_devicemode().
3175                  */
3176                 
3177                 if (printer->info_2->devmode == NULL)
3178                         printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3179
3180                 DEBUGADD(8,("Converting the devicemode struct\n"));
3181                 convert_devicemode(devmode, printer->info_2->devmode);
3182
3183         } else {
3184                 if (printer->info_2->devmode != NULL)
3185                         free_nt_devicemode(&printer->info_2->devmode);
3186                 printer->info_2->devmode=NULL;
3187         }
3188
3189         /*
3190          * Do sanity check on the requested changes for Samba.
3191          */
3192
3193         if (!check_printer_ok(printer->info_2, snum)) {
3194                 result = ERROR_ACCESS_DENIED;
3195                 goto done;
3196         }
3197
3198         if (add_a_printer(*printer, 2)!=0) {
3199                 /* I don't really know what to return here !!! */
3200                 result = ERROR_ACCESS_DENIED;
3201                 goto done;
3202         }
3203
3204  done:
3205         free_a_printer(&printer, 2);
3206         free_sec_desc_buf(&sd);
3207
3208         return result;
3209 }
3210
3211 /****************************************************************************
3212 ****************************************************************************/
3213 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3214                            const SPOOL_PRINTER_INFO_LEVEL *info,
3215                            DEVMODE_CTR devmode_ctr,
3216                            SEC_DESC_BUF *secdesc_ctr,
3217                            uint32 command, pipes_struct *p)
3218 {
3219         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3220         
3221         if (!OPEN_HANDLE(Printer)) {
3222                 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3223                 return ERROR_INVALID_HANDLE;
3224         }
3225
3226         /* check the level */   
3227         switch (level) {
3228                 case 0:
3229                         return control_printer(handle, command, p);
3230                         break;
3231                 case 2:
3232                         return update_printer(handle, level, info, devmode_ctr.devmode);
3233                         break;
3234                 case 3:
3235                         return update_printer_sec(handle, level, info, p,
3236                                                   secdesc_ctr);
3237                         break;
3238                 default:
3239                         return ERROR_INVALID_LEVEL;
3240                         break;
3241         }
3242 }
3243
3244 /****************************************************************************
3245 ****************************************************************************/
3246 uint32 _spoolss_fcpn(POLICY_HND *handle)
3247 {
3248         Printer_entry *Printer= find_printer_index_by_hnd(handle);
3249         
3250         if (!OPEN_HANDLE(Printer)) {
3251                 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3252                 return ERROR_INVALID_HANDLE;
3253         }
3254         
3255         Printer->notify.flags=0;
3256         Printer->notify.options=0;
3257         Printer->notify.localmachine[0]='\0';
3258         Printer->notify.printerlocal=0;
3259         if (Printer->notify.option)
3260                 safe_free(Printer->notify.option->ctr.type);
3261         safe_free(Printer->notify.option);
3262         Printer->notify.option=NULL;
3263         
3264         return NT_STATUS_NO_PROBLEMO;
3265 }
3266
3267 /****************************************************************************
3268 ****************************************************************************/
3269 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3270                         NEW_BUFFER *buffer, uint32 offered)
3271 {
3272         return NT_STATUS_NO_PROBLEMO;
3273 }
3274
3275 /****************************************************************************
3276 ****************************************************************************/
3277 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3278                             int position, int snum)
3279 {
3280         pstring temp_name;
3281         
3282         struct tm *t;
3283         time_t unixdate = time(NULL);
3284         
3285         t=gmtime(&unixdate);
3286         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3287
3288         job_info->jobid=queue->job;     
3289         init_unistr(&job_info->printername, lp_servicename(snum));
3290         init_unistr(&job_info->machinename, temp_name);
3291         init_unistr(&job_info->username, queue->user);
3292         init_unistr(&job_info->document, queue->file);
3293         init_unistr(&job_info->datatype, "RAW");
3294         init_unistr(&job_info->text_status, "");
3295         job_info->status=nt_printj_status(queue->status);
3296         job_info->priority=queue->priority;
3297         job_info->position=position;
3298         job_info->totalpages=0;
3299         job_info->pagesprinted=0;
3300
3301         make_systemtime(&(job_info->submitted), t);
3302 }
3303
3304 /****************************************************************************
3305 ****************************************************************************/
3306 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3307                             int position, int snum)
3308 {
3309         pstring temp_name;
3310         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3311         pstring chaine;
3312
3313         struct tm *t;
3314         time_t unixdate = time(NULL);
3315
3316         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3317                 return False;
3318         
3319         t=gmtime(&unixdate);
3320         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3321
3322         job_info->jobid=queue->job;
3323         
3324         snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3325
3326         init_unistr(&(job_info->printername), chaine);
3327         
3328         init_unistr(&job_info->machinename, temp_name);
3329         init_unistr(&job_info->username, queue->user);
3330         init_unistr(&job_info->document, queue->file);
3331         init_unistr(&job_info->notifyname, queue->user);
3332         init_unistr(&job_info->datatype, "RAW");
3333         init_unistr(&job_info->printprocessor, "winprint");
3334         init_unistr(&job_info->parameters, "");
3335         init_unistr(&job_info->text_status, "");
3336         
3337 /* and here the security descriptor */
3338
3339         job_info->status=nt_printj_status(queue->status);
3340         job_info->priority=queue->priority;
3341         job_info->position=position;
3342         job_info->starttime=0;
3343         job_info->untiltime=0;
3344         job_info->totalpages=0;
3345         job_info->size=queue->size;
3346         make_systemtime(&(job_info->submitted), t);
3347         job_info->timeelapsed=0;
3348         job_info->pagesprinted=0;
3349
3350         if((job_info->devmode = construct_dev_mode(snum, global_myname)) == NULL) {
3351                 free_a_printer(&ntprinter, 2);
3352                 return False;
3353         }
3354
3355         free_a_printer(&ntprinter, 2);
3356         return (True);
3357 }
3358
3359 /****************************************************************************
3360  Enumjobs at level 1.
3361 ****************************************************************************/
3362 static uint32 enumjobs_level1(print_queue_struct *queue, int snum, 
3363                               NEW_BUFFER *buffer, uint32 offered, 
3364                               uint32 *needed, uint32 *returned)
3365 {
3366         JOB_INFO_1 *info;
3367         int i;
3368         
3369         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3370         if (info==NULL) {
3371                 safe_free(queue);
3372                 *returned=0;
3373                 return ERROR_NOT_ENOUGH_MEMORY;
3374         }
3375         
3376         for (i=0; i<*returned; i++)
3377                 fill_job_info_1(&info[i], &queue[i], i, snum);
3378
3379         safe_free(queue);
3380
3381         /* check the required size. */  
3382         for (i=0; i<*returned; i++)
3383                 (*needed) += spoolss_size_job_info_1(&info[i]);
3384
3385         if (!alloc_buffer_size(buffer, *needed)) {
3386                 safe_free(info);
3387                 return ERROR_INSUFFICIENT_BUFFER;
3388         }
3389
3390         /* fill the buffer with the structures */
3391         for (i=0; i<*returned; i++)
3392                 new_smb_io_job_info_1("", buffer, &info[i], 0); 
3393
3394         /* clear memory */
3395         safe_free(info);
3396
3397         if (*needed > offered) {
3398                 *returned=0;
3399                 return ERROR_INSUFFICIENT_BUFFER;
3400         }
3401         else
3402                 return NT_STATUS_NO_PROBLEMO;
3403 }
3404
3405 /****************************************************************************
3406  Enumjobs at level 2.
3407 ****************************************************************************/
3408 static uint32 enumjobs_level2(print_queue_struct *queue, int snum, 
3409                               NEW_BUFFER *buffer, uint32 offered, 
3410                               uint32 *needed, uint32 *returned)
3411 {
3412         JOB_INFO_2 *info;
3413         int i;
3414         
3415         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
3416         if (info==NULL) {
3417                 safe_free(queue);
3418                 *returned=0;
3419                 return ERROR_NOT_ENOUGH_MEMORY;
3420         }
3421         
3422         for (i=0; i<*returned; i++)
3423                 fill_job_info_2(&(info[i]), &queue[i], i, snum);
3424
3425         safe_free(queue);
3426
3427         /* check the required size. */  
3428         for (i=0; i<*returned; i++)
3429                 (*needed) += spoolss_size_job_info_2(&info[i]);
3430
3431         if (!alloc_buffer_size(buffer, *needed)) {
3432                 safe_free(info);
3433                 return ERROR_INSUFFICIENT_BUFFER;
3434         }
3435
3436         /* fill the buffer with the structures */
3437         for (i=0; i<*returned; i++)
3438                 new_smb_io_job_info_2("", buffer, &info[i], 0); 
3439
3440         /* clear memory */
3441         safe_free(info);
3442
3443         if (*needed > offered) {
3444                 *returned=0;
3445                 return ERROR_INSUFFICIENT_BUFFER;
3446         }
3447         else
3448                 return NT_STATUS_NO_PROBLEMO;
3449 }
3450
3451 /****************************************************************************
3452  Enumjobs.
3453 ****************************************************************************/
3454 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,                    
3455                           NEW_BUFFER *buffer, uint32 offered,
3456                           uint32 *needed, uint32 *returned)
3457 {       
3458         int snum;
3459         print_queue_struct *queue=NULL;
3460         print_status_struct prt_status;
3461
3462         DEBUG(4,("_spoolss_enumjobs\n"));
3463
3464         ZERO_STRUCT(prt_status);
3465
3466         *needed=0;
3467         *returned=0;
3468
3469         if (!get_printer_snum(handle, &snum))
3470                 return ERROR_INVALID_HANDLE;
3471
3472         *returned = print_queue_status(snum, &queue, &prt_status);
3473         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
3474
3475         switch (level) {
3476         case 1:
3477                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
3478                 break;
3479         case 2:
3480                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
3481                 break;                          
3482         default:
3483                 safe_free(queue);
3484                 *returned=0;
3485                 return ERROR_INVALID_LEVEL;
3486                 break;
3487         }
3488 }
3489
3490
3491 /****************************************************************************
3492 ****************************************************************************/
3493 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
3494 {
3495         return 0x0;
3496 }
3497
3498 /****************************************************************************
3499 ****************************************************************************/
3500 uint32 _spoolss_setjob( POLICY_HND *handle,
3501                                 uint32 jobid,
3502                                 uint32 level,
3503                                 pipes_struct *p,
3504                                 JOB_INFO *ctr,
3505                                 uint32 command)
3506
3507 {
3508         struct current_user user;
3509         int snum;
3510         print_status_struct prt_status;
3511                 
3512         memset(&prt_status, 0, sizeof(prt_status));
3513
3514         if (!get_printer_snum(handle, &snum)) {
3515                 return ERROR_INVALID_HANDLE;
3516         }
3517
3518         if (!print_job_exists(jobid)) {
3519                 return ERROR_INVALID_PRINTER_NAME;
3520         }
3521         
3522         if (p->ntlmssp_auth_validated) {
3523                 memcpy(&user, &p->pipe_user, sizeof(user));
3524         } else {
3525                 extern struct current_user current_user;
3526                 memcpy(&user, &current_user, sizeof(user));
3527         }
3528
3529         switch (command) {
3530         case JOB_CONTROL_CANCEL:
3531         case JOB_CONTROL_DELETE:
3532                 if (print_job_delete(&user, jobid)) return 0x0;
3533                 break;
3534         case JOB_CONTROL_PAUSE:
3535                 if (print_job_pause(&user, jobid)) return 0x0;
3536                 break;
3537         case JOB_CONTROL_RESUME:
3538                 if (print_job_resume(&user, jobid)) return 0x0;
3539                 break;
3540         default:
3541                 return ERROR_INVALID_LEVEL;
3542         }
3543
3544         return ERROR_INVALID_HANDLE;
3545 }
3546
3547 /****************************************************************************
3548  Enumerates all printer drivers at level 1.
3549 ****************************************************************************/
3550 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3551 {
3552         int i;
3553         int ndrivers;
3554         uint32 version;
3555         fstring *list = NULL;
3556
3557         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3558         DRIVER_INFO_1 *driver_info_1=NULL;
3559
3560         *returned=0;
3561
3562 #define MAX_VERSION 4
3563
3564         for (version=0; version<MAX_VERSION; version++) {
3565                 list=NULL;
3566                 ndrivers=get_ntdrivers(&list, architecture, version);
3567                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
3568
3569                 if(ndrivers == -1)
3570                         return ERROR_NOT_ENOUGH_MEMORY;
3571
3572                 if(ndrivers != 0) {
3573                         if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
3574                                 safe_free(list);
3575                                 return ERROR_NOT_ENOUGH_MEMORY;
3576                         }
3577                 }
3578
3579                 for (i=0; i<ndrivers; i++) {
3580                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3581                         ZERO_STRUCT(driver);
3582                         get_a_printer_driver(&driver, 3, list[i], architecture, version);
3583                         fill_printer_driver_info_1(&(driver_info_1[*returned+i]), driver, servername, architecture );           
3584                 }       
3585
3586                 *returned+=ndrivers;
3587                 safe_free(list);
3588         }
3589         
3590         /* check the required size. */
3591         for (i=0; i<*returned; i++) {
3592                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3593                 *needed += spoolss_size_printer_driver_info_1(&(driver_info_1[i]));
3594         }
3595
3596         if (!alloc_buffer_size(buffer, *needed)) {
3597                 safe_free(driver_info_1);
3598                 return ERROR_INSUFFICIENT_BUFFER;
3599         }
3600
3601         /* fill the buffer with the form structures */
3602         for (i=0; i<*returned; i++) {
3603                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
3604                 new_smb_io_printer_driver_info_1("", buffer, &(driver_info_1[i]), 0);
3605         }
3606
3607         safe_free(driver_info_1);
3608
3609         if (*needed > offered) {
3610                 *returned=0;
3611                 return ERROR_INSUFFICIENT_BUFFER;
3612         }
3613         else
3614                 return NT_STATUS_NO_PROBLEMO;
3615 }
3616
3617 /****************************************************************************
3618  Enumerates all printer drivers at level 2.
3619 ****************************************************************************/
3620 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3621 {
3622         int i;
3623         int ndrivers;
3624         uint32 version;
3625         fstring *list = NULL;
3626
3627         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3628         DRIVER_INFO_2 *driver_info_2=NULL;
3629
3630         *returned=0;
3631
3632 #define MAX_VERSION 4
3633
3634         for (version=0; version<MAX_VERSION; version++) {
3635                 list=NULL;
3636                 ndrivers=get_ntdrivers(&list, architecture, version);
3637                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
3638
3639                 if(ndrivers == -1)
3640                         return ERROR_NOT_ENOUGH_MEMORY;
3641
3642                 if(ndrivers != 0) {
3643                         if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
3644                                 safe_free(list);
3645                                 return ERROR_NOT_ENOUGH_MEMORY;
3646                         }
3647                 }
3648                 
3649                 for (i=0; i<ndrivers; i++) {
3650                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3651                         ZERO_STRUCT(driver);
3652                         get_a_printer_driver(&driver, 3, list[i], architecture, version);
3653                         fill_printer_driver_info_2(&(driver_info_2[*returned+i]), driver, servername);          
3654                 }       
3655
3656                 *returned+=ndrivers;
3657                 safe_free(list);
3658         }
3659         
3660         /* check the required size. */
3661         for (i=0; i<*returned; i++) {
3662                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3663                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
3664         }
3665
3666         if (!alloc_buffer_size(buffer, *needed)) {
3667                 safe_free(driver_info_2);
3668                 return ERROR_INSUFFICIENT_BUFFER;
3669         }
3670
3671         /* fill the buffer with the form structures */
3672         for (i=0; i<*returned; i++) {
3673                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
3674                 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
3675         }
3676
3677         safe_free(driver_info_2);
3678
3679         if (*needed > offered) {
3680                 *returned=0;
3681                 return ERROR_INSUFFICIENT_BUFFER;
3682         }
3683         else
3684                 return NT_STATUS_NO_PROBLEMO;
3685 }
3686
3687 /****************************************************************************
3688  Enumerates all printer drivers at level 3.
3689 ****************************************************************************/
3690 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3691 {
3692         int i;
3693         int ndrivers;
3694         uint32 version;
3695         fstring *list = NULL;
3696
3697         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3698         DRIVER_INFO_3 *driver_info_3=NULL;
3699
3700         *returned=0;
3701
3702 #define MAX_VERSION 4
3703
3704         for (version=0; version<MAX_VERSION; version++) {
3705                 list=NULL;
3706                 ndrivers=get_ntdrivers(&list, architecture, version);
3707                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
3708
3709                 if(ndrivers == -1)
3710                         return ERROR_NOT_ENOUGH_MEMORY;
3711
3712                 if(ndrivers != 0) {
3713                         if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
3714                                 safe_free(list);
3715                                 return ERROR_NOT_ENOUGH_MEMORY;
3716                         }
3717                 }
3718
3719                 for (i=0; i<ndrivers; i++) {
3720                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3721                         ZERO_STRUCT(driver);
3722                         get_a_printer_driver(&driver, 3, list[i], architecture, version);
3723                         fill_printer_driver_info_3(&(driver_info_3[*returned+i]), driver, servername);          
3724                 }       
3725
3726                 *returned+=ndrivers;
3727                 safe_free(list);
3728         }
3729
3730         /* check the required size. */
3731         for (i=0; i<*returned; i++) {
3732                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3733                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
3734         }
3735
3736         if (!alloc_buffer_size(buffer, *needed)) {
3737                 safe_free(driver_info_3);
3738                 return ERROR_INSUFFICIENT_BUFFER;
3739         }
3740         
3741         /* fill the buffer with the driver structures */
3742         for (i=0; i<*returned; i++) {
3743                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
3744                 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
3745         }
3746
3747         for (i=0; i<*returned; i++)
3748                 safe_free(driver_info_3[i].dependentfiles);
3749         
3750         safe_free(driver_info_3);
3751         
3752         if (*needed > offered) {
3753                 *returned=0;
3754                 return ERROR_INSUFFICIENT_BUFFER;
3755         }
3756         else
3757                 return NT_STATUS_NO_PROBLEMO;
3758 }
3759
3760 /****************************************************************************
3761  Enumerates all printer drivers.
3762 ****************************************************************************/
3763 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
3764                                     NEW_BUFFER *buffer, uint32 offered,
3765                                     uint32 *needed, uint32 *returned)
3766 {
3767         int i;
3768         fstring *list = NULL;
3769         fstring servername;
3770         fstring architecture;
3771
3772         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
3773         fstrcpy(servername, global_myname);
3774         *needed=0;
3775         *returned=0;
3776
3777         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
3778
3779         switch (level) {
3780         case 1:
3781                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
3782                 break;
3783         case 2:
3784                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
3785                 break;
3786         case 3:
3787                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
3788                 break;
3789         default:
3790                 *returned=0;
3791                 safe_free(list);
3792                 return ERROR_INVALID_LEVEL;
3793                 break;
3794         }
3795 }
3796
3797 /****************************************************************************
3798 ****************************************************************************/
3799 static void fill_form_1(FORM_1 *form, nt_forms_struct *list, int position)
3800 {
3801         form->flag=list->flag;
3802         init_unistr(&form->name, list->name);
3803         form->width=list->width;
3804         form->length=list->length;
3805         form->left=list->left;
3806         form->top=list->top;
3807         form->right=list->right;
3808         form->bottom=list->bottom;      
3809 }
3810         
3811 /****************************************************************************
3812 ****************************************************************************/
3813 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level, 
3814                                NEW_BUFFER *buffer, uint32 offered, 
3815                                uint32 *needed, uint32 *numofforms)
3816 {
3817         nt_forms_struct *list=NULL;
3818         FORM_1 *forms_1;
3819         int buffer_size=0;
3820         int i;
3821
3822         DEBUG(4,("_new_spoolss_enumforms\n"));
3823         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
3824         DEBUGADD(5,("Info level [%d]\n",          level));
3825
3826         *numofforms = get_ntforms(&list);
3827         DEBUGADD(5,("Number of forms [%d]\n",     *numofforms));
3828
3829         if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
3830
3831         switch (level) {
3832         case 1:
3833                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
3834                         *numofforms=0;
3835                         return ERROR_NOT_ENOUGH_MEMORY;
3836                 }
3837
3838                 /* construct the list of form structures */
3839                 for (i=0; i<*numofforms; i++) {
3840                         DEBUGADD(6,("Filling form number [%d]\n",i));
3841                         fill_form_1(&forms_1[i], &list[i], i);
3842                 }
3843                 
3844                 safe_free(list);
3845
3846                 /* check the required size. */
3847                 for (i=0; i<*numofforms; i++) {
3848                         DEBUGADD(6,("adding form [%d]'s size\n",i));
3849                         buffer_size += spoolss_size_form_1(&forms_1[i]);
3850                 }
3851
3852                 *needed=buffer_size;            
3853                 
3854                 if (!alloc_buffer_size(buffer, buffer_size)){
3855                         safe_free(forms_1);
3856                         return ERROR_INSUFFICIENT_BUFFER;
3857                 }
3858
3859                 /* fill the buffer with the form structures */
3860                 for (i=0; i<*numofforms; i++) {
3861                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
3862                         new_smb_io_form_1("", buffer, &forms_1[i], 0);
3863                 }
3864
3865                 safe_free(forms_1);
3866
3867                 if (*needed > offered) {
3868                         *numofforms=0;
3869                         return ERROR_INSUFFICIENT_BUFFER;
3870                 }
3871                 else
3872                         return NT_STATUS_NO_PROBLEMO;
3873                         
3874         default:
3875                 safe_free(list);
3876                 return ERROR_INVALID_LEVEL;
3877         }
3878
3879 }
3880
3881 /****************************************************************************
3882 ****************************************************************************/
3883 static void fill_port_1(PORT_INFO_1 *port, char *name)
3884 {
3885         init_unistr(&port->port_name, name);
3886 }
3887
3888 /****************************************************************************
3889 ****************************************************************************/
3890 static void fill_port_2(PORT_INFO_2 *port, char *name)
3891 {
3892         init_unistr(&port->port_name, name);
3893         init_unistr(&port->monitor_name, "Local Monitor");
3894         init_unistr(&port->description, "Local Port");
3895 #define PORT_TYPE_WRITE 1
3896         port->port_type=PORT_TYPE_WRITE;
3897         port->reserved=0x0;     
3898 }
3899
3900 /****************************************************************************
3901  enumports level 1.
3902 ****************************************************************************/
3903 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3904 {
3905         int n_services=lp_numservices();
3906         int snum;
3907         int i=0;
3908         
3909         PORT_INFO_1 *ports=NULL;
3910
3911         for (snum=0; snum<n_services; snum++)
3912                 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3913                         (*returned)++;
3914
3915         if((ports=(PORT_INFO_1 *)malloc( (*returned+1) * sizeof(PORT_INFO_1) )) == NULL)
3916                 return ERROR_NOT_ENOUGH_MEMORY;
3917         
3918         for (snum=0; snum<n_services; snum++) {
3919                 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3920                         /*
3921                          * Ensure this port name is unique.
3922                          */
3923                         int j;
3924
3925                         DEBUG(10,("enumports_level_1: port name %s\n", PRINTERNAME(snum)));
3926
3927                         for(j = 0; j < i; j++) {
3928                                 fstring port_name;
3929                                 unistr_to_dos(port_name, (const char *)&ports[j].port_name.buffer[0], sizeof(port_name));
3930
3931                                 if (strequal(port_name, PRINTERNAME(snum)))
3932                                         break;
3933                         }
3934
3935                         if (j < i)
3936                                 continue;
3937
3938                         DEBUGADD(6,("Filling port number [%d]\n", i));
3939                         fill_port_1(&ports[i], PRINTERNAME(snum));
3940                         i++;
3941                 }
3942         }
3943
3944         *returned = i;
3945
3946         /* check the required size. */
3947         for (i=0; i<*returned; i++) {
3948                 DEBUGADD(6,("adding port [%d]'s size\n", i));
3949                 *needed += spoolss_size_port_info_1(&ports[i]);
3950         }
3951                 
3952         if (!alloc_buffer_size(buffer, *needed)) {
3953                 safe_free(ports);
3954                 return ERROR_INSUFFICIENT_BUFFER;
3955         }
3956
3957         /* fill the buffer with the ports structures */
3958         for (i=0; i<*returned; i++) {
3959                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
3960                 new_smb_io_port_1("", buffer, &ports[i], 0);
3961         }
3962
3963         safe_free(ports);
3964
3965         if (*needed > offered) {
3966                 *returned=0;
3967                 return ERROR_INSUFFICIENT_BUFFER;
3968         }
3969         else
3970                 return NT_STATUS_NO_PROBLEMO;
3971 }
3972
3973 /****************************************************************************
3974  enumports level 2.
3975 ****************************************************************************/
3976
3977 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3978 {
3979         int n_services=lp_numservices();
3980         int snum;
3981         int i=0;
3982         
3983         PORT_INFO_2 *ports=NULL;
3984
3985         for (snum=0; snum<n_services; snum++)
3986                 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3987                         (*returned)++;
3988
3989         if((ports=(PORT_INFO_2 *)malloc( (*returned+1) * sizeof(PORT_INFO_2) )) == NULL)
3990                 return ERROR_NOT_ENOUGH_MEMORY;
3991         
3992         for (snum=0; snum<n_services; snum++) {
3993                 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3994                         /*
3995                          * Ensure this port name is unique.
3996                          */
3997                         int j;
3998
3999                         DEBUG(10,("enumports_level_2: port name %s\n", PRINTERNAME(snum)));
4000
4001                         for(j = 0; j < i; j++) {
4002                                 fstring port_name;
4003                                 unistr_to_dos(port_name, (const char *)&ports[j].port_name.buffer[0], sizeof(port_name));
4004
4005                                 if (strequal(port_name, PRINTERNAME(snum)))
4006                                         break;
4007                         }
4008
4009                         if (j < i)
4010                                 continue;
4011
4012                         DEBUGADD(6,("Filling port number [%d]\n", i));
4013                         fill_port_2(&ports[i], PRINTERNAME(snum));
4014                         i++;
4015                 }
4016         }
4017
4018         *returned = i;
4019
4020         /* check the required size. */
4021         for (i=0; i<*returned; i++) {
4022                 DEBUGADD(6,("adding port [%d]'s size\n", i));
4023                 *needed += spoolss_size_port_info_2(&ports[i]);
4024         }
4025                 
4026         if (!alloc_buffer_size(buffer, *needed)) {
4027                 safe_free(ports);
4028                 return ERROR_INSUFFICIENT_BUFFER;
4029         }
4030
4031         /* fill the buffer with the ports structures */
4032         for (i=0; i<*returned; i++) {
4033                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4034                 new_smb_io_port_2("", buffer, &ports[i], 0);
4035         }
4036
4037         safe_free(ports);
4038
4039         if (*needed > offered) {
4040                 *returned=0;
4041                 return ERROR_INSUFFICIENT_BUFFER;
4042         }
4043         else
4044                 return NT_STATUS_NO_PROBLEMO;
4045 }
4046
4047 /****************************************************************************
4048  enumports.
4049 ****************************************************************************/
4050 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level, 
4051                            NEW_BUFFER *buffer, uint32 offered, 
4052                            uint32 *needed, uint32 *returned)
4053 {
4054         DEBUG(4,("_spoolss_enumports\n"));
4055         
4056         *returned=0;
4057         *needed=0;
4058         
4059         switch (level) {
4060         case 1:
4061                 return enumports_level_1(buffer, offered, needed, returned);
4062                 break;
4063         case 2:
4064                 return enumports_level_2(buffer, offered, needed, returned);
4065                 break;
4066         default:
4067                 return ERROR_INVALID_LEVEL;
4068                 break;
4069         }
4070 }
4071
4072 /****************************************************************************
4073 ****************************************************************************/
4074 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4075                                 const SPOOL_PRINTER_INFO_LEVEL *info,
4076                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4077                                 uint32 user_switch, const SPOOL_USER_CTR *user,
4078                                 POLICY_HND *handle)
4079 {
4080         NT_PRINTER_INFO_LEVEL *printer = NULL;
4081         fstring name;
4082         fstring share_name;
4083         int snum;
4084
4085         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4086                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4087                 return ERROR_NOT_ENOUGH_MEMORY;
4088         }
4089
4090         ZERO_STRUCTP(printer);
4091
4092         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4093         convert_printer_info(info, printer, 2);
4094
4095         unistr2_to_ascii(share_name, &info->info_2->sharename, sizeof(share_name)-1);
4096         
4097         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname, share_name);
4098
4099         if ((snum = print_queue_snum(share_name)) == -1) {
4100                 free_a_printer(&printer,2);
4101                 return ERROR_ACCESS_DENIED;
4102         }
4103         
4104         /*
4105          * Do sanity check on the requested changes for Samba.
4106          */
4107
4108         if (!check_printer_ok(printer->info_2, snum)) {
4109                 free_a_printer(&printer,2);
4110                 return ERROR_ACCESS_DENIED;
4111         }
4112
4113         /* write the ASCII on disk */
4114         if (add_a_printer(*printer, 2) != 0) {
4115                 free_a_printer(&printer,2);
4116                 return ERROR_ACCESS_DENIED;
4117         }
4118
4119         if (!open_printer_hnd(handle, name)) {
4120                 /* Handle open failed - remove addition. */
4121                 del_a_printer(share_name);
4122                 free_a_printer(&printer,2);
4123                 return ERROR_ACCESS_DENIED;
4124         }
4125
4126         free_a_printer(&printer,2);
4127         return NT_STATUS_NO_PROBLEMO;
4128 }
4129
4130 /****************************************************************************
4131 ****************************************************************************/
4132 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4133                                 const SPOOL_PRINTER_INFO_LEVEL *info,
4134                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4135                                 uint32 user_switch, const SPOOL_USER_CTR *user,
4136                                 POLICY_HND *handle)
4137 {
4138         switch (level) {
4139                 case 1:
4140                         /* we don't handle yet */
4141                         /* but I know what to do ... */
4142                         return ERROR_INVALID_LEVEL;
4143                         break;
4144                 case 2:
4145                         return spoolss_addprinterex_level_2(uni_srv_name, info, 
4146                                                             unk0, unk1, unk2, unk3,
4147                                                             user_switch, user, handle);
4148                         break;
4149                 default:
4150                         return ERROR_INVALID_LEVEL;
4151                         break;
4152         }
4153 }
4154
4155 /****************************************************************************
4156 ****************************************************************************/
4157 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4158                                  uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4159 {
4160         uint32 err = NT_STATUS_NO_PROBLEMO;
4161         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4162         struct current_user user;
4163         
4164         ZERO_STRUCT(driver);
4165         
4166         if (p->ntlmssp_auth_validated) {
4167                 memcpy(&user, &p->pipe_user, sizeof(user));
4168         } else {
4169                 extern struct current_user current_user;
4170                 memcpy(&user, &current_user, sizeof(user));
4171         }
4172         
4173         convert_printer_driver_info(info, &driver, level);
4174
4175         DEBUG(5,("Cleaning driver's information\n"));
4176         clean_up_driver_struct(driver, level);
4177
4178         DEBUG(5,("Moving driver to final destination\n"));
4179         move_driver_to_download_area(driver, level, &user);
4180
4181         if (add_a_printer_driver(driver, level)!=0)
4182                 return ERROR_ACCESS_DENIED;
4183
4184         free_a_printer_driver(driver, level);
4185
4186         return err;
4187 }
4188
4189 /****************************************************************************
4190 ****************************************************************************/
4191 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4192 {
4193         init_unistr(&(info->name), name);
4194 }
4195
4196 /****************************************************************************
4197 ****************************************************************************/
4198 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4199 {
4200         pstring path;
4201         pstring long_archi;
4202         pstring short_archi;
4203         DRIVER_DIRECTORY_1 *info=NULL;
4204
4205         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4206
4207         if (get_short_archi(short_archi, long_archi)==FALSE)
4208                 return ERROR_INVALID_ENVIRONMENT;
4209
4210         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4211                 return ERROR_NOT_ENOUGH_MEMORY;
4212
4213         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4214
4215         DEBUG(4,("printer driver directory: [%s]\n", path));
4216
4217         fill_driverdir_1(info, path);
4218         
4219         *needed += spoolss_size_driverdir_info_1(info);
4220
4221         if (!alloc_buffer_size(buffer, *needed)) {
4222                 safe_free(info);
4223                 return ERROR_INSUFFICIENT_BUFFER;
4224         }
4225
4226         new_smb_io_driverdir_1("", buffer, info, 0);
4227
4228         safe_free(info);
4229         
4230         if (*needed > offered)
4231                 return ERROR_INSUFFICIENT_BUFFER;
4232         else
4233                 return NT_STATUS_NO_PROBLEMO;
4234 }
4235
4236 /****************************************************************************
4237 ****************************************************************************/
4238 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4239                                         NEW_BUFFER *buffer, uint32 offered, 
4240                                         uint32 *needed)
4241 {
4242         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4243
4244         *needed=0;
4245
4246         switch(level) {
4247         case 1:
4248                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4249                 break;
4250         default:
4251                 return ERROR_INVALID_LEVEL;
4252                 break;
4253         }
4254 }
4255         
4256 /****************************************************************************
4257 ****************************************************************************/
4258 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4259                                 uint32 in_value_len, uint32 in_data_len,
4260                                 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4261                                 uint32 *out_type,
4262                                 uint32 *out_max_data_len, uint8  **data_out, uint32 *out_data_len)
4263 {
4264         NT_PRINTER_INFO_LEVEL *printer = NULL;
4265         
4266         fstring value;
4267         
4268         uint32 param_index;
4269         uint32 biggest_valuesize;
4270         uint32 biggest_datasize;
4271         uint32 data_len;
4272         Printer_entry *Printer = find_printer_index_by_hnd(handle);
4273         int snum;
4274         uint8 *data=NULL;
4275         uint32 type;
4276
4277         ZERO_STRUCT(printer);
4278         
4279         *out_max_value_len=0;
4280         *out_value=NULL;
4281         *out_value_len=0;
4282
4283         *out_type=0;
4284
4285         *out_max_data_len=0;
4286         *data_out=NULL;
4287         *out_data_len=0;
4288
4289         DEBUG(5,("spoolss_enumprinterdata\n"));
4290
4291         if (!OPEN_HANDLE(Printer)) {
4292                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4293                 return ERROR_INVALID_HANDLE;
4294         }
4295
4296         if (!get_printer_snum(handle, &snum))
4297                 return ERROR_INVALID_HANDLE;
4298         
4299         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
4300                 return ERROR_INVALID_HANDLE;
4301
4302         /* 
4303          * The NT machine wants to know the biggest size of value and data
4304          *
4305          * cf: MSDN EnumPrinterData remark section
4306          */
4307         if ( (in_value_len==0) && (in_data_len==0) ) {
4308                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
4309                 
4310                 param_index=0;
4311                 biggest_valuesize=0;
4312                 biggest_datasize=0;
4313                 
4314                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
4315                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
4316                         if (data_len > biggest_datasize) biggest_datasize=data_len;
4317
4318                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
4319
4320                         safe_free(data);
4321                         param_index++;
4322                 }
4323
4324                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
4325                 *out_value_len=2*(1+biggest_valuesize);
4326                 *out_data_len=biggest_datasize;
4327
4328                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
4329
4330                 free_a_printer(&printer, 2);
4331                 return NT_STATUS_NO_PROBLEMO;
4332         }
4333         
4334         /* 
4335          * the value len is wrong in NT sp3
4336          * that's the number of bytes not the number of unicode chars
4337          */
4338
4339         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4340                 safe_free(data);
4341                 free_a_printer(&printer, 2);
4342                 return ERROR_NO_MORE_ITEMS;
4343         }
4344
4345         free_a_printer(&printer, 2);
4346
4347         /* 
4348          * the value is:
4349          * - counted in bytes in the request
4350          * - counted in UNICODE chars in the max reply
4351          * - counted in bytes in the real size
4352          *
4353          * take a pause *before* coding not *during* coding
4354          */
4355          
4356         *out_max_value_len=(in_value_len/sizeof(uint16));
4357         if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
4358                 safe_free(data);
4359                 return ERROR_NOT_ENOUGH_MEMORY;
4360         }
4361         
4362         ZERO_STRUCTP(*out_value);
4363         *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
4364
4365         *out_type=type;
4366
4367         /* the data is counted in bytes */
4368         *out_max_data_len=in_data_len;
4369         if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
4370                 safe_free(data);
4371                 return ERROR_NOT_ENOUGH_MEMORY;
4372         }
4373         
4374         ZERO_STRUCTP(*data_out);
4375         memcpy(*data_out, data, (size_t)data_len);
4376         *out_data_len=data_len;
4377
4378         safe_free(data);
4379         
4380         return NT_STATUS_NO_PROBLEMO;
4381 }
4382
4383 /****************************************************************************
4384 ****************************************************************************/
4385 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
4386                                 const UNISTR2 *value,
4387                                 uint32 type,
4388                                 uint32 max_len,
4389                                 const uint8 *data,
4390                                 uint32 real_len,
4391                                 uint32 numeric_data)
4392 {
4393         NT_PRINTER_INFO_LEVEL *printer = NULL;
4394         NT_PRINTER_PARAM *param = NULL;
4395                 
4396         int snum=0;
4397         uint32 status = 0x0;
4398         Printer_entry *Printer=find_printer_index_by_hnd(handle);
4399         
4400         DEBUG(5,("spoolss_setprinterdata\n"));
4401
4402         
4403         if (!OPEN_HANDLE(Printer)) {
4404                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4405                 return ERROR_INVALID_HANDLE;
4406         }
4407
4408         if (!get_printer_snum(handle, &snum))
4409                 return ERROR_INVALID_HANDLE;
4410
4411         status = get_a_printer(&printer, 2, lp_servicename(snum));
4412         if (status != 0x0)
4413                 return ERROR_INVALID_NAME;
4414
4415         convert_specific_param(&param, value , type, data, real_len);
4416         unlink_specific_param_if_exist(printer->info_2, param);
4417         
4418         if (!add_a_specific_param(printer->info_2, param))
4419                 status = ERROR_INVALID_PARAMETER;
4420         else
4421                 status = add_a_printer(*printer, 2);
4422
4423         free_a_printer(&printer, 2);
4424         return status;
4425 }
4426
4427 /****************************************************************************
4428 ****************************************************************************/
4429 uint32 _spoolss_addform( POLICY_HND *handle,
4430                                 uint32 level,
4431                                 const FORM *form)
4432 {
4433         int count=0;
4434         nt_forms_struct *list=NULL;
4435         Printer_entry *Printer = find_printer_index_by_hnd(handle);
4436
4437         DEBUG(5,("spoolss_addform\n"));
4438
4439         if (!OPEN_HANDLE(Printer)) {
4440                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4441                 return ERROR_INVALID_HANDLE;
4442         }
4443
4444         count=get_ntforms(&list);
4445         if(!add_a_form(&list, form, &count))
4446                 return ERROR_NOT_ENOUGH_MEMORY;
4447         write_ntforms(&list, count);
4448
4449         safe_free(list);
4450
4451         return 0x0;
4452 }
4453
4454 /****************************************************************************
4455 ****************************************************************************/
4456 uint32 _spoolss_setform( POLICY_HND *handle,
4457                                 const UNISTR2 *uni_name,
4458                                 uint32 level,
4459                                 const FORM *form)
4460 {
4461         int count=0;
4462         nt_forms_struct *list=NULL;
4463         Printer_entry *Printer = find_printer_index_by_hnd(handle);
4464
4465         DEBUG(5,("spoolss_setform\n"));
4466
4467         if (!OPEN_HANDLE(Printer)) {
4468                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4469                 return ERROR_INVALID_HANDLE;
4470         }
4471         count=get_ntforms(&list);
4472         update_a_form(&list, form, count);
4473         write_ntforms(&list, count);
4474
4475         safe_free(list);
4476
4477         return 0x0;
4478 }
4479
4480 /****************************************************************************
4481  enumprintprocessors level 1.
4482 ****************************************************************************/
4483 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4484 {
4485         PRINTPROCESSOR_1 *info_1=NULL;
4486         
4487         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
4488                 return ERROR_NOT_ENOUGH_MEMORY;
4489
4490         (*returned) = 0x1;
4491         
4492         init_unistr(&(info_1->name), "winprint");
4493
4494         *needed += spoolss_size_printprocessor_info_1(info_1);
4495
4496         if (!alloc_buffer_size(buffer, *needed))
4497                 return ERROR_INSUFFICIENT_BUFFER;
4498
4499         smb_io_printprocessor_info_1("", buffer, info_1, 0);
4500
4501         safe_free(info_1);
4502
4503         if (*needed > offered) {
4504                 *returned=0;
4505                 return ERROR_INSUFFICIENT_BUFFER;
4506         }
4507         else
4508                 return NT_STATUS_NO_PROBLEMO;
4509 }
4510
4511 /****************************************************************************
4512 ****************************************************************************/
4513 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
4514                                     NEW_BUFFER *buffer, uint32 offered, 
4515                                     uint32 *needed, uint32 *returned)
4516 {
4517         DEBUG(5,("spoolss_enumprintprocessors\n"));
4518
4519         /* 
4520          * Enumerate the print processors ...
4521          *
4522          * Just reply with "winprint", to keep NT happy
4523          * and I can use my nice printer checker.
4524          */
4525         
4526         *returned=0;
4527         *needed=0;
4528         
4529         switch (level) {
4530         case 1:
4531                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
4532                 break;
4533         default:
4534                 return ERROR_INVALID_LEVEL;
4535                 break;
4536         }
4537 }
4538
4539 /****************************************************************************
4540  enumprintprocdatatypes level 1.
4541 ****************************************************************************/
4542 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4543 {
4544         PRINTPROCDATATYPE_1 *info_1=NULL;
4545         
4546         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
4547                 return ERROR_NOT_ENOUGH_MEMORY;
4548
4549         (*returned) = 0x1;
4550         
4551         init_unistr(&(info_1->name), "RAW");
4552
4553         *needed += spoolss_size_printprocdatatype_info_1(info_1);
4554
4555         if (!alloc_buffer_size(buffer, *needed))
4556                 return ERROR_INSUFFICIENT_BUFFER;
4557
4558         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
4559
4560         safe_free(info_1);
4561
4562         if (*needed > offered) {
4563                 *returned=0;
4564                 return ERROR_INSUFFICIENT_BUFFER;
4565         }
4566         else
4567                 return NT_STATUS_NO_PROBLEMO;
4568 }
4569
4570 /****************************************************************************
4571 ****************************************************************************/
4572 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
4573                                         NEW_BUFFER *buffer, uint32 offered, 
4574                                         uint32 *needed, uint32 *returned)
4575 {
4576         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
4577         
4578         *returned=0;
4579         *needed=0;
4580         
4581         switch (level) {
4582         case 1:
4583                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
4584                 break;
4585         default:
4586                 return ERROR_INVALID_LEVEL;
4587                 break;
4588         }
4589 }
4590
4591 /****************************************************************************
4592  enumprintmonitors level 1.
4593 ****************************************************************************/
4594 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4595 {
4596         PRINTMONITOR_1 *info_1=NULL;
4597         
4598         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
4599                 return ERROR_NOT_ENOUGH_MEMORY;
4600
4601         (*returned) = 0x1;
4602         
4603         init_unistr(&(info_1->name), "Local Port");
4604
4605         *needed += spoolss_size_printmonitor_info_1(info_1);
4606
4607         if (!alloc_buffer_size(buffer, *needed))
4608                 return ERROR_INSUFFICIENT_BUFFER;
4609
4610         smb_io_printmonitor_info_1("", buffer, info_1, 0);
4611
4612         safe_free(info_1);
4613
4614         if (*needed > offered) {
4615                 *returned=0;
4616                 return ERROR_INSUFFICIENT_BUFFER;
4617         }
4618         else
4619                 return NT_STATUS_NO_PROBLEMO;
4620 }
4621
4622 /****************************************************************************
4623  enumprintmonitors level 2.
4624 ****************************************************************************/
4625 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4626 {
4627         PRINTMONITOR_2 *info_2=NULL;
4628         
4629         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
4630                 return ERROR_NOT_ENOUGH_MEMORY;
4631
4632         (*returned) = 0x1;
4633         
4634         init_unistr(&(info_2->name), "Local Port");
4635         init_unistr(&(info_2->environment), "Windows NT X86");
4636         init_unistr(&(info_2->dll_name), "localmon.dll");
4637
4638         *needed += spoolss_size_printmonitor_info_2(info_2);
4639
4640         if (!alloc_buffer_size(buffer, *needed))
4641                 return ERROR_INSUFFICIENT_BUFFER;
4642
4643         smb_io_printmonitor_info_2("", buffer, info_2, 0);
4644
4645         safe_free(info_2);
4646
4647         if (*needed > offered) {
4648                 *returned=0;
4649                 return ERROR_INSUFFICIENT_BUFFER;
4650         }
4651         else
4652                 return NT_STATUS_NO_PROBLEMO;
4653 }
4654
4655 /****************************************************************************
4656 ****************************************************************************/
4657 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
4658                                     NEW_BUFFER *buffer, uint32 offered, 
4659                                     uint32 *needed, uint32 *returned)
4660 {
4661         DEBUG(5,("spoolss_enumprintmonitors\n"));
4662
4663         /* 
4664          * Enumerate the print monitors ...
4665          *
4666          * Just reply with "Local Port", to keep NT happy
4667          * and I can use my nice printer checker.
4668          */
4669         
4670         *returned=0;
4671         *needed=0;
4672         
4673         switch (level) {
4674         case 1:
4675                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
4676                 break;          
4677         case 2:
4678                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
4679                 break;
4680         default:
4681                 return ERROR_INVALID_LEVEL;
4682                 break;
4683         }
4684 }
4685
4686 /****************************************************************************
4687 ****************************************************************************/
4688 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4689 {
4690         int i=0;
4691         BOOL found=False;
4692         JOB_INFO_1 *info_1=NULL;
4693
4694         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
4695
4696         if (info_1 == NULL) {
4697                 safe_free(queue);
4698                 return ERROR_NOT_ENOUGH_MEMORY;
4699         }
4700                 
4701         for (i=0; i<count && found==False; i++) {
4702                 if (queue[i].job==(int)jobid)
4703                         found=True;
4704         }
4705         
4706         if (found==False) {
4707                 safe_free(queue);
4708                 safe_free(info_1);
4709                 /* I shoud reply something else ... I can't find the good one */
4710                 return NT_STATUS_NO_PROBLEMO;
4711         }
4712         
4713         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
4714         
4715         safe_free(queue);
4716         
4717         *needed += spoolss_size_job_info_1(info_1);
4718
4719         if (!alloc_buffer_size(buffer, *needed)) {
4720                 safe_free(info_1);
4721                 return ERROR_INSUFFICIENT_BUFFER;
4722         }
4723
4724         new_smb_io_job_info_1("", buffer, info_1, 0);
4725
4726         safe_free(info_1);
4727
4728         if (*needed > offered)
4729                 return ERROR_INSUFFICIENT_BUFFER;
4730         else
4731                 return NT_STATUS_NO_PROBLEMO;
4732 }
4733
4734
4735 /****************************************************************************
4736 ****************************************************************************/
4737 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4738 {
4739         int i=0;
4740         BOOL found=False;
4741         JOB_INFO_2 *info_2;
4742         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
4743
4744         ZERO_STRUCTP(info_2);
4745
4746         if (info_2 == NULL) {
4747                 safe_free(queue);
4748                 return ERROR_NOT_ENOUGH_MEMORY;
4749         }
4750
4751         for (i=0; i<count && found==False; i++) {
4752                 if (queue[i].job==(int)jobid)
4753                         found=True;
4754         }
4755         
4756         if (found==False) {
4757                 safe_free(queue);
4758                 safe_free(info_2);
4759                 /* I shoud reply something else ... I can't find the good one */
4760                 return NT_STATUS_NO_PROBLEMO;
4761         }
4762         
4763         fill_job_info_2(info_2, &(queue[i-1]), i, snum);
4764         
4765         safe_free(queue);
4766         
4767         *needed += spoolss_size_job_info_2(info_2);
4768
4769         if (!alloc_buffer_size(buffer, *needed)) {
4770                 safe_free(info_2);
4771                 return ERROR_INSUFFICIENT_BUFFER;
4772         }
4773
4774         new_smb_io_job_info_2("", buffer, info_2, 0);
4775
4776         free_dev_mode(info_2->devmode);
4777         safe_free(info_2);
4778
4779         if (*needed > offered)
4780                 return ERROR_INSUFFICIENT_BUFFER;
4781         else
4782                 return NT_STATUS_NO_PROBLEMO;
4783 }
4784
4785 /****************************************************************************
4786 ****************************************************************************/
4787 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
4788                         NEW_BUFFER *buffer, uint32 offered, 
4789                         uint32 *needed)
4790 {
4791         int snum;
4792         int count;
4793         print_queue_struct *queue=NULL;
4794         print_status_struct prt_status;
4795
4796         DEBUG(5,("spoolss_getjob\n"));
4797         
4798         memset(&prt_status, 0, sizeof(prt_status));
4799
4800         *needed=0;
4801         
4802         if (!get_printer_snum(handle, &snum))
4803                 return ERROR_INVALID_HANDLE;
4804         
4805         count = print_queue_status(snum, &queue, &prt_status);
4806         
4807         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
4808                      count, prt_status.status, prt_status.message));
4809                 
4810         switch (level) {
4811         case 1:
4812                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
4813                 break;
4814         case 2:
4815                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
4816                 break;
4817         default:
4818                 safe_free(queue);
4819                 return ERROR_INVALID_LEVEL;
4820                 break;
4821         }
4822 }
4823 #undef OLD_NTDOMAIN