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