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