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