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