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