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