Merge of comment repair.
[sfrench/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 username
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 job status
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 job name
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 job status
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 job time
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 job size
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 job position
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 /*******************************************************************
1385  * fill a notify_info_data with submitted time
1386  ********************************************************************/
1387 static void spoolss_notify_submitted_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1388 {
1389         struct tm *t;
1390
1391         t=gmtime(&queue->time);
1392
1393         data->notify_data.data.length = sizeof(SYSTEMTIME);
1394         make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1395 }
1396
1397 #define END 65535
1398
1399 struct s_notify_info_data_table
1400 {
1401         uint16 type;
1402         uint16 field;
1403         char *name;
1404         uint32 size;
1405         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1406                     print_queue_struct *queue,
1407                     NT_PRINTER_INFO_LEVEL *printer);
1408 };
1409
1410 struct s_notify_info_data_table notify_info_data_table[] =
1411 {
1412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         POINTER,   spoolss_notify_server_name },
1413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        POINTER,   spoolss_notify_printer_name },
1414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          POINTER,   spoolss_notify_share_name },
1415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           POINTER,   spoolss_notify_port_name },
1416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         POINTER,   spoolss_notify_driver_name },
1417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             POINTER,   spoolss_notify_comment },
1418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            POINTER,   spoolss_notify_location },
1419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             POINTER,   spoolss_notify_devmode },
1420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             POINTER,   spoolss_notify_sepfile },
1421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     POINTER,   spoolss_notify_print_processor },
1422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          POINTER,   spoolss_notify_parameters },
1423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            POINTER,   spoolss_notify_datatype },
1424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER,   spoolss_notify_security_desc },
1425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          ONE_VALUE, spoolss_notify_attributes },
1426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            ONE_VALUE, spoolss_notify_priority },
1427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    ONE_VALUE, spoolss_notify_default_priority },
1428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          ONE_VALUE, spoolss_notify_start_time },
1429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          ONE_VALUE, spoolss_notify_until_time },
1430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              ONE_VALUE, spoolss_notify_status },
1431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       POINTER,   NULL },
1432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               ONE_VALUE, spoolss_notify_cjobs },
1433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         ONE_VALUE, spoolss_notify_average_ppm },
1434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         POINTER,   NULL },
1435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       POINTER,   NULL },
1436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         POINTER,   NULL },
1437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       POINTER,   NULL },
1438 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            POINTER,   spoolss_notify_printer_name },
1439 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            POINTER,   spoolss_notify_server_name },
1440 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               POINTER,   spoolss_notify_port_name },
1441 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               POINTER,   spoolss_notify_username },
1442 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             POINTER,   spoolss_notify_username },
1443 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                POINTER,   spoolss_notify_datatype },
1444 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         POINTER,   spoolss_notify_print_processor },
1445 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              POINTER,   spoolss_notify_parameters },
1446 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             POINTER,   spoolss_notify_driver_name },
1447 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 POINTER,   spoolss_notify_devmode },
1448 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  ONE_VALUE, spoolss_notify_job_status },
1449 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           POINTER,   spoolss_notify_job_status_string },
1450 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     POINTER,   NULL },
1451 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                POINTER,   spoolss_notify_job_name },
1452 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                ONE_VALUE, spoolss_notify_priority },
1453 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                ONE_VALUE, spoolss_notify_job_position },
1454 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               POINTER,   spoolss_notify_submitted_time },
1455 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              ONE_VALUE, spoolss_notify_start_time },
1456 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              ONE_VALUE, spoolss_notify_until_time },
1457 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    ONE_VALUE, spoolss_notify_job_time },
1458 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             ONE_VALUE, NULL },
1459 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           ONE_VALUE, NULL },
1460 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             ONE_VALUE, spoolss_notify_job_size },
1461 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_BYTES_PRINTED,           "JOB_NOTIFY_BYTES_PRINTED",           ONE_VALUE, NULL },
1462 { END,                 END,                                "",                                   END,       NULL }
1463 };
1464
1465 /*******************************************************************
1466 return the size of info_data structure
1467 ********************************************************************/  
1468 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1469 {
1470         int i=0;
1471
1472         while (notify_info_data_table[i].type != END)
1473         {
1474                 if ( (notify_info_data_table[i].type == type ) &&
1475                      (notify_info_data_table[i].field == field ) )
1476                 {
1477                         return (notify_info_data_table[i].size);
1478                 }
1479                 i++;
1480         }
1481         return (65535);
1482 }
1483
1484 /*******************************************************************
1485 return the type of notify_info_data
1486 ********************************************************************/  
1487 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1488 {
1489         int i=0;
1490
1491         while (notify_info_data_table[i].type != END)
1492         {
1493                 if ( (notify_info_data_table[i].type == type ) &&
1494                      (notify_info_data_table[i].field == field ) )
1495                 {
1496                         if (notify_info_data_table[i].size == POINTER)
1497                         {
1498                                 return (False);
1499                         }
1500                         else
1501                         {
1502                                 return (True);
1503                         }
1504                 }
1505                 i++;
1506         }
1507         return (False);
1508 }
1509
1510 /****************************************************************************
1511 ****************************************************************************/
1512 static int search_notify(uint16 type, uint16 field, int *value)
1513 {       
1514         int j;
1515         BOOL found;
1516
1517         for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1518         {
1519                 if ( (notify_info_data_table[j].type  == type  ) &&
1520                      (notify_info_data_table[j].field == field ) )
1521                         found=True;
1522         }
1523         *value=--j;
1524
1525         if ( found && (notify_info_data_table[j].fn != NULL) )
1526                 return True;
1527         else
1528                 return False;   
1529 }
1530
1531 /****************************************************************************
1532 ****************************************************************************/
1533 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1534 {
1535         info_data->type     = type;
1536         info_data->field    = field;
1537         info_data->reserved = 0;
1538         info_data->id       = id;
1539         info_data->size     = size_of_notify_info_data(type, field);
1540         info_data->enc_type = type_of_notify_info_data(type, field);
1541 }
1542
1543
1544 /*******************************************************************
1545  *
1546  * fill a notify_info struct with info asked
1547  * 
1548  ********************************************************************/
1549 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1550 {
1551         int field_num,j;
1552         uint16 type;
1553         uint16 field;
1554
1555         SPOOL_NOTIFY_INFO_DATA *current_data;
1556         NT_PRINTER_INFO_LEVEL *printer = NULL;
1557         print_queue_struct *queue=NULL;
1558         
1559         DEBUG(4,("construct_notify_printer_info\n"));
1560         
1561         type=option_type->type;
1562
1563         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1564                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"), 
1565                 option_type->count, lp_servicename(snum)));
1566         
1567         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1568                 return False;
1569
1570         for(field_num=0; field_num<option_type->count; field_num++) {
1571                 field = option_type->fields[field_num];
1572                 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1573
1574                 if (!search_notify(type, field, &j) )
1575                         continue;
1576                 
1577                 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1578                         return False;
1579                 }
1580                 current_data=&info->data[info->count];
1581
1582                 construct_info_data(current_data, type, field, id);             
1583                 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1584
1585                 info->count++;
1586         }
1587
1588         free_a_printer(&printer, 2);
1589         return True;
1590 }
1591
1592 /*******************************************************************
1593  *
1594  * fill a notify_info struct with info asked
1595  * 
1596  ********************************************************************/
1597 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1598 {
1599         int field_num,j;
1600         uint16 type;
1601         uint16 field;
1602
1603         SPOOL_NOTIFY_INFO_DATA *current_data;
1604         NT_PRINTER_INFO_LEVEL *printer = NULL;
1605         
1606         DEBUG(4,("construct_notify_jobs_info\n"));
1607         
1608         type = option_type->type;
1609
1610         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1611                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"), 
1612                 option_type->count));
1613
1614         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1615                 return False;
1616         
1617         for(field_num=0; field_num<option_type->count; field_num++) {
1618                 field = option_type->fields[field_num];
1619
1620                 if (!search_notify(type, field, &j) )
1621                         continue;
1622
1623                 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1624                         return False;
1625                 }
1626
1627                 current_data=&(info->data[info->count]);
1628
1629                 construct_info_data(current_data, type, field, id);
1630                 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1631                 info->count++;
1632         }
1633
1634         free_a_printer(&printer, 2);    
1635         return True;
1636 }
1637
1638 /*
1639  * JFM: The enumeration is not that simple, it's even non obvious.
1640  *
1641  * let's take an example: I want to monitor the PRINTER SERVER for
1642  * the printer's name and the number of jobs currently queued.
1643  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1644  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1645  * 
1646  * I have 3 printers on the back of my server.
1647  *
1648  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1649  * structures.
1650  *   Number     Data                    Id
1651  *      1       printer 1 name          1
1652  *      2       printer 1 cjob          1
1653  *      3       printer 2 name          2
1654  *      4       printer 2 cjob          2
1655  *      5       printer 3 name          3
1656  *      6       printer 3 name          3
1657  *
1658  * that's the print server case, the printer case is even worse.
1659  */
1660
1661
1662
1663 /*******************************************************************
1664  *
1665  * enumerate all printers on the printserver
1666  * fill a notify_info struct with info asked
1667  * 
1668  ********************************************************************/
1669 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1670 {
1671         int snum;
1672         Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1673         int n_services=lp_numservices();
1674         int i;
1675         uint32 id;
1676         SPOOL_NOTIFY_OPTION *option;
1677         SPOOL_NOTIFY_OPTION_TYPE *option_type;
1678
1679         DEBUG(4,("printserver_notify_info\n"));
1680         
1681         option=Printer->notify.option;
1682         id=1;
1683         info->version=2;
1684         info->data=NULL;
1685         info->count=0;
1686
1687         for (i=0; i<option->count; i++) {
1688                 option_type=&(option->ctr.type[i]);
1689                 
1690                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1691                         continue;
1692                 
1693                 for (snum=0; snum<n_services; snum++)
1694                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1695                                 if (construct_notify_printer_info(info, snum, option_type, id))
1696                                         id++;
1697         }
1698                         
1699         /*
1700          * Debugging information, don't delete.
1701          */
1702         /* 
1703         DEBUG(1,("dumping the NOTIFY_INFO\n"));
1704         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1705         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1706         
1707         for (i=0; i<info->count; i++) {
1708                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1709                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1710                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1711         }
1712         */
1713         
1714         return NT_STATUS_NO_PROBLEMO;
1715 }
1716
1717 /*******************************************************************
1718  *
1719  * fill a notify_info struct with info asked
1720  * 
1721  ********************************************************************/
1722 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1723 {
1724         int snum;
1725         Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1726         int i;
1727         uint32 id;
1728         SPOOL_NOTIFY_OPTION *option;
1729         SPOOL_NOTIFY_OPTION_TYPE *option_type;
1730         int count,j;
1731         print_queue_struct *queue=NULL;
1732         print_status_struct status;
1733         
1734         DEBUG(4,("printer_notify_info\n"));
1735
1736         option=Printer->notify.option;
1737         id=0xffffffff;
1738         info->version=2;
1739         info->data=NULL;
1740         info->count=0;
1741
1742         get_printer_snum(hnd, &snum);
1743
1744         for (i=0; i<option->count; i++) {
1745                 option_type=&option->ctr.type[i];
1746                 
1747                 switch ( option_type->type ) {
1748                 case PRINTER_NOTIFY_TYPE:
1749                         if(construct_notify_printer_info(info, snum, option_type, id))
1750                                 id--;
1751                         break;
1752                         
1753                 case JOB_NOTIFY_TYPE:
1754                         memset(&status, 0, sizeof(status));     
1755                         count = print_queue_status(snum, &queue, &status);
1756                         for (j=0; j<count; j++)
1757                                 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1758                         safe_free(queue);
1759                         break;
1760                 }
1761         }
1762         
1763         /*
1764          * Debugging information, don't delete.
1765          */
1766         /* 
1767         DEBUG(1,("dumping the NOTIFY_INFO\n"));
1768         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1769         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1770         
1771         for (i=0; i<info->count; i++) {
1772                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1773                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1774                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1775         }
1776         */
1777         return NT_STATUS_NO_PROBLEMO;
1778 }
1779
1780 /********************************************************************
1781  * spoolss_rfnpcnex
1782  ********************************************************************/
1783 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1784                           SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1785 {
1786         Printer_entry *Printer=find_printer_index_by_hnd(handle);
1787
1788         if (!OPEN_HANDLE(Printer)) {
1789                 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1790                 return ERROR_INVALID_HANDLE;
1791         }
1792
1793         DEBUG(4,("Printer type %x\n",Printer->printer_type));
1794
1795         /* jfm: the change value isn't used right now.
1796          *      we will honour it when
1797          *      a) we'll be able to send notification to the client
1798          *      b) we'll have a way to communicate between the spoolss process.
1799          *
1800          *      same thing for option->flags
1801          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as 
1802          *      I don't have a global notification system, I'm sending back all the
1803          *      informations even when _NOTHING_ has changed.
1804          */
1805
1806         /* just discard the SPOOL_NOTIFY_OPTION */
1807         if (option!=NULL)
1808                 safe_free(option->ctr.type);
1809         
1810         switch (Printer->printer_type) {
1811                 case PRINTER_HANDLE_IS_PRINTSERVER:
1812                         return printserver_notify_info(handle, info);
1813                 case PRINTER_HANDLE_IS_PRINTER:
1814                         return printer_notify_info(handle, info);
1815         }
1816
1817         return ERROR_INVALID_HANDLE;
1818 }
1819
1820 /********************************************************************
1821  * construct_printer_info_0
1822  * fill a printer_info_1 struct
1823  ********************************************************************/
1824 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, fstring servername)
1825 {
1826         pstring chaine;
1827         int count;
1828         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1829         counter_printer_0 *session_counter;
1830         uint32 global_counter;
1831         struct tm *t;
1832         time_t setuptime;
1833
1834         print_queue_struct *queue=NULL;
1835         print_status_struct status;
1836         
1837         memset(&status, 0, sizeof(status));     
1838
1839         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1840                 return False;
1841
1842         count = print_queue_status(snum, &queue, &status);
1843
1844         /* check if we already have a counter for this printer */       
1845         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1846
1847         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1848                 if (session_counter->snum == snum)
1849                         break;
1850         }
1851
1852         /* it's the first time, add it to the list */
1853         if (session_counter==NULL) {
1854                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1855                         free_a_printer(&ntprinter, 2);
1856                         return False;
1857                 }
1858                 ZERO_STRUCTP(session_counter);
1859                 session_counter->snum=snum;
1860                 session_counter->counter=0;
1861                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1862         }
1863         
1864         /* increment it */
1865         session_counter->counter++;
1866         
1867         /* JFM:
1868          * the global_counter should be stored in a TDB as it's common to all the clients
1869          * and should be zeroed on samba startup
1870          */
1871         global_counter=session_counter->counter;
1872         
1873         /* the description and the name are of the form \\server\share */
1874         slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter->info_2->printername);
1875
1876         init_unistr(&printer->printername, chaine);
1877         
1878         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername);
1879         init_unistr(&printer->servername, chaine);
1880         
1881         printer->cjobs = count;
1882         printer->total_jobs = 0;
1883         printer->total_bytes = 0;
1884
1885         setuptime = (time_t)ntprinter->info_2->setuptime;
1886         t=gmtime(&setuptime);
1887
1888         printer->year = t->tm_year+1900;
1889         printer->month = t->tm_mon+1;
1890         printer->dayofweek = t->tm_wday;
1891         printer->day = t->tm_mday;
1892         printer->hour = t->tm_hour;
1893         printer->minute = t->tm_min;
1894         printer->second = t->tm_sec;
1895         printer->milliseconds = 0;
1896
1897         printer->global_counter = global_counter;
1898         printer->total_pages = 0;
1899         printer->major_version = 0x0004;        /* NT 4 */
1900         printer->build_version = 0x0565;        /* build 1381 */
1901         printer->unknown7 = 0x1;
1902         printer->unknown8 = 0x0;
1903         printer->unknown9 = 0x0;
1904         printer->session_counter = session_counter->counter;
1905         printer->unknown11 = 0x0;
1906         printer->printer_errors = 0x0;          /* number of print failure */
1907         printer->unknown13 = 0x0;
1908         printer->unknown14 = 0x1;
1909         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
1910         printer->unknown16 = 0x0;
1911         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1912         printer->unknown18 = 0x0;
1913         printer->status = nt_printq_status(status.status);
1914         printer->unknown20 = 0x0;
1915         printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1916         printer->unknown22 = 0x0;
1917         printer->unknown23 = 0x6;               /* 6  ???*/
1918         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
1919         printer->unknown25 = 0;
1920         printer->unknown26 = 0;
1921         printer->unknown27 = 0;
1922         printer->unknown28 = 0;
1923         printer->unknown29 = 0;
1924         
1925         safe_free(queue);
1926         free_a_printer(&ntprinter,2);
1927         return (True);  
1928 }
1929
1930 /********************************************************************
1931  * construct_printer_info_1
1932  * fill a printer_info_1 struct
1933  ********************************************************************/
1934 static BOOL construct_printer_info_1(fstring server, uint32 flags, PRINTER_INFO_1 *printer, int snum)
1935 {
1936         pstring chaine;
1937         pstring chaine2;
1938         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1939
1940         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1941                 return False;
1942
1943         printer->flags=flags;
1944
1945         if (*ntprinter->info_2->comment == '\0') {
1946                 init_unistr(&printer->comment, lp_comment(snum));
1947                 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1948                         ntprinter->info_2->drivername, lp_comment(snum));
1949         }
1950         else {
1951                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1952                 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1953                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
1954         }
1955                 
1956         snprintf(chaine2,sizeof(chaine)-1,"%s%s", server, ntprinter->info_2->printername);
1957
1958         init_unistr(&printer->description, chaine);
1959         init_unistr(&printer->name, chaine2);   
1960         
1961         free_a_printer(&ntprinter,2);
1962
1963         return True;
1964 }
1965
1966 /****************************************************************************
1967  Free a DEVMODE struct.
1968 ****************************************************************************/
1969
1970 static void free_dev_mode(DEVICEMODE *dev)
1971 {
1972         if (dev == NULL)
1973                 return;
1974
1975         if (dev->private)
1976                 safe_free(dev->private);
1977
1978         safe_free(dev); 
1979 }
1980
1981 /****************************************************************************
1982  Create a DEVMODE struct. Returns malloced memory.
1983 ****************************************************************************/
1984
1985 static DEVICEMODE *construct_dev_mode(int snum, char *servername)
1986 {
1987         char adevice[32];
1988         char aform[32];
1989         NT_PRINTER_INFO_LEVEL *printer = NULL;
1990         NT_DEVICEMODE *ntdevmode = NULL;
1991         DEVICEMODE *devmode = NULL;
1992
1993         DEBUG(7,("construct_dev_mode\n"));
1994         
1995         DEBUGADD(8,("getting printer characteristics\n"));
1996
1997         if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
1998                 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
1999                 return NULL;
2000         }
2001
2002         ZERO_STRUCTP(devmode);  
2003
2004         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2005                 goto fail;
2006
2007         if (printer->info_2->devmode)
2008                 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2009
2010         if (ntdevmode == NULL)
2011                 goto fail;
2012
2013         DEBUGADD(8,("loading DEVICEMODE\n"));
2014
2015         snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, printer->info_2->printername);
2016         init_unistr(&devmode->devicename, adevice);
2017
2018         snprintf(aform, sizeof(aform), ntdevmode->formname);
2019         init_unistr(&devmode->formname, aform);
2020
2021         devmode->specversion      = ntdevmode->specversion;
2022         devmode->driverversion    = ntdevmode->driverversion;
2023         devmode->size             = ntdevmode->size;
2024         devmode->driverextra      = ntdevmode->driverextra;
2025         devmode->fields           = ntdevmode->fields;
2026                                     
2027         devmode->orientation      = ntdevmode->orientation;     
2028         devmode->papersize        = ntdevmode->papersize;
2029         devmode->paperlength      = ntdevmode->paperlength;
2030         devmode->paperwidth       = ntdevmode->paperwidth;
2031         devmode->scale            = ntdevmode->scale;
2032         devmode->copies           = ntdevmode->copies;
2033         devmode->defaultsource    = ntdevmode->defaultsource;
2034         devmode->printquality     = ntdevmode->printquality;
2035         devmode->color            = ntdevmode->color;
2036         devmode->duplex           = ntdevmode->duplex;
2037         devmode->yresolution      = ntdevmode->yresolution;
2038         devmode->ttoption         = ntdevmode->ttoption;
2039         devmode->collate          = ntdevmode->collate;
2040         devmode->icmmethod        = ntdevmode->icmmethod;
2041         devmode->icmintent        = ntdevmode->icmintent;
2042         devmode->mediatype        = ntdevmode->mediatype;
2043         devmode->dithertype       = ntdevmode->dithertype;
2044
2045         if (ntdevmode->private != NULL) {
2046                 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2047                         goto fail;
2048         }
2049
2050         free_nt_devicemode(&ntdevmode);
2051         free_a_printer(&printer,2);
2052
2053         return devmode;
2054
2055   fail:
2056
2057         if (ntdevmode)
2058                 free_nt_devicemode(&ntdevmode);
2059         if (printer)
2060                 free_a_printer(&printer,2);
2061         free_dev_mode(devmode);
2062
2063         return NULL;
2064 }
2065
2066 /********************************************************************
2067  * construct_printer_info_2
2068  * fill a printer_info_2 struct
2069  ********************************************************************/
2070
2071 static BOOL construct_printer_info_2(fstring servername, PRINTER_INFO_2 *printer, int snum)
2072 {
2073         pstring chaine;
2074         pstring chaine2;
2075         pstring sl;
2076         int count;
2077         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2078
2079         print_queue_struct *queue=NULL;
2080         print_status_struct status;
2081         memset(&status, 0, sizeof(status));     
2082
2083         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2084                 return False;
2085                 
2086         memset(&status, 0, sizeof(status));             
2087         count = print_queue_status(snum, &queue, &status);
2088
2089         snprintf(chaine, sizeof(chaine)-1, "%s", servername);
2090
2091         if (strlen(servername)!=0)
2092                 fstrcpy(sl, "\\");
2093         else
2094                 fstrcpy(sl, '\0');
2095
2096         if (!strchr(ntprinter->info_2->printername, '\\')) {
2097                 snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter->info_2->printername);
2098         } else {
2099                 pstrcpy(chaine2, ntprinter->info_2->printername);
2100         }
2101
2102         init_unistr(&printer->servername, chaine);                              /* servername*/
2103         init_unistr(&printer->printername, chaine2);                            /* printername*/
2104         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
2105         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
2106         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
2107
2108         if (*ntprinter->info_2->comment == '\0')
2109                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
2110         else
2111                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2112
2113         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
2114         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
2115         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2116         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
2117         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
2118
2119         printer->attributes = ntprinter->info_2->attributes;
2120
2121         printer->priority = ntprinter->info_2->priority;                                /* priority */  
2122         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
2123         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
2124         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
2125         printer->status = nt_printq_status(status.status);                      /* status */
2126         printer->cjobs = count;                                                 /* jobs */
2127         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
2128                         
2129         if((printer->devmode = construct_dev_mode(snum, servername)) == NULL) {
2130                 DEBUG(8, ("Returning NULL Devicemode!\n"));
2131         }
2132
2133         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2134                 /* steal the printer info sec_desc structure.  [badly done]. */
2135                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2136                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2137                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2138                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2139         }
2140         else {
2141                 printer->secdesc = NULL;
2142         }
2143
2144         free_a_printer(&ntprinter, 2);
2145         safe_free(queue);
2146         return True;
2147 }
2148
2149 /********************************************************************
2150  * construct_printer_info_3
2151  * fill a printer_info_3 struct
2152  ********************************************************************/
2153 static BOOL construct_printer_info_3(fstring servername,
2154                         PRINTER_INFO_3 **pp_printer, int snum)
2155 {
2156         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2157         PRINTER_INFO_3 *printer = NULL;
2158
2159         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2160                 return False;
2161
2162         *pp_printer = NULL;
2163         if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2164                 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2165                 return False;
2166         }
2167
2168         ZERO_STRUCTP(printer);
2169         
2170         printer->flags = 4; /* These are the components of the SD we are returning. */
2171         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2172                 /* steal the printer info sec_desc structure.  [badly done]. */
2173                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2174
2175 #if 0
2176                 /*
2177                  * Set the flags for the components we are returning.
2178                  */
2179
2180                 if (printer->secdesc->owner_sid)
2181                         printer->flags |= OWNER_SECURITY_INFORMATION;
2182
2183                 if (printer->secdesc->grp_sid)
2184                         printer->flags |= GROUP_SECURITY_INFORMATION;
2185
2186                 if (printer->secdesc->dacl)
2187                         printer->flags |= DACL_SECURITY_INFORMATION;
2188
2189                 if (printer->secdesc->sacl)
2190                         printer->flags |= SACL_SECURITY_INFORMATION;
2191 #endif
2192
2193                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2194                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2195                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2196         }
2197
2198         free_a_printer(&ntprinter, 2);
2199
2200         *pp_printer = printer;
2201         return True;
2202 }
2203
2204 /********************************************************************
2205  Spoolss_enumprinters.
2206 ********************************************************************/
2207 static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2208 {
2209         int snum;
2210         int i;
2211         int n_services=lp_numservices();
2212         PRINTER_INFO_1 *printers=NULL;
2213         PRINTER_INFO_1 current_prt;
2214         
2215         DEBUG(4,("enum_all_printers_info_1\n"));        
2216
2217         for (snum=0; snum<n_services; snum++) {
2218                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2219                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2220                                 
2221                         if (construct_printer_info_1(server, flags, &current_prt, snum)) {
2222                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2223                                         *returned=0;
2224                                         return ERROR_NOT_ENOUGH_MEMORY;
2225                                 }
2226                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
2227                                 memcpy(&(printers[*returned]), &current_prt, sizeof(PRINTER_INFO_1));
2228                                 (*returned)++;
2229                         }
2230                 }
2231         }
2232                 
2233         /* check the required size. */  
2234         for (i=0; i<*returned; i++)
2235                 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2236
2237         if (!alloc_buffer_size(buffer, *needed))
2238                 return ERROR_INSUFFICIENT_BUFFER;
2239
2240         /* fill the buffer with the structures */
2241         for (i=0; i<*returned; i++)
2242                 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);       
2243
2244         /* clear memory */
2245         safe_free(printers);
2246
2247         if (*needed > offered) {
2248                 *returned=0;
2249                 return ERROR_INSUFFICIENT_BUFFER;
2250         }
2251         else
2252                 return NT_STATUS_NO_PROBLEMO;
2253 }
2254
2255 /********************************************************************
2256  enum_all_printers_info_1_local.
2257 *********************************************************************/
2258 static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2259 {
2260         fstring temp;
2261         DEBUG(4,("enum_all_printers_info_1_local\n"));  
2262         
2263         fstrcpy(temp, "\\\\");
2264         fstrcat(temp, global_myname);
2265
2266         if (!strcmp(name, temp)) {
2267                 fstrcat(temp, "\\");
2268                 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2269         }
2270         else
2271                 return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2272 }
2273
2274 /********************************************************************
2275  enum_all_printers_info_1_name.
2276 *********************************************************************/
2277 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2278 {
2279         fstring temp;
2280         DEBUG(4,("enum_all_printers_info_1_name\n"));   
2281         
2282         fstrcpy(temp, "\\\\");
2283         fstrcat(temp, global_myname);
2284
2285         if (!strcmp(name, temp)) {
2286                 fstrcat(temp, "\\");
2287                 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2288         }
2289         else
2290                 return ERROR_INVALID_NAME;
2291 }
2292
2293 /********************************************************************
2294  enum_all_printers_info_1_remote.
2295 *********************************************************************/
2296 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2297 {
2298         PRINTER_INFO_1 *printer;
2299         fstring printername;
2300         fstring desc;
2301         fstring comment;
2302         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
2303
2304         /* JFM: currently it's more a place holder than anything else.
2305          * In the spooler world there is a notion of server registration.
2306          * the print servers are registring (sp ?) on the PDC (in the same domain)
2307          * 
2308          * We should have a TDB here. The registration is done thru an undocumented RPC call.
2309          */
2310         
2311         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2312                 return ERROR_NOT_ENOUGH_MEMORY;
2313
2314         *returned=1;
2315         
2316         snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);               
2317         snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2318         snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2319
2320         init_unistr(&printer->description, desc);
2321         init_unistr(&printer->name, printername);       
2322         init_unistr(&printer->comment, comment);
2323         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2324                 
2325         /* check the required size. */  
2326         *needed += spoolss_size_printer_info_1(printer);
2327
2328         if (!alloc_buffer_size(buffer, *needed)) {
2329                 safe_free(printer);
2330                 return ERROR_INSUFFICIENT_BUFFER;
2331         }
2332
2333         /* fill the buffer with the structures */
2334         new_smb_io_printer_info_1("", buffer, printer, 0);      
2335
2336         /* clear memory */
2337         safe_free(printer);
2338
2339         if (*needed > offered) {
2340                 *returned=0;
2341                 return ERROR_INSUFFICIENT_BUFFER;
2342         }
2343         else
2344                 return NT_STATUS_NO_PROBLEMO;
2345 }
2346
2347 /********************************************************************
2348  enum_all_printers_info_1_network.
2349 *********************************************************************/
2350 static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2351 {
2352         fstring temp;
2353         DEBUG(4,("enum_all_printers_info_1_network\n"));        
2354         
2355         fstrcpy(temp, "\\\\");
2356         fstrcat(temp, global_myname);
2357         fstrcat(temp, "\\");
2358         return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2359 }
2360
2361 /********************************************************************
2362  * api_spoolss_enumprinters
2363  *
2364  * called from api_spoolss_enumprinters (see this to understand)
2365  ********************************************************************/
2366 static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2367 {
2368         int snum;
2369         int i;
2370         int n_services=lp_numservices();
2371         PRINTER_INFO_2 *printers=NULL;
2372         PRINTER_INFO_2 current_prt;
2373
2374         for (snum=0; snum<n_services; snum++) {
2375                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2376                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2377                                 
2378                         if (construct_printer_info_2(servername, &current_prt, snum)) {
2379                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2380                                         return ERROR_NOT_ENOUGH_MEMORY;
2381                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
2382                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
2383                                 (*returned)++;
2384                         }
2385                 }
2386         }
2387         
2388         /* check the required size. */  
2389         for (i=0; i<*returned; i++)
2390                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2391
2392         if (!alloc_buffer_size(buffer, *needed)) {
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                 return ERROR_INSUFFICIENT_BUFFER;
2399         }
2400
2401         /* fill the buffer with the structures */
2402         for (i=0; i<*returned; i++)
2403                 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);       
2404         
2405         /* clear memory */
2406         for (i=0; i<*returned; i++) {
2407                 free_devmode(printers[i].devmode);
2408                 free_sec_desc(&printers[i].secdesc);
2409         }
2410         safe_free(printers);
2411
2412         if (*needed > offered) {
2413                 *returned=0;
2414                 return ERROR_INSUFFICIENT_BUFFER;
2415         }
2416         else
2417                 return NT_STATUS_NO_PROBLEMO;
2418 }
2419
2420 /********************************************************************
2421  * handle enumeration of printers at level 1
2422  ********************************************************************/
2423 static uint32 enumprinters_level1( uint32 flags, fstring name,
2424                                  NEW_BUFFER *buffer, uint32 offered,
2425                                  uint32 *needed, uint32 *returned)
2426 {
2427         /* Not all the flags are equals */
2428
2429         if (flags & PRINTER_ENUM_LOCAL)
2430                 return enum_all_printers_info_1_local(name, buffer, offered, needed, returned);
2431
2432         if (flags & PRINTER_ENUM_NAME)
2433                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2434
2435         if (flags & PRINTER_ENUM_REMOTE)
2436                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2437
2438         if (flags & PRINTER_ENUM_NETWORK)
2439                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
2440
2441         return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2442 }
2443
2444 /********************************************************************
2445  * handle enumeration of printers at level 2
2446  ********************************************************************/
2447 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2448                                  NEW_BUFFER *buffer, uint32 offered,
2449                                  uint32 *needed, uint32 *returned)
2450 {
2451         fstring temp;
2452         
2453         fstrcpy(temp, "\\\\");
2454         fstrcat(temp, global_myname);
2455
2456         if (flags & PRINTER_ENUM_LOCAL) {
2457                 if (!strcmp(servername, temp))
2458                         return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2459                 else
2460                         return enum_all_printers_info_2("", buffer, offered, needed, returned);
2461         }
2462
2463         if (flags & PRINTER_ENUM_NAME) {
2464                 if (!strcmp(servername, temp))
2465                         return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2466                 else
2467                         return ERROR_INVALID_NAME;
2468         }
2469
2470         if (flags & PRINTER_ENUM_REMOTE)
2471                 return ERROR_INVALID_LEVEL;
2472
2473         return NT_STATUS_NO_PROBLEMO;
2474 }
2475
2476 /********************************************************************
2477  * handle enumeration of printers at level 5
2478  ********************************************************************/
2479 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2480                                  NEW_BUFFER *buffer, uint32 offered,
2481                                  uint32 *needed, uint32 *returned)
2482 {
2483 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2484         return NT_STATUS_NO_PROBLEMO;
2485 }
2486
2487 /********************************************************************
2488  * api_spoolss_enumprinters
2489  *
2490  * called from api_spoolss_enumprinters (see this to understand)
2491  ********************************************************************/
2492 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2493                               NEW_BUFFER *buffer, uint32 offered,
2494                               uint32 *needed, uint32 *returned)
2495 {
2496         fstring name;
2497         
2498         DEBUG(4,("_spoolss_enumprinters\n"));
2499
2500         *needed=0;
2501         *returned=0;
2502         
2503         /*
2504          * Level 1: 
2505          *          flags==PRINTER_ENUM_NAME
2506          *           if name=="" then enumerates all printers
2507          *           if name!="" then enumerate the printer
2508          *          flags==PRINTER_ENUM_REMOTE
2509          *          name is NULL, enumerate printers
2510          * Level 2: name!="" enumerates printers, name can't be NULL
2511          * Level 3: doesn't exist
2512          * Level 4: does a local registry lookup
2513          * Level 5: same as Level 2
2514          */
2515
2516         unistr2_to_ascii(name, servername, sizeof(name)-1);
2517         strupper(name);
2518
2519         switch (level) {
2520         case 1:
2521                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2522         case 2:
2523                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2524         case 5:
2525                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2526         case 3:
2527         case 4:
2528         default:
2529                 return ERROR_INVALID_LEVEL;
2530         }
2531 }
2532
2533 /****************************************************************************
2534 ****************************************************************************/
2535 static uint32 getprinter_level_0(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2536 {
2537         PRINTER_INFO_0 *printer=NULL;
2538
2539         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2540                 return ERROR_NOT_ENOUGH_MEMORY;
2541
2542         construct_printer_info_0(printer, snum, servername);
2543         
2544         /* check the required size. */  
2545         *needed += spoolss_size_printer_info_0(printer);
2546
2547         if (!alloc_buffer_size(buffer, *needed)) {
2548                 safe_free(printer);
2549                 return ERROR_INSUFFICIENT_BUFFER;
2550         }
2551
2552         /* fill the buffer with the structures */
2553         new_smb_io_printer_info_0("", buffer, printer, 0);      
2554         
2555         /* clear memory */
2556         safe_free(printer);
2557
2558         if (*needed > offered) {
2559                 return ERROR_INSUFFICIENT_BUFFER;
2560         }
2561         else
2562                 return NT_STATUS_NO_PROBLEMO;   
2563 }
2564
2565 /****************************************************************************
2566 ****************************************************************************/
2567 static uint32 getprinter_level_1(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2568 {
2569         PRINTER_INFO_1 *printer=NULL;
2570
2571         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2572                 return ERROR_NOT_ENOUGH_MEMORY;
2573
2574         construct_printer_info_1(servername, PRINTER_ENUM_ICON8, printer, snum);
2575         
2576         /* check the required size. */  
2577         *needed += spoolss_size_printer_info_1(printer);
2578
2579         if (!alloc_buffer_size(buffer, *needed)) {
2580                 safe_free(printer);
2581                 return ERROR_INSUFFICIENT_BUFFER;
2582         }
2583
2584         /* fill the buffer with the structures */
2585         new_smb_io_printer_info_1("", buffer, printer, 0);      
2586         
2587         /* clear memory */
2588         safe_free(printer);
2589
2590         if (*needed > offered) {
2591                 return ERROR_INSUFFICIENT_BUFFER;
2592         }
2593         else
2594                 return NT_STATUS_NO_PROBLEMO;   
2595 }
2596
2597 /****************************************************************************
2598 ****************************************************************************/
2599 static uint32 getprinter_level_2(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2600 {
2601         PRINTER_INFO_2 *printer=NULL;
2602         fstring temp;
2603
2604         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2605                 return ERROR_NOT_ENOUGH_MEMORY;
2606         
2607         fstrcpy(temp, "\\\\");
2608         fstrcat(temp, servername);
2609         construct_printer_info_2(temp, printer, snum);
2610         
2611         /* check the required size. */  
2612         *needed += spoolss_size_printer_info_2(printer);
2613
2614         if (!alloc_buffer_size(buffer, *needed)) {
2615                 free_printer_info_2(printer);
2616                 return ERROR_INSUFFICIENT_BUFFER;
2617         }
2618
2619         /* fill the buffer with the structures */
2620         if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2621                 free_printer_info_2(printer);
2622                 return ERROR_NOT_ENOUGH_MEMORY;
2623         }
2624         
2625         /* clear memory */
2626         free_printer_info_2(printer);
2627
2628         if (*needed > offered) {
2629                 return ERROR_INSUFFICIENT_BUFFER;
2630         }
2631         else
2632                 return NT_STATUS_NO_PROBLEMO;   
2633 }
2634
2635 /****************************************************************************
2636 ****************************************************************************/
2637 static uint32 getprinter_level_3(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2638 {
2639         PRINTER_INFO_3 *printer=NULL;
2640         fstring temp;
2641
2642         fstrcpy(temp, "\\\\");
2643         fstrcat(temp, servername);
2644         if (!construct_printer_info_3(temp, &printer, snum))
2645                 return ERROR_NOT_ENOUGH_MEMORY;
2646         
2647         /* check the required size. */  
2648         *needed += spoolss_size_printer_info_3(printer);
2649
2650         if (!alloc_buffer_size(buffer, *needed)) {
2651                 free_printer_info_3(printer);
2652                 return ERROR_INSUFFICIENT_BUFFER;
2653         }
2654
2655         /* fill the buffer with the structures */
2656         new_smb_io_printer_info_3("", buffer, printer, 0);      
2657         
2658         /* clear memory */
2659         free_printer_info_3(printer);
2660         
2661         if (*needed > offered) {
2662                 return ERROR_INSUFFICIENT_BUFFER;
2663         }
2664         else
2665                 return NT_STATUS_NO_PROBLEMO;   
2666 }
2667
2668 /****************************************************************************
2669 ****************************************************************************/
2670 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2671                            NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2672 {
2673         int snum;
2674         fstring servername;
2675         
2676         *needed=0;
2677
2678         pstrcpy(servername, global_myname);
2679
2680         if (!get_printer_snum(handle, &snum))
2681                 return ERROR_INVALID_HANDLE;
2682
2683         switch (level) {
2684         case 0:
2685                 return getprinter_level_0(servername, snum, buffer, offered, needed);
2686         case 1:
2687                 return getprinter_level_1(servername,snum, buffer, offered, needed);
2688         case 2:         
2689                 return getprinter_level_2(servername,snum, buffer, offered, needed);
2690         case 3:         
2691                 return getprinter_level_3(servername,snum, buffer, offered, needed);
2692         default:
2693                 return ERROR_INVALID_LEVEL;
2694         }
2695 }       
2696                 
2697 /********************************************************************
2698  * fill a DRIVER_INFO_1 struct
2699  ********************************************************************/
2700 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2701 {
2702         init_unistr( &info->name, driver.info_3->name);
2703 }
2704
2705 /********************************************************************
2706  * construct_printer_driver_info_1
2707  ********************************************************************/
2708 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2709 {       
2710         NT_PRINTER_INFO_LEVEL *printer = NULL;
2711         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2712
2713         ZERO_STRUCT(driver);
2714
2715         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2716                 return ERROR_INVALID_PRINTER_NAME;
2717
2718         if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2719                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2720
2721         fill_printer_driver_info_1(info, driver, servername, architecture);
2722
2723         free_a_printer(&printer,2);
2724
2725         return NT_STATUS_NO_PROBLEMO;
2726 }
2727
2728 /********************************************************************
2729  * construct_printer_driver_info_2
2730  * fill a printer_info_2 struct
2731  ********************************************************************/
2732 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2733 {
2734         pstring temp_driverpath;
2735         pstring temp_datafile;
2736         pstring temp_configfile;
2737
2738         info->version=driver.info_3->cversion;
2739
2740         init_unistr( &info->name, driver.info_3->name );
2741         init_unistr( &info->architecture, driver.info_3->environment );
2742
2743         snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2744         init_unistr( &info->driverpath, temp_driverpath );
2745
2746         snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2747         init_unistr( &info->datafile, temp_datafile );
2748
2749         snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2750         init_unistr( &info->configfile, temp_configfile );      
2751 }
2752
2753 /********************************************************************
2754  * construct_printer_driver_info_2
2755  * fill a printer_info_2 struct
2756  ********************************************************************/
2757 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2758 {
2759         NT_PRINTER_INFO_LEVEL *printer = NULL;
2760         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2761
2762         ZERO_STRUCT(printer);
2763         ZERO_STRUCT(driver);
2764
2765         if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2766                 return ERROR_INVALID_PRINTER_NAME;
2767
2768         if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2769                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2770
2771         fill_printer_driver_info_2(info, driver, servername);
2772
2773         free_a_printer(&printer,2);
2774
2775         return NT_STATUS_NO_PROBLEMO;
2776 }
2777
2778 /********************************************************************
2779  * copy a strings array and convert to UNICODE
2780  *
2781  * convert an array of ascii string to a UNICODE string
2782  ********************************************************************/
2783 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2784 {
2785         int i=0;
2786         int j=0;
2787         char *v;
2788         pstring line;
2789
2790         DEBUG(6,("init_unistr_array\n"));
2791         *uni_array=NULL;
2792
2793         while (1) {
2794                 if (char_array == NULL)
2795                         v = "";
2796                 else {
2797                         v = char_array[i];
2798                         if (!v) v = ""; /* hack to handle null lists */
2799                 }
2800                 if (strlen(v) == 0) break;
2801                 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2802                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2803                 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2804                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
2805                         return;
2806                 }
2807                 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2808                 i++;
2809         }
2810         
2811         if (*uni_array) {
2812                 (*uni_array)[j]=0x0000;
2813         }
2814         
2815         DEBUGADD(6,("last one:done\n"));
2816 }
2817
2818 /********************************************************************
2819  * construct_printer_info_3
2820  * fill a printer_info_3 struct
2821  ********************************************************************/
2822 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2823 {
2824         pstring temp_driverpath;
2825         pstring temp_datafile;
2826         pstring temp_configfile;
2827         pstring temp_helpfile;
2828
2829         ZERO_STRUCTP(info);
2830
2831         info->version=driver.info_3->cversion;
2832
2833         init_unistr( &info->name, driver.info_3->name );        
2834         init_unistr( &info->architecture, driver.info_3->environment );
2835
2836         snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);                 
2837         init_unistr( &info->driverpath, temp_driverpath );
2838
2839         snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile); 
2840         init_unistr( &info->datafile, temp_datafile );
2841
2842         snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2843         init_unistr( &info->configfile, temp_configfile );      
2844
2845         snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2846         init_unistr( &info->helpfile, temp_helpfile );
2847
2848         init_unistr( &info->monitorname, driver.info_3->monitorname );
2849         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2850
2851         info->dependentfiles=NULL;
2852         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2853 }
2854
2855 /********************************************************************
2856  * construct_printer_info_3
2857  * fill a printer_info_3 struct
2858  ********************************************************************/
2859 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2860 {       
2861         NT_PRINTER_INFO_LEVEL *printer = NULL;
2862         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2863         uint32 status=0;
2864         ZERO_STRUCT(driver);
2865
2866         status=get_a_printer(&printer, 2, lp_servicename(snum) );
2867         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2868         if (status != 0)
2869                 return ERROR_INVALID_PRINTER_NAME;
2870
2871         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
2872         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2873         if (status != 0) {
2874                 free_a_printer(&printer,2);
2875                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2876         }
2877
2878         fill_printer_driver_info_3(info, driver, servername);
2879
2880         free_a_printer(&printer,2);
2881
2882         return NT_STATUS_NO_PROBLEMO;
2883 }
2884
2885 /********************************************************************
2886  * construct_printer_info_6
2887  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2888  ********************************************************************/
2889
2890 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2891 {
2892         pstring temp_driverpath;
2893         pstring temp_datafile;
2894         pstring temp_configfile;
2895         pstring temp_helpfile;
2896         fstring nullstr;
2897
2898         ZERO_STRUCTP(info);
2899         memset(&nullstr, '\0', sizeof(fstring));
2900
2901         info->version=driver.info_3->cversion;
2902
2903         init_unistr( &info->name, driver.info_3->name );        
2904         init_unistr( &info->architecture, driver.info_3->environment );
2905
2906         snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);                 
2907         init_unistr( &info->driverpath, temp_driverpath );
2908
2909         snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile); 
2910         init_unistr( &info->datafile, temp_datafile );
2911
2912         snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2913         init_unistr( &info->configfile, temp_configfile );      
2914
2915         snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2916         init_unistr( &info->helpfile, temp_helpfile );
2917
2918         init_unistr( &info->monitorname, driver.info_3->monitorname );
2919         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2920
2921         info->dependentfiles=NULL;
2922         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2923
2924         info->previousdrivernames=NULL;
2925         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2926
2927         info->driver_date.low=0;
2928         info->driver_date.high=0;
2929
2930         info->padding=0;
2931         info->driver_version_low=0;
2932         info->driver_version_high=0;
2933
2934         init_unistr( &info->mfgname, "");
2935         init_unistr( &info->oem_url, "");
2936         init_unistr( &info->hardware_id, "");
2937         init_unistr( &info->provider, "");
2938 }
2939
2940 /********************************************************************
2941  * construct_printer_info_6
2942  * fill a printer_info_6 struct
2943  ********************************************************************/
2944 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2945 {       
2946         NT_PRINTER_INFO_LEVEL *printer = NULL;
2947         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2948         uint32 status=0;
2949         ZERO_STRUCT(driver);
2950
2951         status=get_a_printer(&printer, 2, lp_servicename(snum) );
2952         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2953         if (status != 0)
2954                 return ERROR_INVALID_PRINTER_NAME;
2955
2956         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
2957         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2958         if (status != 0) {
2959                 free_a_printer(&printer,2);
2960                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2961         }
2962
2963         fill_printer_driver_info_6(info, driver, servername);
2964
2965         free_a_printer(&printer,2);
2966
2967         return NT_STATUS_NO_PROBLEMO;
2968 }
2969
2970 /****************************************************************************
2971 ****************************************************************************/
2972
2973 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2974 {
2975         safe_free(info->dependentfiles);
2976 }
2977
2978 /****************************************************************************
2979 ****************************************************************************/
2980
2981 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2982 {
2983         safe_free(info->dependentfiles);
2984         
2985 }
2986
2987 /****************************************************************************
2988 ****************************************************************************/
2989 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2990 {
2991         DRIVER_INFO_1 *info=NULL;
2992         uint32 status;
2993         
2994         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2995                 return ERROR_NOT_ENOUGH_MEMORY;
2996         
2997         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2998         if (status != NT_STATUS_NO_PROBLEMO) {
2999                 safe_free(info);
3000                 return status;
3001         }
3002
3003         /* check the required size. */  
3004         *needed += spoolss_size_printer_driver_info_1(info);
3005
3006         if (!alloc_buffer_size(buffer, *needed)) {
3007                 safe_free(info);
3008                 return ERROR_INSUFFICIENT_BUFFER;
3009         }
3010
3011         /* fill the buffer with the structures */
3012         new_smb_io_printer_driver_info_1("", buffer, info, 0);  
3013
3014         /* clear memory */
3015         safe_free(info);
3016
3017         if (*needed > offered)
3018                 return ERROR_INSUFFICIENT_BUFFER;
3019         else
3020                 return NT_STATUS_NO_PROBLEMO;
3021 }
3022
3023 /****************************************************************************
3024 ****************************************************************************/
3025 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3026 {
3027         DRIVER_INFO_2 *info=NULL;
3028         uint32 status;
3029         
3030         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3031                 return ERROR_NOT_ENOUGH_MEMORY;
3032         
3033         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3034         if (status != NT_STATUS_NO_PROBLEMO) {
3035                 safe_free(info);
3036                 return status;
3037         }
3038
3039         /* check the required size. */  
3040         *needed += spoolss_size_printer_driver_info_2(info);
3041
3042         if (!alloc_buffer_size(buffer, *needed)) {
3043                 safe_free(info);
3044                 return ERROR_INSUFFICIENT_BUFFER;
3045         }
3046
3047         /* fill the buffer with the structures */
3048         new_smb_io_printer_driver_info_2("", buffer, info, 0);  
3049
3050         /* clear memory */
3051         safe_free(info);
3052
3053         if (*needed > offered)
3054                 return ERROR_INSUFFICIENT_BUFFER;
3055         else
3056                 return NT_STATUS_NO_PROBLEMO;
3057 }
3058
3059 /****************************************************************************
3060 ****************************************************************************/
3061 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3062 {
3063         DRIVER_INFO_3 info;
3064         uint32 status;
3065
3066         ZERO_STRUCT(info);
3067
3068         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3069         if (status != NT_STATUS_NO_PROBLEMO) {
3070                 return status;
3071         }
3072
3073         /* check the required size. */  
3074         *needed += spoolss_size_printer_driver_info_3(&info);
3075
3076         if (!alloc_buffer_size(buffer, *needed)) {
3077                 free_printer_driver_info_3(&info);
3078                 return ERROR_INSUFFICIENT_BUFFER;
3079         }
3080
3081         /* fill the buffer with the structures */
3082         new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3083
3084         free_printer_driver_info_3(&info);
3085
3086         if (*needed > offered)
3087                 return ERROR_INSUFFICIENT_BUFFER;
3088         else
3089                 return NT_STATUS_NO_PROBLEMO;
3090 }
3091
3092 /****************************************************************************
3093 ****************************************************************************/
3094 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3095 {
3096         DRIVER_INFO_6 info;
3097         uint32 status;
3098
3099         ZERO_STRUCT(info);
3100
3101         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3102         if (status != NT_STATUS_NO_PROBLEMO) {
3103                 return status;
3104         }
3105
3106         /* check the required size. */  
3107         *needed += spoolss_size_printer_driver_info_6(&info);
3108
3109         if (!alloc_buffer_size(buffer, *needed)) {
3110                 free_printer_driver_info_6(&info);
3111                 return ERROR_INSUFFICIENT_BUFFER;
3112         }
3113
3114         /* fill the buffer with the structures */
3115         new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3116
3117         free_printer_driver_info_6(&info);
3118
3119         if (*needed > offered)
3120                 return ERROR_INSUFFICIENT_BUFFER;
3121         else
3122                 return NT_STATUS_NO_PROBLEMO;
3123 }
3124
3125 /****************************************************************************
3126 ****************************************************************************/
3127 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level, 
3128                                 uint32 clientmajorversion, uint32 clientminorversion,
3129                                 NEW_BUFFER *buffer, uint32 offered,
3130                                 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3131 {
3132         fstring servername;
3133         fstring architecture;
3134         int snum;
3135
3136         DEBUG(4,("_spoolss_getprinterdriver2\n"));
3137
3138         *needed=0;
3139         *servermajorversion=0;
3140         *serverminorversion=0;
3141
3142         pstrcpy(servername, global_myname);
3143         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3144
3145         if (!get_printer_snum(handle, &snum))
3146                 return ERROR_INVALID_HANDLE;
3147
3148         switch (level) {
3149         case 1:
3150                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3151         case 2:
3152                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3153         case 3:
3154                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3155         case 6:
3156                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3157         default:
3158                 return ERROR_INVALID_LEVEL;
3159         }
3160 }
3161
3162 /****************************************************************************
3163 ****************************************************************************/
3164 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3165 {
3166         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3167
3168         if (OPEN_HANDLE(Printer)) {
3169                 Printer->page_started=True;
3170                 return 0x0;
3171         }
3172
3173         DEBUG(3,("Error in startpageprinter printer handle\n"));
3174         return ERROR_INVALID_HANDLE;
3175 }
3176
3177 /****************************************************************************
3178 ****************************************************************************/
3179 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3180 {
3181         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3182
3183         if (!OPEN_HANDLE(Printer)) {
3184                 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3185                 return ERROR_INVALID_HANDLE;
3186         }
3187         
3188         Printer->page_started=False;
3189
3190         return NT_STATUS_NO_PROBLEMO;
3191 }
3192
3193 /****************************************************************************
3194  Return a user struct for a pipe user.
3195 ****************************************************************************/
3196
3197 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3198 {
3199         if (p->ntlmssp_auth_validated) {
3200                 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3201         } else {
3202                 extern struct current_user current_user;
3203                 memcpy(user, &current_user, sizeof(struct current_user));
3204         }
3205
3206         return user;
3207 }
3208
3209 /********************************************************************
3210  * api_spoolss_getprinter
3211  * called from the spoolss dispatcher
3212  *
3213  ********************************************************************/
3214 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3215                                 pipes_struct *p, DOC_INFO *docinfo, 
3216                                 uint32 *jobid)
3217 {
3218         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3219         int snum;
3220         pstring jobname;
3221         fstring datatype;
3222         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3223         struct current_user user;
3224
3225         if (!OPEN_HANDLE(Printer)) {
3226                 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3227                 return ERROR_INVALID_HANDLE;
3228         }
3229
3230         get_current_user(&user, p);
3231
3232         /*
3233          * a nice thing with NT is it doesn't listen to what you tell it.
3234          * when asked to send _only_ RAW datas, it tries to send datas
3235          * in EMF format.
3236          *
3237          * So I add checks like in NT Server ...
3238          *
3239          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
3240          * there's a bug in NT client-side code, so we'll fix it in the
3241          * server-side code. *nnnnnggggh!*
3242          */
3243         
3244         if (info_1->p_datatype != 0) {
3245                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3246                 if (strcmp(datatype, "RAW") != 0) {
3247                         (*jobid)=0;
3248                         return ERROR_INVALID_DATATYPE;
3249                 }               
3250         }                
3251         
3252         /* get the share number of the printer */
3253         if (!get_printer_snum(handle, &snum)) {
3254                 return ERROR_INVALID_HANDLE;
3255         }
3256
3257         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3258         
3259         Printer->jobid = print_job_start(&user, snum, jobname);
3260
3261         /* An error occured in print_job_start() so return an appropriate
3262            NT error code. */
3263
3264         if (Printer->jobid == -1) {
3265                 return map_nt_error_from_unix(errno);
3266         }
3267         
3268         Printer->document_started=True;
3269         (*jobid) = Printer->jobid;
3270
3271         srv_spoolss_sendnotify(handle);
3272         return 0x0;
3273 }
3274
3275 /********************************************************************
3276  * api_spoolss_getprinter
3277  * called from the spoolss dispatcher
3278  *
3279  ********************************************************************/
3280 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3281 {
3282         Printer_entry *Printer=find_printer_index_by_hnd(handle);
3283         
3284         if (!OPEN_HANDLE(Printer)) {
3285                 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3286                 return ERROR_INVALID_HANDLE;
3287         }
3288         
3289         Printer->document_started=False;
3290         print_job_end(Printer->jobid);
3291         /* error codes unhandled so far ... */
3292
3293         srv_spoolss_sendnotify(handle);
3294
3295         return 0x0;
3296 }
3297
3298 /****************************************************************************
3299 ****************************************************************************/
3300 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3301                                 uint32 buffer_size,
3302                                 uint8 *buffer,
3303                                 uint32 *buffer_written)
3304 {
3305         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3306         
3307         if (!OPEN_HANDLE(Printer)) {
3308                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3309                 return ERROR_INVALID_HANDLE;
3310         }
3311
3312         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, 
3313                                             buffer_size);
3314
3315         return 0x0;
3316 }
3317
3318 /********************************************************************
3319  * api_spoolss_getprinter
3320  * called from the spoolss dispatcher
3321  *
3322  ********************************************************************/
3323 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3324                               pipes_struct *p)
3325 {
3326         struct current_user user;
3327         int snum;
3328         int errcode = 0;
3329         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3330
3331         get_current_user(&user, p);
3332
3333         if (!OPEN_HANDLE(Printer)) {
3334                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3335                 return ERROR_INVALID_HANDLE;
3336         }
3337
3338         if (!get_printer_snum(handle, &snum) )   
3339                 return ERROR_INVALID_HANDLE;
3340
3341         switch (command) {
3342         case PRINTER_CONTROL_PAUSE:
3343                 if (print_queue_pause(&user, snum, &errcode)) {
3344                         srv_spoolss_sendnotify(handle);
3345                         return 0;
3346                 }
3347                 break;
3348         case PRINTER_CONTROL_RESUME:
3349         case PRINTER_CONTROL_UNPAUSE:
3350                 if (print_queue_resume(&user, snum, &errcode)) {
3351                         srv_spoolss_sendnotify(handle);
3352                         return 0;
3353                 }
3354                 break;
3355         case PRINTER_CONTROL_PURGE:
3356                 if (print_queue_purge(&user, snum, &errcode)) {
3357                         srv_spoolss_sendnotify(handle);
3358                         return 0;
3359                 }
3360                 break;
3361         }
3362
3363         if (errcode)
3364                 return (uint32)errcode;
3365
3366         return ERROR_INVALID_FUNCTION;
3367 }
3368
3369 /********************************************************************
3370  * api_spoolss_abortprinter
3371  ********************************************************************/
3372
3373 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3374 {
3375         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3376 }
3377
3378 /********************************************************************
3379  * called by spoolss_api_setprinter
3380  * when updating a printer description
3381  ********************************************************************/
3382 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3383                                  const SPOOL_PRINTER_INFO_LEVEL *info,
3384                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3385 {
3386         struct current_user user;
3387         uint32 result;
3388         int snum;
3389
3390         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3391
3392         if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3393                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3394                 return ERROR_INVALID_HANDLE;
3395         }
3396
3397         /* Work out which user is performing the operation */
3398         get_current_user(&user, p);
3399
3400         /* Check the user has permissions to change the security
3401            descriptor.  By experimentation with two NT machines, the user
3402            requires Full Access to the printer to change security
3403            information. */ 
3404         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3405                 result = ERROR_ACCESS_DENIED;
3406                 goto done;
3407         }
3408
3409         result = nt_printing_setsec(Printer->dev.handlename, secdesc_ctr);
3410
3411  done:
3412         return result;
3413 }
3414
3415 /********************************************************************
3416  Do Samba sanity checks on a printer info struct.
3417  ********************************************************************/
3418
3419 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3420 {
3421         /*
3422          * Ensure that this printer is shared under the correct name
3423          * as this is what Samba insists upon.
3424          */
3425
3426         if (!(info->attributes & (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_NETWORK))) {
3427                 DEBUG(10,("check_printer_ok: SHARED/NETWORK check failed (%x).\n",
3428                                                         (unsigned int)info->attributes ));
3429                 return False;
3430         }
3431
3432         if (!(info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY)) {
3433                 /* NT forgets to set the raw attribute but sends the correct type. */
3434                 if (strequal(info->datatype, "RAW"))
3435                         info->attributes |= PRINTER_ATTRIBUTE_RAW_ONLY;
3436                 else {
3437                         DEBUG(10,("check_printer_ok: RAW check failed (%x).\n", (unsigned int)info->attributes ));
3438                         return False;
3439                 }
3440         }
3441
3442         /*
3443          * Sometimes the NT client doesn't set the sharename, but
3444          * includes the sharename in the printername. This could
3445          * cause SETPRINTER to fail which causes problems with the
3446          * client getting confused between local/remote printers...
3447          */
3448          
3449         if (*info->sharename == '\0') {
3450                 char *p = strrchr(info->printername, '\\');
3451                 if (p)
3452                         fstrcpy(info->sharename, p+1);
3453         }
3454
3455         if (!strequal(info->sharename, lp_servicename(snum))) {
3456                 DEBUG(10,("check_printer_ok: NAME check failed (%s) (%s).\n",
3457                                         info->sharename, lp_servicename(snum)));
3458                 return False;
3459         }
3460
3461         return True;
3462 }
3463
3464 /****************************************************************************
3465 ****************************************************************************/
3466 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3467 {
3468         pid_t local_pid = sys_getpid();
3469         char *cmd = lp_addprinter_cmd();
3470         char *path;
3471         char **qlines;
3472         pstring tmp_file;
3473         pstring command;
3474         pstring driverlocation;
3475         int numlines;
3476         int ret;
3477
3478         if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3479                 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3480         else
3481                 path = tmpdir();
3482
3483         /* build driver path... only 9X architecture is needed for legacy reasons */
3484         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3485                         global_myname);
3486         /* change \ to \\ for the shell */
3487         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3488         
3489         slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3490         slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3491                         cmd, printer->info_2->printername, printer->info_2->sharename,
3492                         printer->info_2->portname, printer->info_2->drivername,
3493                         printer->info_2->location, driverlocation);
3494
3495         unlink(tmp_file);
3496         DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3497         ret = smbrun(command, tmp_file, False);
3498         DEBUGADD(10,("returned [%d]\n", ret));
3499
3500         if ( ret != 0 ) {
3501                 unlink(tmp_file);
3502                 return False;
3503         }
3504
3505         numlines = 0;
3506         qlines = file_lines_load(tmp_file, &numlines);
3507         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3508         DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3509         unlink(tmp_file);
3510
3511         if(numlines) {
3512                 /* Set the portname to what the script says the portname should be. */
3513                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3514                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3515
3516                 /* Send SIGHUP to process group... is there a better way? */
3517                 kill(0, SIGHUP);
3518                 add_all_printers();
3519         }
3520
3521         file_lines_free(qlines);
3522         return True;
3523 }
3524
3525 /********************************************************************
3526  * called by spoolss_api_setprinter
3527  * when updating a printer description
3528  ********************************************************************/
3529
3530 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3531                            const SPOOL_PRINTER_INFO_LEVEL *info,
3532                            DEVICEMODE *devmode)
3533 {
3534         int snum;
3535         NT_PRINTER_INFO_LEVEL *printer = NULL;
3536         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3537         uint32 result;
3538
3539         DEBUG(8,("update_printer\n"));
3540         
3541         result = NT_STATUS_NO_PROBLEMO;
3542
3543         /* Check calling user has permission to update printer description */ 
3544
3545         if (level!=2) {
3546                 DEBUG(0,("Send a mail to samba@samba.org\n"));
3547                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3548                 result = ERROR_INVALID_LEVEL;
3549                 goto done;
3550         }
3551
3552         if (!OPEN_HANDLE(Printer)) {
3553                 result = ERROR_INVALID_HANDLE;
3554                 goto done;
3555         }
3556
3557         if (!get_printer_snum(handle, &snum)) {
3558                 result = ERROR_INVALID_HANDLE;
3559                 goto done;
3560         }
3561
3562         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3563                 DEBUG(3, ("printer property change denied by security "
3564                           "descriptor\n"));
3565                 result = ERROR_ACCESS_DENIED;
3566                 goto done;
3567         }
3568         
3569         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0) {
3570                 result = ERROR_INVALID_HANDLE;
3571                 goto done;
3572         }
3573
3574         DEBUGADD(8,("Converting info_2 struct\n"));
3575
3576         /*
3577          * convert_printer_info converts the incoming
3578          * info from the client and overwrites the info
3579          * just read from the tdb in the pointer 'printer'.
3580          */
3581
3582         convert_printer_info(info, printer, level);
3583         
3584         if (info->info_2->devmode_ptr != 0) {
3585                 /* we have a valid devmode
3586                    convert it and link it*/
3587
3588                 /*
3589                  * Ensure printer->info_2->devmode is a valid pointer 
3590                  * as we will be overwriting it in convert_devicemode().
3591                  */
3592                 
3593                 if (printer->info_2->devmode == NULL)
3594                         printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3595
3596                 DEBUGADD(8,("Converting the devicemode struct\n"));
3597                 convert_devicemode(devmode, printer->info_2->devmode);
3598
3599         } else {
3600                 if (printer->info_2->devmode != NULL)
3601                         free_nt_devicemode(&printer->info_2->devmode);
3602                 printer->info_2->devmode=NULL;
3603         }
3604
3605         /*
3606          * Do sanity check on the requested changes for Samba.
3607          */
3608
3609         if (!check_printer_ok(printer->info_2, snum)) {
3610                 result = ERROR_INVALID_PARAMETER;
3611                 goto done;
3612         }
3613
3614         if (*lp_addprinter_cmd() )
3615                 if ( !add_printer_hook(printer) ) {
3616                         result = ERROR_ACCESS_DENIED;
3617                         goto done;
3618                 }
3619         
3620         if (add_a_printer(*printer, 2)!=0) {
3621                 /* I don't really know what to return here !!! */
3622                 result = ERROR_ACCESS_DENIED;
3623                 goto done;
3624         }
3625
3626  done:
3627         free_a_printer(&printer, 2);
3628
3629         srv_spoolss_sendnotify(handle);
3630
3631         return result;
3632 }
3633
3634 /****************************************************************************
3635 ****************************************************************************/
3636 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3637                            const SPOOL_PRINTER_INFO_LEVEL *info,
3638                            DEVMODE_CTR devmode_ctr,
3639                            SEC_DESC_BUF *secdesc_ctr,
3640                            uint32 command, pipes_struct *p)
3641 {
3642         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3643         
3644         if (!OPEN_HANDLE(Printer)) {
3645                 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3646                 return ERROR_INVALID_HANDLE;
3647         }
3648
3649         /* check the level */   
3650         switch (level) {
3651                 case 0:
3652                         return control_printer(handle, command, p);
3653                 case 2:
3654                         return update_printer(handle, level, info, devmode_ctr.devmode);
3655                 case 3:
3656                         return update_printer_sec(handle, level, info, p,
3657                                                   secdesc_ctr);
3658                 default:
3659                         return ERROR_INVALID_LEVEL;
3660         }
3661 }
3662
3663 /****************************************************************************
3664 ****************************************************************************/
3665 uint32 _spoolss_fcpn(POLICY_HND *handle)
3666 {
3667         Printer_entry *Printer= find_printer_index_by_hnd(handle);
3668         
3669         if (!OPEN_HANDLE(Printer)) {
3670                 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3671                 return ERROR_INVALID_HANDLE;
3672         }
3673
3674         if (Printer->notify.client_connected==True)
3675                 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3676                         return ERROR_INVALID_HANDLE;
3677
3678         Printer->notify.flags=0;
3679         Printer->notify.options=0;
3680         Printer->notify.localmachine[0]='\0';
3681         Printer->notify.printerlocal=0;
3682         if (Printer->notify.option)
3683                 safe_free(Printer->notify.option->ctr.type);
3684         safe_free(Printer->notify.option);
3685         Printer->notify.option=NULL;
3686         Printer->notify.client_connected=False;
3687
3688         return NT_STATUS_NO_PROBLEMO;
3689 }
3690
3691 /****************************************************************************
3692 ****************************************************************************/
3693 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3694                        NEW_BUFFER *buffer, uint32 offered,
3695                        uint32 *needed)
3696 {
3697         *needed = 0;
3698         return ERROR_INVALID_PARAMETER; /* this is what a NT server
3699                                            returns for AddJob. AddJob
3700                                            must fail on non-local
3701                                            printers */
3702 }
3703
3704 /****************************************************************************
3705 ****************************************************************************/
3706 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3707                             int position, int snum)
3708 {
3709         pstring temp_name;
3710         
3711         struct tm *t;
3712         
3713         t=gmtime(&queue->time);
3714         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3715
3716         job_info->jobid=queue->job;     
3717         init_unistr(&job_info->printername, lp_servicename(snum));
3718         init_unistr(&job_info->machinename, temp_name);
3719         init_unistr(&job_info->username, queue->user);
3720         init_unistr(&job_info->document, queue->file);
3721         init_unistr(&job_info->datatype, "RAW");
3722         init_unistr(&job_info->text_status, "");
3723         job_info->status=nt_printj_status(queue->status);
3724         job_info->priority=queue->priority;
3725         job_info->position=position;
3726         job_info->totalpages=0;
3727         job_info->pagesprinted=0;
3728
3729         make_systemtime(&job_info->submitted, t);
3730 }
3731
3732 /****************************************************************************
3733 ****************************************************************************/
3734 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3735                             int position, int snum)
3736 {
3737         pstring temp_name;
3738         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3739         pstring chaine;
3740         struct tm *t;
3741
3742         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3743                 return False;
3744         
3745         t=gmtime(&queue->time);
3746         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3747
3748         job_info->jobid=queue->job;
3749         
3750         snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3751
3752         init_unistr(&job_info->printername, chaine);
3753         
3754         init_unistr(&job_info->machinename, temp_name);
3755         init_unistr(&job_info->username, queue->user);
3756         init_unistr(&job_info->document, queue->file);
3757         init_unistr(&job_info->notifyname, queue->user);
3758         init_unistr(&job_info->datatype, "RAW");
3759         init_unistr(&job_info->printprocessor, "winprint");
3760         init_unistr(&job_info->parameters, "");
3761         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3762         init_unistr(&job_info->text_status, "");
3763         
3764 /* and here the security descriptor */
3765
3766         job_info->status=nt_printj_status(queue->status);
3767         job_info->priority=queue->priority;
3768         job_info->position=position;
3769         job_info->starttime=0;
3770         job_info->untiltime=0;
3771         job_info->totalpages=0;
3772         job_info->size=queue->size;
3773         make_systemtime(&(job_info->submitted), t);
3774         job_info->timeelapsed=0;
3775         job_info->pagesprinted=0;
3776
3777         if((job_info->devmode = construct_dev_mode(snum, global_myname)) == NULL) {
3778                 free_a_printer(&ntprinter, 2);
3779                 return False;
3780         }
3781
3782         free_a_printer(&ntprinter, 2);
3783         return (True);
3784 }
3785
3786 /****************************************************************************
3787  Enumjobs at level 1.
3788 ****************************************************************************/
3789 static uint32 enumjobs_level1(print_queue_struct *queue, int snum, 
3790                               NEW_BUFFER *buffer, uint32 offered, 
3791                               uint32 *needed, uint32 *returned)
3792 {
3793         JOB_INFO_1 *info;
3794         int i;
3795         
3796         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3797         if (info==NULL) {
3798                 safe_free(queue);
3799                 *returned=0;
3800                 return ERROR_NOT_ENOUGH_MEMORY;
3801         }
3802         
3803         for (i=0; i<*returned; i++)
3804                 fill_job_info_1(&info[i], &queue[i], i, snum);
3805
3806         safe_free(queue);
3807
3808         /* check the required size. */  
3809         for (i=0; i<*returned; i++)
3810                 (*needed) += spoolss_size_job_info_1(&info[i]);
3811
3812         if (!alloc_buffer_size(buffer, *needed)) {
3813                 safe_free(info);
3814                 return ERROR_INSUFFICIENT_BUFFER;
3815         }
3816
3817         /* fill the buffer with the structures */
3818         for (i=0; i<*returned; i++)
3819                 new_smb_io_job_info_1("", buffer, &info[i], 0); 
3820
3821         /* clear memory */
3822         safe_free(info);
3823
3824         if (*needed > offered) {
3825                 *returned=0;
3826                 return ERROR_INSUFFICIENT_BUFFER;
3827         }
3828         else
3829                 return NT_STATUS_NO_PROBLEMO;
3830 }
3831
3832 /****************************************************************************
3833  Enumjobs at level 2.
3834 ****************************************************************************/
3835 static uint32 enumjobs_level2(print_queue_struct *queue, int snum, 
3836                               NEW_BUFFER *buffer, uint32 offered, 
3837                               uint32 *needed, uint32 *returned)
3838 {
3839         JOB_INFO_2 *info;
3840         int i;
3841         
3842         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
3843         if (info==NULL) {
3844                 safe_free(queue);
3845                 *returned=0;
3846                 return ERROR_NOT_ENOUGH_MEMORY;
3847         }
3848         
3849         for (i=0; i<*returned; i++)
3850                 fill_job_info_2(&(info[i]), &queue[i], i, snum);
3851
3852         safe_free(queue);
3853
3854         /* check the required size. */  
3855         for (i=0; i<*returned; i++)
3856                 (*needed) += spoolss_size_job_info_2(&info[i]);
3857
3858         if (!alloc_buffer_size(buffer, *needed)) {
3859                 safe_free(info);
3860                 return ERROR_INSUFFICIENT_BUFFER;
3861         }
3862
3863         /* fill the buffer with the structures */
3864         for (i=0; i<*returned; i++)
3865                 new_smb_io_job_info_2("", buffer, &info[i], 0); 
3866
3867         /* clear memory */
3868         safe_free(info);
3869
3870         if (*needed > offered) {
3871                 *returned=0;
3872                 return ERROR_INSUFFICIENT_BUFFER;
3873         }
3874         else
3875                 return NT_STATUS_NO_PROBLEMO;
3876 }
3877
3878 /****************************************************************************
3879  Enumjobs.
3880 ****************************************************************************/
3881 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,                    
3882                           NEW_BUFFER *buffer, uint32 offered,
3883                           uint32 *needed, uint32 *returned)
3884 {       
3885         int snum;
3886         print_queue_struct *queue=NULL;
3887         print_status_struct prt_status;
3888
3889         DEBUG(4,("_spoolss_enumjobs\n"));
3890
3891         ZERO_STRUCT(prt_status);
3892
3893         *needed=0;
3894         *returned=0;
3895
3896         if (!get_printer_snum(handle, &snum))
3897                 return ERROR_INVALID_HANDLE;
3898
3899         *returned = print_queue_status(snum, &queue, &prt_status);
3900         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
3901
3902         if (*returned == 0) {
3903                 safe_free(queue);
3904                 return NT_STATUS_NO_PROBLEMO;
3905         }
3906
3907         switch (level) {
3908         case 1:
3909                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
3910         case 2:
3911                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
3912         default:
3913                 safe_free(queue);
3914                 *returned=0;
3915                 return ERROR_INVALID_LEVEL;
3916         }
3917 }
3918
3919
3920 /****************************************************************************
3921 ****************************************************************************/
3922 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
3923 {
3924         return 0x0;
3925 }
3926
3927 /****************************************************************************
3928 ****************************************************************************/
3929 uint32 _spoolss_setjob( POLICY_HND *handle,
3930                                 uint32 jobid,
3931                                 uint32 level,
3932                 pipes_struct *p,
3933                                 JOB_INFO *ctr,
3934                                 uint32 command)
3935
3936 {
3937         struct current_user user;
3938         int snum;
3939         print_status_struct prt_status;
3940                 
3941         memset(&prt_status, 0, sizeof(prt_status));
3942
3943         if (!get_printer_snum(handle, &snum)) {
3944                 return ERROR_INVALID_HANDLE;
3945         }
3946
3947         if (!print_job_exists(jobid)) {
3948                 return ERROR_INVALID_PRINTER_NAME;
3949         }
3950
3951         get_current_user(&user, p);     
3952
3953         switch (command) {
3954         case JOB_CONTROL_CANCEL:
3955         case JOB_CONTROL_DELETE:
3956                 if (print_job_delete(&user, jobid)) {
3957                         srv_spoolss_sendnotify(handle);
3958                         return 0x0;
3959                 }
3960                 break;
3961         case JOB_CONTROL_PAUSE:
3962                 if (print_job_pause(&user, jobid)) {
3963                         srv_spoolss_sendnotify(handle);
3964                         return 0x0;
3965                 }               
3966                 break;
3967         case JOB_CONTROL_RESUME:
3968                 if (print_job_resume(&user, jobid)) {
3969                         srv_spoolss_sendnotify(handle);
3970                         return 0x0;
3971                 }
3972                 break;
3973         default:
3974                 return ERROR_INVALID_LEVEL;
3975         }
3976
3977         return ERROR_INVALID_HANDLE;
3978 }
3979
3980 /****************************************************************************
3981  Enumerates all printer drivers at level 1.
3982 ****************************************************************************/
3983 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3984 {
3985         int i;
3986         int ndrivers;
3987         uint32 version;
3988         fstring *list = NULL;
3989
3990         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3991         DRIVER_INFO_1 *driver_info_1=NULL;
3992
3993         *returned=0;
3994
3995 #define MAX_VERSION 4
3996
3997         for (version=0; version<MAX_VERSION; version++) {
3998                 list=NULL;
3999                 ndrivers=get_ntdrivers(&list, architecture, version);
4000                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4001
4002                 if(ndrivers == -1)
4003                         return ERROR_NOT_ENOUGH_MEMORY;
4004
4005                 if(ndrivers != 0) {
4006                         if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4007                                 safe_free(list);
4008                                 return ERROR_NOT_ENOUGH_MEMORY;
4009                         }
4010                 }
4011
4012                 for (i=0; i<ndrivers; i++) {
4013                         uint32 status;
4014                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4015                         ZERO_STRUCT(driver);
4016                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4017                                 safe_free(list);
4018                                 return status;
4019                         }
4020                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
4021                         free_a_printer_driver(driver, 3);
4022                 }       
4023
4024                 *returned+=ndrivers;
4025                 safe_free(list);
4026         }
4027         
4028         /* check the required size. */
4029         for (i=0; i<*returned; i++) {
4030                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4031                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4032         }
4033
4034         if (!alloc_buffer_size(buffer, *needed)) {
4035                 safe_free(driver_info_1);
4036                 return ERROR_INSUFFICIENT_BUFFER;
4037         }
4038
4039         /* fill the buffer with the form structures */
4040         for (i=0; i<*returned; i++) {
4041                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4042                 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4043         }
4044
4045         safe_free(driver_info_1);
4046
4047         if (*needed > offered) {
4048                 *returned=0;
4049                 return ERROR_INSUFFICIENT_BUFFER;
4050         }
4051         else
4052                 return NT_STATUS_NO_PROBLEMO;
4053 }
4054
4055 /****************************************************************************
4056  Enumerates all printer drivers at level 2.
4057 ****************************************************************************/
4058 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4059 {
4060         int i;
4061         int ndrivers;
4062         uint32 version;
4063         fstring *list = NULL;
4064
4065         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4066         DRIVER_INFO_2 *driver_info_2=NULL;
4067
4068         *returned=0;
4069
4070 #define MAX_VERSION 4
4071
4072         for (version=0; version<MAX_VERSION; version++) {
4073                 list=NULL;
4074                 ndrivers=get_ntdrivers(&list, architecture, version);
4075                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4076
4077                 if(ndrivers == -1)
4078                         return ERROR_NOT_ENOUGH_MEMORY;
4079
4080                 if(ndrivers != 0) {
4081                         if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4082                                 safe_free(list);
4083                                 return ERROR_NOT_ENOUGH_MEMORY;
4084                         }
4085                 }
4086                 
4087                 for (i=0; i<ndrivers; i++) {
4088                         uint32 status;
4089
4090                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4091                         ZERO_STRUCT(driver);
4092                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4093                                 safe_free(list);
4094                                 return status;
4095                         }
4096                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
4097                         free_a_printer_driver(driver, 3);
4098                 }       
4099
4100                 *returned+=ndrivers;
4101                 safe_free(list);
4102         }
4103         
4104         /* check the required size. */
4105         for (i=0; i<*returned; i++) {
4106                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4107                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4108         }
4109
4110         if (!alloc_buffer_size(buffer, *needed)) {
4111                 safe_free(driver_info_2);
4112                 return ERROR_INSUFFICIENT_BUFFER;
4113         }
4114
4115         /* fill the buffer with the form structures */
4116         for (i=0; i<*returned; i++) {
4117                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4118                 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4119         }
4120
4121         safe_free(driver_info_2);
4122
4123         if (*needed > offered) {
4124                 *returned=0;
4125                 return ERROR_INSUFFICIENT_BUFFER;
4126         }
4127         else
4128                 return NT_STATUS_NO_PROBLEMO;
4129 }
4130
4131 /****************************************************************************
4132  Enumerates all printer drivers at level 3.
4133 ****************************************************************************/
4134 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4135 {
4136         int i;
4137         int ndrivers;
4138         uint32 version;
4139         fstring *list = NULL;
4140
4141         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4142         DRIVER_INFO_3 *driver_info_3=NULL;
4143
4144         *returned=0;
4145
4146 #define MAX_VERSION 4
4147
4148         for (version=0; version<MAX_VERSION; version++) {
4149                 list=NULL;
4150                 ndrivers=get_ntdrivers(&list, architecture, version);
4151                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4152
4153                 if(ndrivers == -1)
4154                         return ERROR_NOT_ENOUGH_MEMORY;
4155
4156                 if(ndrivers != 0) {
4157                         if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4158                                 safe_free(list);
4159                                 return ERROR_NOT_ENOUGH_MEMORY;
4160                         }
4161                 }
4162
4163                 for (i=0; i<ndrivers; i++) {
4164                         uint32 status;
4165
4166                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4167                         ZERO_STRUCT(driver);
4168                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4169                                 safe_free(list);
4170                                 return status;
4171                         }
4172                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
4173                         free_a_printer_driver(driver, 3);
4174                 }       
4175
4176                 *returned+=ndrivers;
4177                 safe_free(list);
4178         }
4179
4180         /* check the required size. */
4181         for (i=0; i<*returned; i++) {
4182                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4183                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4184         }
4185
4186         if (!alloc_buffer_size(buffer, *needed)) {
4187                 safe_free(driver_info_3);
4188                 return ERROR_INSUFFICIENT_BUFFER;
4189         }
4190         
4191         /* fill the buffer with the driver structures */
4192         for (i=0; i<*returned; i++) {
4193                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4194                 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4195         }
4196
4197         for (i=0; i<*returned; i++)
4198                 safe_free(driver_info_3[i].dependentfiles);
4199         
4200         safe_free(driver_info_3);
4201         
4202         if (*needed > offered) {
4203                 *returned=0;
4204                 return ERROR_INSUFFICIENT_BUFFER;
4205         }
4206         else
4207                 return NT_STATUS_NO_PROBLEMO;
4208 }
4209
4210 /****************************************************************************
4211  Enumerates all printer drivers.
4212 ****************************************************************************/
4213 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4214                                     NEW_BUFFER *buffer, uint32 offered,
4215                                     uint32 *needed, uint32 *returned)
4216 {
4217         fstring *list = NULL;
4218         fstring servername;
4219         fstring architecture;
4220
4221         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4222         fstrcpy(servername, global_myname);
4223         *needed=0;
4224         *returned=0;
4225
4226         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4227
4228         switch (level) {
4229         case 1:
4230                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4231         case 2:
4232                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4233         case 3:
4234                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4235         default:
4236                 *returned=0;
4237                 safe_free(list);
4238                 return ERROR_INVALID_LEVEL;
4239         }
4240 }
4241
4242 /****************************************************************************
4243 ****************************************************************************/
4244 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4245 {
4246         form->flag=list->flag;
4247         init_unistr(&form->name, list->name);
4248         form->width=list->width;
4249         form->length=list->length;
4250         form->left=list->left;
4251         form->top=list->top;
4252         form->right=list->right;
4253         form->bottom=list->bottom;      
4254 }
4255         
4256 /****************************************************************************
4257 ****************************************************************************/
4258 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level, 
4259                                NEW_BUFFER *buffer, uint32 offered, 
4260                                uint32 *needed, uint32 *numofforms)
4261 {
4262         nt_forms_struct *list=NULL;
4263         FORM_1 *forms_1;
4264         int buffer_size=0;
4265         int i;
4266
4267         DEBUG(4,("_new_spoolss_enumforms\n"));
4268         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4269         DEBUGADD(5,("Info level [%d]\n",          level));
4270
4271         *numofforms = get_ntforms(&list);
4272         DEBUGADD(5,("Number of forms [%d]\n",     *numofforms));
4273
4274         if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4275
4276         switch (level) {
4277         case 1:
4278                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4279                         *numofforms=0;
4280                         return ERROR_NOT_ENOUGH_MEMORY;
4281                 }
4282
4283                 /* construct the list of form structures */
4284                 for (i=0; i<*numofforms; i++) {
4285                         DEBUGADD(6,("Filling form number [%d]\n",i));
4286                         fill_form_1(&forms_1[i], &list[i]);
4287                 }
4288                 
4289                 safe_free(list);
4290
4291                 /* check the required size. */
4292                 for (i=0; i<*numofforms; i++) {
4293                         DEBUGADD(6,("adding form [%d]'s size\n",i));
4294                         buffer_size += spoolss_size_form_1(&forms_1[i]);
4295                 }
4296
4297                 *needed=buffer_size;            
4298                 
4299                 if (!alloc_buffer_size(buffer, buffer_size)){
4300                         safe_free(forms_1);
4301                         return ERROR_INSUFFICIENT_BUFFER;
4302                 }
4303
4304                 /* fill the buffer with the form structures */
4305                 for (i=0; i<*numofforms; i++) {
4306                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
4307                         new_smb_io_form_1("", buffer, &forms_1[i], 0);
4308                 }
4309
4310                 safe_free(forms_1);
4311
4312                 if (*needed > offered) {
4313                         *numofforms=0;
4314                         return ERROR_INSUFFICIENT_BUFFER;
4315                 }
4316                 else
4317                         return NT_STATUS_NO_PROBLEMO;
4318                         
4319         default:
4320                 safe_free(list);
4321                 return ERROR_INVALID_LEVEL;
4322         }
4323
4324 }
4325
4326 /****************************************************************************
4327 ****************************************************************************/
4328 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4329 {
4330         nt_forms_struct *list=NULL;
4331         FORM_1 form_1;
4332         fstring form_name;
4333         int buffer_size=0;
4334         int numofforms, i;
4335
4336         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4337
4338         DEBUG(4,("_spoolss_getform\n"));
4339         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4340         DEBUGADD(5,("Info level [%d]\n",          level));
4341
4342         numofforms = get_ntforms(&list);
4343         DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
4344
4345         if (numofforms == 0)
4346                 return ERROR_NO_MORE_ITEMS;
4347
4348         switch (level) {
4349         case 1:
4350
4351                 /* Check if the requested name is in the list of form structures */
4352                 for (i=0; i<numofforms; i++) {
4353
4354                         DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4355
4356                         if (strequal(form_name, list[i].name)) {
4357                                 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4358                                 fill_form_1(&form_1, &list[i]);
4359                                 break;
4360                         }
4361                 }
4362                 
4363                 safe_free(list);
4364
4365                 /* check the required size. */
4366
4367                 *needed=spoolss_size_form_1(&form_1);
4368                 
4369                 if (!alloc_buffer_size(buffer, buffer_size)){
4370                         return ERROR_INSUFFICIENT_BUFFER;
4371                 }
4372
4373                 if (*needed > offered) {
4374                         return ERROR_INSUFFICIENT_BUFFER;
4375                 }
4376
4377                 /* fill the buffer with the form structures */
4378                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4379                 new_smb_io_form_1("", buffer, &form_1, 0);
4380
4381                 return NT_STATUS_NO_PROBLEMO;
4382                         
4383         default:
4384                 safe_free(list);
4385                 return ERROR_INVALID_LEVEL;
4386         }
4387 }
4388
4389 /****************************************************************************
4390 ****************************************************************************/
4391 static void fill_port_1(PORT_INFO_1 *port, char *name)
4392 {
4393         init_unistr(&port->port_name, name);
4394 }
4395
4396 /****************************************************************************
4397 ****************************************************************************/
4398 static void fill_port_2(PORT_INFO_2 *port, char *name)
4399 {
4400         init_unistr(&port->port_name, name);
4401         init_unistr(&port->monitor_name, "Local Monitor");
4402         init_unistr(&port->description, "Local Port");
4403 #define PORT_TYPE_WRITE 1
4404         port->port_type=PORT_TYPE_WRITE;
4405         port->reserved=0x0;     
4406 }
4407
4408 /****************************************************************************
4409  enumports level 1.
4410 ****************************************************************************/
4411 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4412 {
4413         PORT_INFO_1 *ports=NULL;
4414         int i=0;
4415
4416         if (*lp_enumports_cmd()) {
4417                 pid_t local_pid = sys_getpid();
4418                 char *cmd = lp_enumports_cmd();
4419                 char *path;
4420                 char **qlines;
4421                 pstring tmp_file;
4422                 pstring command;
4423                 int numlines;
4424                 int ret;
4425
4426                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4427                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4428                 else
4429                         path = tmpdir();
4430
4431                 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4432                 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4433
4434                 unlink(tmp_file);
4435                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4436                 ret = smbrun(command, tmp_file, False);
4437                 DEBUG(10,("Returned [%d]\n", ret));
4438                 if (ret != 0) {
4439                         unlink(tmp_file);
4440                         /* Is this the best error to return here? */
4441                         return ERROR_ACCESS_DENIED;
4442                 }
4443
4444                 numlines = 0;
4445                 qlines = file_lines_load(tmp_file, &numlines);
4446                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4447                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4448                 unlink(tmp_file);
4449
4450                 if(numlines) {
4451                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4452                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4453                                 file_lines_free(qlines);
4454                                 return ERROR_NOT_ENOUGH_MEMORY;
4455                         }
4456
4457                         for (i=0; i<numlines; i++) {
4458                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4459                                 fill_port_1(&ports[i], qlines[i]);
4460                         }
4461
4462                         file_lines_free(qlines);
4463                 }
4464
4465                 *returned = numlines;
4466
4467         } else {
4468                 *returned = 1; /* Sole Samba port returned. */
4469
4470                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4471                         return ERROR_NOT_ENOUGH_MEMORY;
4472         
4473                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4474
4475                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4476         }
4477
4478         /* check the required size. */
4479         for (i=0; i<*returned; i++) {
4480                 DEBUGADD(6,("adding port [%d]'s size\n", i));
4481                 *needed += spoolss_size_port_info_1(&ports[i]);
4482         }
4483                 
4484         if (!alloc_buffer_size(buffer, *needed)) {
4485                 safe_free(ports);
4486                 return ERROR_INSUFFICIENT_BUFFER;
4487         }
4488
4489         /* fill the buffer with the ports structures */
4490         for (i=0; i<*returned; i++) {
4491                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4492                 new_smb_io_port_1("", buffer, &ports[i], 0);
4493         }
4494
4495         safe_free(ports);
4496
4497         if (*needed > offered) {
4498                 *returned=0;
4499                 return ERROR_INSUFFICIENT_BUFFER;
4500         }
4501         else
4502                 return NT_STATUS_NO_PROBLEMO;
4503 }
4504
4505 /****************************************************************************
4506  enumports level 2.
4507 ****************************************************************************/
4508
4509 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4510 {
4511         PORT_INFO_2 *ports=NULL;
4512         int i=0;
4513
4514         if (*lp_enumports_cmd()) {
4515                 pid_t local_pid = sys_getpid();
4516                 char *cmd = lp_enumports_cmd();
4517                 char *path;
4518                 char **qlines;
4519                 pstring tmp_file;
4520                 pstring command;
4521                 int numlines;
4522                 int ret;
4523
4524                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4525                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4526                 else
4527                         path = tmpdir();
4528
4529                 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4530                 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4531
4532                 unlink(tmp_file);
4533                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4534                 ret = smbrun(command, tmp_file, False);
4535                 DEBUGADD(10,("returned [%d]\n", ret));
4536                 if (ret != 0) {
4537                         unlink(tmp_file);
4538                         /* Is this the best error to return here? */
4539                         return ERROR_ACCESS_DENIED;
4540                 }
4541
4542                 numlines = 0;
4543                 qlines = file_lines_load(tmp_file, &numlines);
4544                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4545                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4546                 unlink(tmp_file);
4547
4548                 if(numlines) {
4549                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4550                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4551                                 file_lines_free(qlines);
4552                                 return ERROR_NOT_ENOUGH_MEMORY;
4553                         }
4554
4555                         for (i=0; i<numlines; i++) {
4556                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4557                                 fill_port_2(&(ports[i]), qlines[i]);
4558                         }
4559
4560                         file_lines_free(qlines);
4561                 }
4562
4563                 *returned = numlines;
4564
4565         } else {
4566
4567                 *returned = 1;
4568
4569                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4570                         return ERROR_NOT_ENOUGH_MEMORY;
4571         
4572                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4573
4574                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4575         }
4576
4577         /* check the required size. */
4578         for (i=0; i<*returned; i++) {
4579                 DEBUGADD(6,("adding port [%d]'s size\n", i));
4580                 *needed += spoolss_size_port_info_2(&ports[i]);
4581         }
4582                 
4583         if (!alloc_buffer_size(buffer, *needed)) {
4584                 safe_free(ports);
4585                 return ERROR_INSUFFICIENT_BUFFER;
4586         }
4587
4588         /* fill the buffer with the ports structures */
4589         for (i=0; i<*returned; i++) {
4590                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4591                 new_smb_io_port_2("", buffer, &ports[i], 0);
4592         }
4593
4594         safe_free(ports);
4595
4596         if (*needed > offered) {
4597                 *returned=0;
4598                 return ERROR_INSUFFICIENT_BUFFER;
4599         }
4600         else
4601                 return NT_STATUS_NO_PROBLEMO;
4602 }
4603
4604 /****************************************************************************
4605  enumports.
4606 ****************************************************************************/
4607 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level, 
4608                            NEW_BUFFER *buffer, uint32 offered, 
4609                            uint32 *needed, uint32 *returned)
4610 {
4611         DEBUG(4,("_spoolss_enumports\n"));
4612         
4613         *returned=0;
4614         *needed=0;
4615         
4616         switch (level) {
4617         case 1:
4618                 return enumports_level_1(buffer, offered, needed, returned);
4619         case 2:
4620                 return enumports_level_2(buffer, offered, needed, returned);
4621         default:
4622                 return ERROR_INVALID_LEVEL;
4623         }
4624 }
4625
4626 /****************************************************************************
4627 ****************************************************************************/
4628 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4629                                 const SPOOL_PRINTER_INFO_LEVEL *info,
4630                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4631                                 uint32 user_switch, const SPOOL_USER_CTR *user,
4632                                 POLICY_HND *handle)
4633 {
4634         NT_PRINTER_INFO_LEVEL *printer = NULL;
4635         fstring name;
4636         int snum;
4637
4638         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4639                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4640                 return ERROR_NOT_ENOUGH_MEMORY;
4641         }
4642
4643         ZERO_STRUCTP(printer);
4644
4645         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4646         convert_printer_info(info, printer, 2);
4647
4648         if (*lp_addprinter_cmd() )
4649                 if ( !add_printer_hook(printer) ) {
4650                         free_a_printer(&printer,2);
4651                         return ERROR_ACCESS_DENIED;
4652         }
4653
4654         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4655              printer->info_2->sharename);
4656
4657         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4658                 free_a_printer(&printer,2);
4659                 return ERROR_ACCESS_DENIED;
4660         }
4661
4662         /* you must be a printer admin to add a new printer */
4663         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4664                 free_a_printer(&printer,2);
4665                 return ERROR_ACCESS_DENIED;             
4666         }
4667         
4668         /*
4669          * Do sanity check on the requested changes for Samba.
4670          */
4671
4672         if (!check_printer_ok(printer->info_2, snum)) {
4673                 free_a_printer(&printer,2);
4674                 return ERROR_INVALID_PARAMETER;
4675         }
4676
4677         /* write the ASCII on disk */
4678         if (add_a_printer(*printer, 2) != 0) {
4679                 free_a_printer(&printer,2);
4680                 return ERROR_ACCESS_DENIED;
4681         }
4682
4683         if (!open_printer_hnd(handle, name)) {
4684                 /* Handle open failed - remove addition. */
4685                 del_a_printer(printer->info_2->sharename);
4686                 free_a_printer(&printer,2);
4687                 return ERROR_ACCESS_DENIED;
4688         }
4689
4690         free_a_printer(&printer,2);
4691
4692         srv_spoolss_sendnotify(handle);
4693
4694         return NT_STATUS_NO_PROBLEMO;
4695 }
4696
4697 /****************************************************************************
4698 ****************************************************************************/
4699 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4700                                 const SPOOL_PRINTER_INFO_LEVEL *info,
4701                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4702                                 uint32 user_switch, const SPOOL_USER_CTR *user,
4703                                 POLICY_HND *handle)
4704 {
4705         switch (level) {
4706                 case 1:
4707                         /* we don't handle yet */
4708                         /* but I know what to do ... */
4709                         return ERROR_INVALID_LEVEL;
4710                 case 2:
4711                         return spoolss_addprinterex_level_2(uni_srv_name, info, 
4712                                                             unk0, unk1, unk2, unk3,
4713                                                             user_switch, user, handle);
4714                 default:
4715                         return ERROR_INVALID_LEVEL;
4716         }
4717 }
4718
4719 /****************************************************************************
4720 ****************************************************************************/
4721 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4722                                  uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4723 {
4724         uint32 err = NT_STATUS_NO_PROBLEMO;
4725         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4726         struct current_user user;
4727         
4728         ZERO_STRUCT(driver);
4729
4730         get_current_user(&user, p);     
4731         
4732         convert_printer_driver_info(info, &driver, level);
4733
4734         DEBUG(5,("Cleaning driver's information\n"));
4735         if ((err = clean_up_driver_struct(driver, level)) != NT_STATUS_NO_PROBLEMO )
4736                 goto done;
4737
4738         DEBUG(5,("Moving driver to final destination\n"));
4739         if(!move_driver_to_download_area(driver, level, &user, &err)) {
4740                 if (err == 0)
4741                         err = ERROR_ACCESS_DENIED;
4742                 goto done;
4743         }
4744
4745         if (add_a_printer_driver(driver, level)!=0) {
4746                 err = ERROR_ACCESS_DENIED;
4747                 goto done;
4748         }
4749
4750  done:
4751         free_a_printer_driver(driver, level);
4752         return err;
4753 }
4754
4755 /****************************************************************************
4756 ****************************************************************************/
4757 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4758 {
4759         init_unistr(&info->name, name);
4760 }
4761
4762 /****************************************************************************
4763 ****************************************************************************/
4764 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4765 {
4766         pstring path;
4767         pstring long_archi;
4768         pstring short_archi;
4769         DRIVER_DIRECTORY_1 *info=NULL;
4770
4771         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4772
4773         if (get_short_archi(short_archi, long_archi)==FALSE)
4774                 return ERROR_INVALID_ENVIRONMENT;
4775
4776         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4777                 return ERROR_NOT_ENOUGH_MEMORY;
4778
4779         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4780
4781         DEBUG(4,("printer driver directory: [%s]\n", path));
4782
4783         fill_driverdir_1(info, path);
4784         
4785         *needed += spoolss_size_driverdir_info_1(info);
4786
4787         if (!alloc_buffer_size(buffer, *needed)) {
4788                 safe_free(info);
4789                 return ERROR_INSUFFICIENT_BUFFER;
4790         }
4791
4792         new_smb_io_driverdir_1("", buffer, info, 0);
4793
4794         safe_free(info);
4795         
4796         if (*needed > offered)
4797                 return ERROR_INSUFFICIENT_BUFFER;
4798         else
4799                 return NT_STATUS_NO_PROBLEMO;
4800 }
4801
4802 /****************************************************************************
4803 ****************************************************************************/
4804 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4805                                         NEW_BUFFER *buffer, uint32 offered, 
4806                                         uint32 *needed)
4807 {
4808         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4809
4810         *needed=0;
4811
4812         switch(level) {
4813         case 1:
4814                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4815         default:
4816                 return ERROR_INVALID_LEVEL;
4817         }
4818 }
4819         
4820 /****************************************************************************
4821 ****************************************************************************/
4822 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4823                                 uint32 in_value_len, uint32 in_data_len,
4824                                 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4825                                 uint32 *out_type,
4826                                 uint32 *out_max_data_len, uint8  **data_out, uint32 *out_data_len)
4827 {
4828         NT_PRINTER_INFO_LEVEL *printer = NULL;
4829         
4830         fstring value;
4831         
4832         uint32 param_index;
4833         uint32 biggest_valuesize;
4834         uint32 biggest_datasize;
4835         uint32 data_len;
4836         Printer_entry *Printer = find_printer_index_by_hnd(handle);
4837         int snum;
4838         uint8 *data=NULL;
4839         uint32 type;
4840
4841         ZERO_STRUCT(printer);
4842         
4843         *out_max_value_len=0;
4844         *out_value=NULL;
4845         *out_value_len=0;
4846
4847         *out_type=0;
4848
4849         *out_max_data_len=0;
4850         *data_out=NULL;
4851         *out_data_len=0;
4852
4853         DEBUG(5,("spoolss_enumprinterdata\n"));
4854
4855         if (!OPEN_HANDLE(Printer)) {
4856                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4857                 return ERROR_INVALID_HANDLE;
4858         }
4859
4860         if (!get_printer_snum(handle, &snum))
4861                 return ERROR_INVALID_HANDLE;
4862         
4863         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
4864                 return ERROR_INVALID_HANDLE;
4865
4866         /* 
4867          * The NT machine wants to know the biggest size of value and data
4868          *
4869          * cf: MSDN EnumPrinterData remark section
4870          */
4871         if ( (in_value_len==0) && (in_data_len==0) ) {
4872                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
4873
4874 #if 0
4875                 /*
4876                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
4877                  * if this parameter size doesn't exist.
4878                  * Ok - my opinion here is that the client is not asking for the greatest
4879                  * possible size of all the parameters, but is asking specifically for the size needed
4880                  * for this specific parameter. In that case we can remove the loop below and
4881                  * simplify this lookup code considerably. JF - comments welcome. JRA.
4882                  */
4883
4884                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4885                         safe_free(data);
4886                         free_a_printer(&printer, 2);
4887                         return ERROR_NO_MORE_ITEMS;
4888                 }
4889 #endif
4890
4891                 safe_free(data);
4892                 data = NULL;
4893
4894                 param_index=0;
4895                 biggest_valuesize=0;
4896                 biggest_datasize=0;
4897                 
4898                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
4899                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
4900                         if (data_len > biggest_datasize) biggest_datasize=data_len;
4901
4902                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
4903
4904                         safe_free(data);
4905                         data = NULL;
4906                         param_index++;
4907                 }
4908
4909                 /*
4910                  * I think this is correct, it doesn't break APW and
4911                  * allows Gerald's Win32 test programs to work correctly,
4912                  * but may need altering.... JRA.
4913                  */
4914
4915                 if (param_index == 0) {
4916                         /* No parameters found. */
4917                         free_a_printer(&printer, 2);
4918                         return ERROR_NO_MORE_ITEMS;
4919                 }
4920
4921                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
4922                 *out_value_len=2*(1+biggest_valuesize);
4923                 *out_data_len=biggest_datasize;
4924
4925                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
4926
4927                 free_a_printer(&printer, 2);
4928                 return NT_STATUS_NO_PROBLEMO;
4929         }
4930         
4931         /* 
4932          * the value len is wrong in NT sp3
4933          * that's the number of bytes not the number of unicode chars
4934          */
4935
4936         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4937                 safe_free(data);
4938                 free_a_printer(&printer, 2);
4939                 return ERROR_NO_MORE_ITEMS;
4940         }
4941
4942         free_a_printer(&printer, 2);
4943
4944         /* 
4945          * the value is:
4946          * - counted in bytes in the request
4947          * - counted in UNICODE chars in the max reply
4948          * - counted in bytes in the real size
4949          *
4950          * take a pause *before* coding not *during* coding
4951          */
4952          
4953         *out_max_value_len=(in_value_len/sizeof(uint16));
4954         if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
4955                 safe_free(data);
4956                 return ERROR_NOT_ENOUGH_MEMORY;
4957         }
4958         
4959         ZERO_STRUCTP(*out_value);
4960         *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
4961
4962         *out_type=type;
4963
4964         /* the data is counted in bytes */
4965         *out_max_data_len=in_data_len;
4966         if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
4967                 safe_free(data);
4968                 return ERROR_NOT_ENOUGH_MEMORY;
4969         }
4970         
4971         memset(*data_out,'\0',in_data_len);
4972         memcpy(*data_out, data, (size_t)data_len);
4973         *out_data_len=data_len;
4974
4975         safe_free(data);
4976         
4977         return NT_STATUS_NO_PROBLEMO;
4978 }
4979
4980 /****************************************************************************
4981 ****************************************************************************/
4982 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
4983                                 const UNISTR2 *value,
4984                                 uint32 type,
4985                                 uint32 max_len,
4986                                 const uint8 *data,
4987                                 uint32 real_len,
4988                                 uint32 numeric_data)
4989 {
4990         NT_PRINTER_INFO_LEVEL *printer = NULL;
4991         NT_PRINTER_PARAM *param = NULL;         
4992         int snum=0;
4993         uint32 status = 0x0;
4994         Printer_entry *Printer=find_printer_index_by_hnd(handle);
4995         
4996         DEBUG(5,("spoolss_setprinterdata\n"));
4997
4998         
4999         if (!OPEN_HANDLE(Printer)) {
5000                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5001                 return ERROR_INVALID_HANDLE;
5002         }
5003
5004         if (!get_printer_snum(handle, &snum))
5005                 return ERROR_INVALID_HANDLE;
5006
5007         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5008                 DEBUG(3, ("security descriptor change denied by existing "
5009                           "security descriptor\n"));
5010                 return ERROR_ACCESS_DENIED;
5011         }
5012
5013         status = get_a_printer(&printer, 2, lp_servicename(snum));
5014         if (status != 0x0)
5015                 return ERROR_INVALID_NAME;
5016
5017         convert_specific_param(&param, value , type, data, real_len);
5018         unlink_specific_param_if_exist(printer->info_2, param);
5019         
5020         if (!add_a_specific_param(printer->info_2, param))
5021                 status = ERROR_INVALID_PARAMETER;
5022         else
5023                 status = mod_a_printer(*printer, 2);
5024
5025         free_a_printer(&printer, 2);
5026         return status;
5027 }
5028
5029 /****************************************************************************
5030 ****************************************************************************/
5031 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5032 {
5033         NT_PRINTER_INFO_LEVEL *printer = NULL;
5034         NT_PRINTER_PARAM param;
5035         int snum=0;
5036         uint32 status = 0x0;
5037         Printer_entry *Printer=find_printer_index_by_hnd(handle);
5038         
5039         DEBUG(5,("spoolss_deleteprinterdata\n"));
5040         
5041         if (!OPEN_HANDLE(Printer)) {
5042                 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5043                 return ERROR_INVALID_HANDLE;
5044         }
5045
5046         if (!get_printer_snum(handle, &snum))
5047                 return ERROR_INVALID_HANDLE;
5048
5049         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5050                 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5051                           "security descriptor\n"));
5052                 return ERROR_ACCESS_DENIED;
5053         }
5054
5055         status = get_a_printer(&printer, 2, lp_servicename(snum));
5056         if (status != 0x0)
5057                 return ERROR_INVALID_NAME;
5058
5059         ZERO_STRUCTP(&param);
5060         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5061
5062         if(!unlink_specific_param_if_exist(printer->info_2, &param))
5063                 status = ERROR_INVALID_PARAMETER;
5064         else
5065                 status = mod_a_printer(*printer, 2);
5066
5067         free_a_printer(&printer, 2);
5068         return status;
5069 }
5070
5071 /****************************************************************************
5072 ****************************************************************************/
5073 uint32 _spoolss_addform( POLICY_HND *handle,
5074                                 uint32 level,
5075                                 const FORM *form)
5076 {
5077         int count=0;
5078         nt_forms_struct *list=NULL;
5079         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5080
5081         DEBUG(5,("spoolss_addform\n"));
5082
5083         if (!OPEN_HANDLE(Printer)) {
5084                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5085                 return ERROR_INVALID_HANDLE;
5086         }
5087
5088         count=get_ntforms(&list);
5089         if(!add_a_form(&list, form, &count))
5090                 return ERROR_NOT_ENOUGH_MEMORY;
5091         write_ntforms(&list, count);
5092
5093         safe_free(list);
5094
5095         return 0x0;
5096 }
5097
5098 /****************************************************************************
5099 ****************************************************************************/
5100 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5101 {
5102         int count=0;
5103         uint32 ret = 0;
5104         nt_forms_struct *list=NULL;
5105         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5106
5107         DEBUG(5,("spoolss_deleteform\n"));
5108
5109         if (!OPEN_HANDLE(Printer)) {
5110                 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5111                 return ERROR_INVALID_HANDLE;
5112         }
5113
5114         count = get_ntforms(&list);
5115         if(!delete_a_form(&list, form_name, &count, &ret))
5116                 return ERROR_INVALID_PARAMETER;
5117
5118         safe_free(list);
5119
5120         return ret;
5121 }
5122
5123 /****************************************************************************
5124 ****************************************************************************/
5125 uint32 _spoolss_setform( POLICY_HND *handle,
5126                                 const UNISTR2 *uni_name,
5127                                 uint32 level,
5128                                 const FORM *form)
5129 {
5130         int count=0;
5131         nt_forms_struct *list=NULL;
5132         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5133
5134         DEBUG(5,("spoolss_setform\n"));
5135
5136         if (!OPEN_HANDLE(Printer)) {
5137                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5138                 return ERROR_INVALID_HANDLE;
5139         }
5140         count=get_ntforms(&list);
5141         update_a_form(&list, form, count);
5142         write_ntforms(&list, count);
5143
5144         safe_free(list);
5145
5146         return 0x0;
5147 }
5148
5149 /****************************************************************************
5150  enumprintprocessors level 1.
5151 ****************************************************************************/
5152 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5153 {
5154         PRINTPROCESSOR_1 *info_1=NULL;
5155         
5156         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5157                 return ERROR_NOT_ENOUGH_MEMORY;
5158
5159         (*returned) = 0x1;
5160         
5161         init_unistr(&info_1->name, "winprint");
5162
5163         *needed += spoolss_size_printprocessor_info_1(info_1);
5164
5165         if (!alloc_buffer_size(buffer, *needed))
5166                 return ERROR_INSUFFICIENT_BUFFER;
5167
5168         smb_io_printprocessor_info_1("", buffer, info_1, 0);
5169
5170         safe_free(info_1);
5171
5172         if (*needed > offered) {
5173                 *returned=0;
5174                 return ERROR_INSUFFICIENT_BUFFER;
5175         }
5176         else
5177                 return NT_STATUS_NO_PROBLEMO;
5178 }
5179
5180 /****************************************************************************
5181 ****************************************************************************/
5182 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5183                                     NEW_BUFFER *buffer, uint32 offered, 
5184                                     uint32 *needed, uint32 *returned)
5185 {
5186         DEBUG(5,("spoolss_enumprintprocessors\n"));
5187
5188         /* 
5189          * Enumerate the print processors ...
5190          *
5191          * Just reply with "winprint", to keep NT happy
5192          * and I can use my nice printer checker.
5193          */
5194         
5195         *returned=0;
5196         *needed=0;
5197         
5198         switch (level) {
5199         case 1:
5200                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5201         default:
5202                 return ERROR_INVALID_LEVEL;
5203         }
5204 }
5205
5206 /****************************************************************************
5207  enumprintprocdatatypes level 1.
5208 ****************************************************************************/
5209 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5210 {
5211         PRINTPROCDATATYPE_1 *info_1=NULL;
5212         
5213         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5214                 return ERROR_NOT_ENOUGH_MEMORY;
5215
5216         (*returned) = 0x1;
5217         
5218         init_unistr(&info_1->name, "RAW");
5219
5220         *needed += spoolss_size_printprocdatatype_info_1(info_1);
5221
5222         if (!alloc_buffer_size(buffer, *needed))
5223                 return ERROR_INSUFFICIENT_BUFFER;
5224
5225         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5226
5227         safe_free(info_1);
5228
5229         if (*needed > offered) {
5230                 *returned=0;
5231                 return ERROR_INSUFFICIENT_BUFFER;
5232         }
5233         else
5234                 return NT_STATUS_NO_PROBLEMO;
5235 }
5236
5237 /****************************************************************************
5238 ****************************************************************************/
5239 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5240                                         NEW_BUFFER *buffer, uint32 offered, 
5241                                         uint32 *needed, uint32 *returned)
5242 {
5243         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5244         
5245         *returned=0;
5246         *needed=0;
5247         
5248         switch (level) {
5249         case 1:
5250                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5251         default:
5252                 return ERROR_INVALID_LEVEL;
5253         }
5254 }
5255
5256 /****************************************************************************
5257  enumprintmonitors level 1.
5258 ****************************************************************************/
5259 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5260 {
5261         PRINTMONITOR_1 *info_1=NULL;
5262         
5263         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5264                 return ERROR_NOT_ENOUGH_MEMORY;
5265
5266         (*returned) = 0x1;
5267         
5268         init_unistr(&info_1->name, "Local Port");
5269
5270         *needed += spoolss_size_printmonitor_info_1(info_1);
5271
5272         if (!alloc_buffer_size(buffer, *needed))
5273                 return ERROR_INSUFFICIENT_BUFFER;
5274
5275         smb_io_printmonitor_info_1("", buffer, info_1, 0);
5276
5277         safe_free(info_1);
5278
5279         if (*needed > offered) {
5280                 *returned=0;
5281                 return ERROR_INSUFFICIENT_BUFFER;
5282         }
5283         else
5284                 return NT_STATUS_NO_PROBLEMO;
5285 }
5286
5287 /****************************************************************************
5288  enumprintmonitors level 2.
5289 ****************************************************************************/
5290 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5291 {
5292         PRINTMONITOR_2 *info_2=NULL;
5293         
5294         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5295                 return ERROR_NOT_ENOUGH_MEMORY;
5296
5297         (*returned) = 0x1;
5298         
5299         init_unistr(&info_2->name, "Local Port");
5300         init_unistr(&info_2->environment, "Windows NT X86");
5301         init_unistr(&info_2->dll_name, "localmon.dll");
5302
5303         *needed += spoolss_size_printmonitor_info_2(info_2);
5304
5305         if (!alloc_buffer_size(buffer, *needed))
5306                 return ERROR_INSUFFICIENT_BUFFER;
5307
5308         smb_io_printmonitor_info_2("", buffer, info_2, 0);
5309
5310         safe_free(info_2);
5311
5312         if (*needed > offered) {
5313                 *returned=0;
5314                 return ERROR_INSUFFICIENT_BUFFER;
5315         }
5316         else
5317                 return NT_STATUS_NO_PROBLEMO;
5318 }
5319
5320 /****************************************************************************
5321 ****************************************************************************/
5322 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5323                                     NEW_BUFFER *buffer, uint32 offered, 
5324                                     uint32 *needed, uint32 *returned)
5325 {
5326         DEBUG(5,("spoolss_enumprintmonitors\n"));
5327
5328         /* 
5329          * Enumerate the print monitors ...
5330          *
5331          * Just reply with "Local Port", to keep NT happy
5332          * and I can use my nice printer checker.
5333          */
5334         
5335         *returned=0;
5336         *needed=0;
5337         
5338         switch (level) {
5339         case 1:
5340                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5341         case 2:
5342                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5343         default:
5344                 return ERROR_INVALID_LEVEL;
5345         }
5346 }
5347
5348 /****************************************************************************
5349 ****************************************************************************/
5350 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5351 {
5352         int i=0;
5353         BOOL found=False;
5354         JOB_INFO_1 *info_1=NULL;
5355
5356         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5357
5358         if (info_1 == NULL) {
5359                 safe_free(queue);
5360                 return ERROR_NOT_ENOUGH_MEMORY;
5361         }
5362                 
5363         for (i=0; i<count && found==False; i++) {
5364                 if (queue[i].job==(int)jobid)
5365                         found=True;
5366         }
5367         
5368         if (found==False) {
5369                 safe_free(queue);
5370                 safe_free(info_1);
5371                 /* I shoud reply something else ... I can't find the good one */
5372                 return NT_STATUS_NO_PROBLEMO;
5373         }
5374         
5375         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5376         
5377         safe_free(queue);
5378         
5379         *needed += spoolss_size_job_info_1(info_1);
5380
5381         if (!alloc_buffer_size(buffer, *needed)) {
5382                 safe_free(info_1);
5383                 return ERROR_INSUFFICIENT_BUFFER;
5384         }
5385
5386         new_smb_io_job_info_1("", buffer, info_1, 0);
5387
5388         safe_free(info_1);
5389
5390         if (*needed > offered)
5391                 return ERROR_INSUFFICIENT_BUFFER;
5392         else
5393                 return NT_STATUS_NO_PROBLEMO;
5394 }
5395
5396
5397 /****************************************************************************
5398 ****************************************************************************/
5399 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5400 {
5401         int i=0;
5402         BOOL found=False;
5403         JOB_INFO_2 *info_2;
5404         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5405
5406         ZERO_STRUCTP(info_2);
5407
5408         if (info_2 == NULL) {
5409                 safe_free(queue);
5410                 return ERROR_NOT_ENOUGH_MEMORY;
5411         }
5412
5413         for (i=0; i<count && found==False; i++) {
5414                 if (queue[i].job==(int)jobid)
5415                         found=True;
5416         }
5417         
5418         if (found==False) {
5419                 safe_free(queue);
5420                 safe_free(info_2);
5421                 /* I shoud reply something else ... I can't find the good one */
5422                 return NT_STATUS_NO_PROBLEMO;
5423         }
5424         
5425         fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5426         
5427         safe_free(queue);
5428         
5429         *needed += spoolss_size_job_info_2(info_2);
5430
5431         if (!alloc_buffer_size(buffer, *needed)) {
5432                 safe_free(info_2);
5433                 return ERROR_INSUFFICIENT_BUFFER;
5434         }
5435
5436         new_smb_io_job_info_2("", buffer, info_2, 0);
5437
5438         free_dev_mode(info_2->devmode);
5439         safe_free(info_2);
5440
5441         if (*needed > offered)
5442                 return ERROR_INSUFFICIENT_BUFFER;
5443         else
5444                 return NT_STATUS_NO_PROBLEMO;
5445 }
5446
5447 /****************************************************************************
5448 ****************************************************************************/
5449 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5450                         NEW_BUFFER *buffer, uint32 offered, 
5451                         uint32 *needed)
5452 {
5453         int snum;
5454         int count;
5455         print_queue_struct *queue=NULL;
5456         print_status_struct prt_status;
5457
5458         DEBUG(5,("spoolss_getjob\n"));
5459         
5460         memset(&prt_status, 0, sizeof(prt_status));
5461
5462         *needed=0;
5463         
5464         if (!get_printer_snum(handle, &snum))
5465                 return ERROR_INVALID_HANDLE;
5466         
5467         count = print_queue_status(snum, &queue, &prt_status);
5468         
5469         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5470                      count, prt_status.status, prt_status.message));
5471                 
5472         switch (level) {
5473         case 1:
5474                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5475         case 2:
5476                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5477         default:
5478                 safe_free(queue);
5479                 return ERROR_INVALID_LEVEL;
5480         }
5481 }
5482 #undef OLD_NTDOMAIN