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