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