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