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