74cc19eee1579774ff8d9c3f94242e56f508e4aa
[samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 #define OLD_NTDOMAIN 1
2 /*
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-2000,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8  *  Copyright (C) Jean Fran├žois Micouleau      1998-2000.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #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(conn_tdb_ctx(), 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         uint32 result = NT_STATUS_NO_PROBLEMO;
659         SEC_DESC_BUF *sec_desc = NULL;
660         uint32 acc_granted, status;
661         fstring name;
662         extern struct current_user current_user;
663         
664         if (printername == NULL) {
665                 result = ERROR_INVALID_PRINTER_NAME;
666                 goto done;
667         }
668
669         /* some sanity check because you can open a printer or a print server */
670         /* aka: \\server\printer or \\server */
671         unistr2_to_ascii(name, printername, sizeof(name)-1);
672
673         DEBUGADD(3,("checking name: %s\n",name));
674
675         if (!open_printer_hnd(handle, name)) {
676                 result = ERROR_INVALID_PRINTER_NAME;
677                 goto done;
678         }
679         
680 /*
681         if (printer_default->datatype_ptr != NULL)
682         {
683                 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
684                 set_printer_hnd_datatype(handle, datatype);
685         }
686         else
687                 set_printer_hnd_datatype(handle, "");
688 */
689         
690         if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
691                 close_printer_handle(handle);
692                 result = ERROR_ACCESS_DENIED;
693                 goto done;
694         }
695                 
696         /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
697            client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
698            Then both Win2k and WinNT clients try an OpenPrinterEx with
699            SERVER_ALL_ACCESS, which we force to fail. Then they try
700            OpenPrinterEx with SERVER_READ which we allow. This lets the
701            client view printer folder, but does not show the MSAPW.
702
703            Note: this test needs code to check access rights here too. Jeremy
704            could you look at this? */
705
706         if (handle_is_printserver(handle) &&
707             !lp_ms_add_printer_wizard()) {
708                 if (printer_default->access_required == 0) {
709                         goto done;
710                 }
711                 else if (printer_default->access_required != (SERVER_READ)) {
712                         close_printer_handle(handle);
713                         result = ERROR_ACCESS_DENIED;
714                         goto done;
715                 }
716         }
717
718         /* NT doesn't let us connect to a printer if the connecting user
719            doesn't have print permission.  If no security descriptor just
720            return OK. */
721
722         if (!nt_printing_getsec(name, &sec_desc)) {
723                 goto done;
724         }
725         
726         /* Yuck - we should use the pipe_user rather than current_user but
727            it doesn't seem to be filled in correctly. )-: */
728
729         map_printer_permissions(sec_desc->sec);
730
731         if (!se_access_check(sec_desc->sec, &current_user, PRINTER_ACCESS_USE,
732                              &acc_granted, &status)) {
733                 DEBUG(3, ("access DENIED for printer open\n"));
734                 close_printer_handle(handle);
735                 result = ERROR_ACCESS_DENIED;
736                 goto done;
737         }
738
739  done:
740         free_sec_desc_buf(&sec_desc);
741
742         return result;
743 }
744
745 /****************************************************************************
746 ****************************************************************************/
747 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
748                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
749 {
750         switch (level) {
751                 case 2:
752                         uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
753                         break;
754                 default:
755                         break;
756         }
757
758         return True;
759 }
760
761 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
762                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
763 {
764         switch (level) {
765                 case 3:
766                         printer->info_3=NULL;
767                         uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
768                         break;
769                 case 6:
770                         printer->info_6=NULL;
771                         uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
772                         break;
773                 default:
774                         break;
775         }
776
777         return True;
778 }
779
780 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
781 {
782         unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
783         unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
784
785         nt_devmode->specversion=devmode->specversion;
786         nt_devmode->driverversion=devmode->driverversion;
787         nt_devmode->size=devmode->size;
788         nt_devmode->driverextra=devmode->driverextra;
789         nt_devmode->fields=devmode->fields;
790         nt_devmode->orientation=devmode->orientation;
791         nt_devmode->papersize=devmode->papersize;
792         nt_devmode->paperlength=devmode->paperlength;
793         nt_devmode->paperwidth=devmode->paperwidth;
794         nt_devmode->scale=devmode->scale;
795         nt_devmode->copies=devmode->copies;
796         nt_devmode->defaultsource=devmode->defaultsource;
797         nt_devmode->printquality=devmode->printquality;
798         nt_devmode->color=devmode->color;
799         nt_devmode->duplex=devmode->duplex;
800         nt_devmode->yresolution=devmode->yresolution;
801         nt_devmode->ttoption=devmode->ttoption;
802         nt_devmode->collate=devmode->collate;
803
804         nt_devmode->logpixels=devmode->logpixels;
805         nt_devmode->bitsperpel=devmode->bitsperpel;
806         nt_devmode->pelswidth=devmode->pelswidth;
807         nt_devmode->pelsheight=devmode->pelsheight;
808         nt_devmode->displayflags=devmode->displayflags;
809         nt_devmode->displayfrequency=devmode->displayfrequency;
810         nt_devmode->icmmethod=devmode->icmmethod;
811         nt_devmode->icmintent=devmode->icmintent;
812         nt_devmode->mediatype=devmode->mediatype;
813         nt_devmode->dithertype=devmode->dithertype;
814         nt_devmode->reserved1=devmode->reserved1;
815         nt_devmode->reserved2=devmode->reserved2;
816         nt_devmode->panningwidth=devmode->panningwidth;
817         nt_devmode->panningheight=devmode->panningheight;
818
819         safe_free(nt_devmode->private);
820         if (nt_devmode->driverextra != 0) {
821                 /* if we had a previous private delete it and make a new one */
822                 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
823                         return False;
824                 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
825         }
826         else {
827                 nt_devmode->private = NULL;
828         }
829
830         return True;
831 }
832
833 /********************************************************************
834  * api_spoolss_closeprinter
835  ********************************************************************/
836 uint32 _spoolss_closeprinter(POLICY_HND *handle)
837 {
838         Printer_entry *Printer=find_printer_index_by_hnd(handle);
839
840         if (Printer && Printer->document_started)
841                 _spoolss_enddocprinter(handle);          /* print job was not closed */
842
843         if (!close_printer_handle(handle))
844                 return ERROR_INVALID_HANDLE;    
845                 
846         return NT_STATUS_NO_PROBLEMO;
847 }
848
849 /********************************************************************
850  * api_spoolss_deleteprinter
851  ********************************************************************/
852 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
853 {
854         Printer_entry *Printer=find_printer_index_by_hnd(handle);
855
856         if (Printer && Printer->document_started)
857                 _spoolss_enddocprinter(handle);          /* print job was not closed */
858
859         if (!delete_printer_handle(handle))
860                 return ERROR_INVALID_HANDLE;    
861
862         srv_spoolss_sendnotify(handle);
863                 
864         return NT_STATUS_NO_PROBLEMO;
865 }
866
867 /********************************************************************
868  GetPrinterData on a printer server Handle.
869 ********************************************************************/
870 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
871 {               
872         int i;
873         
874         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
875                 
876         if (!strcmp(value, "BeepEnabled")) {
877                 *type = 0x4;
878                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
879                         return False;
880                 SIVAL(*data, 0, 0x01);
881                 *needed = 0x4;                  
882                 return True;
883         }
884
885         if (!strcmp(value, "EventLog")) {
886                 *type = 0x4;
887                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
888                         return False;
889                 SIVAL(*data, 0, 0x1B);
890                 *needed = 0x4;                  
891                 return True;
892         }
893
894         if (!strcmp(value, "NetPopup")) {
895                 *type = 0x4;
896                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
897                         return False;
898                 SIVAL(*data, 0, 0x01);
899                 *needed = 0x4;
900                 return True;
901         }
902
903         if (!strcmp(value, "MajorVersion")) {
904                 *type = 0x4;
905                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
906                         return False;
907                 SIVAL(*data, 0, 0x02);
908                 *needed = 0x4;
909                 return True;
910         }
911
912         if (!strcmp(value, "DefaultSpoolDirectory")) {
913                 pstring string="You are using a Samba server";
914                 *type = 0x1;                    
915                 *needed = 2*(strlen(string)+1);         
916                 if((*data  = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
917                         return False;
918                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
919                 
920                 /* it's done by hand ready to go on the wire */
921                 for (i=0; i<strlen(string); i++) {
922                         (*data)[2*i]=string[i];
923                         (*data)[2*i+1]='\0';
924                 }                       
925                 return True;
926         }
927
928         if (!strcmp(value, "Architecture")) {                   
929                 pstring string="Windows NT x86";
930                 *type = 0x1;                    
931                 *needed = 2*(strlen(string)+1); 
932                 if((*data  = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
933                         return False;
934                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
935                 for (i=0; i<strlen(string); i++) {
936                         (*data)[2*i]=string[i];
937                         (*data)[2*i+1]='\0';
938                 }                       
939                 return True;
940         }
941         
942         return False;
943 }
944
945 /********************************************************************
946  GetPrinterData on a printer Handle.
947 ********************************************************************/
948 static BOOL getprinterdata_printer(POLICY_HND *handle,
949                                 fstring value, uint32 *type,
950                                 uint8 **data, uint32 *needed, uint32 in_size )
951 {
952         NT_PRINTER_INFO_LEVEL *printer = NULL;
953         int snum=0;
954         uint8 *idata=NULL;
955         uint32 len;
956         Printer_entry *Printer = find_printer_index_by_hnd(handle);
957         
958         DEBUG(5,("getprinterdata_printer\n"));
959
960         if (!OPEN_HANDLE(Printer)) {
961                 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
962                 return False;
963         }
964
965         if(!get_printer_snum(handle, &snum))
966                 return False;
967
968         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
969                 return False;
970
971         if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
972                 free_a_printer(&printer, 2);
973                 return False;
974         }
975
976         free_a_printer(&printer, 2);
977
978         DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
979
980         if (in_size) {
981                 if((*data  = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
982                         return False;
983                 }
984
985                 memset(*data, 0, in_size *sizeof(uint8));
986                 /* copy the min(in_size, len) */
987                 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
988         } else {
989                 *data = NULL;
990         }
991
992         *needed = len;
993         
994         DEBUG(5,("getprinterdata_printer:copy done\n"));
995                         
996         safe_free(idata);
997         
998         return True;
999 }       
1000
1001 /********************************************************************
1002  * spoolss_getprinterdata
1003  ********************************************************************/
1004 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
1005                                 uint32 in_size,
1006                                 uint32 *type,
1007                                 uint32 *out_size,
1008                                 uint8 **data,
1009                                 uint32 *needed)
1010 {
1011         fstring value;
1012         BOOL found=False;
1013         Printer_entry *Printer = find_printer_index_by_hnd(handle);
1014         
1015         /*
1016          * Reminder: when it's a string, the length is in BYTES
1017          * even if UNICODE is negociated.
1018          *
1019          * JFM, 4/19/1999
1020          */
1021
1022         *out_size=in_size;
1023
1024         /* in case of problem, return some default values */
1025         *needed=0;
1026         *type=0;
1027         
1028         DEBUG(4,("_spoolss_getprinterdata\n"));
1029         
1030         if (!OPEN_HANDLE(Printer)) {
1031                 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1032                         return ERROR_NOT_ENOUGH_MEMORY;
1033                 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1034                 return ERROR_INVALID_HANDLE;
1035         }
1036         
1037         unistr2_to_ascii(value, valuename, sizeof(value)-1);
1038         
1039         if (handle_is_printserver(handle))
1040                 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1041         else
1042                 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
1043
1044         if (found==False) {
1045                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1046                 /* reply this param doesn't exist */
1047                 if (*out_size) {
1048                         if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1049                                 return ERROR_NOT_ENOUGH_MEMORY;
1050                         memset(*data, '\0', *out_size*sizeof(uint8));
1051                 } else {
1052                         *data = NULL;
1053                 }
1054
1055                 return ERROR_INVALID_PARAMETER;
1056         }
1057         
1058         if (*needed > *out_size)
1059                 return ERROR_MORE_DATA;
1060         else
1061                 return NT_STATUS_NO_PROBLEMO;
1062 }
1063
1064 /***************************************************************************
1065  connect to the client
1066 ****************************************************************************/
1067 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1068 {
1069         uint32 status;
1070
1071         /*
1072          * If it's the first connection, contact the client
1073          * and connect to the IPC$ share anonumously
1074          */
1075         if (smb_connections==0) {
1076                 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1077                         return False;
1078                 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1079
1080         }
1081
1082         smb_connections++;
1083
1084         if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1085                 return False;
1086
1087         return True;
1088 }
1089
1090 /********************************************************************
1091  * _spoolss_rffpcnex
1092  * ReplyFindFirstPrinterChangeNotifyEx
1093  *
1094  * jfmxxxx: before replying OK: status=0
1095  * should do a rpc call to the workstation asking ReplyOpenPrinter
1096  * have to code it, later.
1097  *
1098  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1099  * called from api_spoolss_rffpcnex
1100  ********************************************************************/
1101 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1102                          const UNISTR2 *localmachine, uint32 printerlocal,
1103                          SPOOL_NOTIFY_OPTION *option)
1104 {
1105         /* store the notify value in the printer struct */
1106
1107         Printer_entry *Printer=find_printer_index_by_hnd(handle);
1108
1109         if (!OPEN_HANDLE(Printer)) {
1110                 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1111                 return ERROR_INVALID_HANDLE;
1112         }
1113
1114         Printer->notify.flags=flags;
1115         Printer->notify.options=options;
1116         Printer->notify.printerlocal=printerlocal;
1117         Printer->notify.option=option;
1118         unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1119
1120         /* connect to the client machine and send a ReplyOpenPrinter */
1121         if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1122                                         Printer->notify.printerlocal, 1,
1123                                         &Printer->notify.client_hnd))
1124                 Printer->notify.client_connected=True;
1125
1126         return NT_STATUS_NO_PROBLEMO;
1127 }
1128
1129 /*******************************************************************
1130  * fill a notify_info_data with the servername
1131  ********************************************************************/
1132 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1133                                                                                 NT_PRINTER_INFO_LEVEL *printer)
1134 {
1135         pstring temp_name;
1136
1137         snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1138
1139         data->notify_data.data.length= (uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1140                                         temp_name, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1141 }
1142
1143 /*******************************************************************
1144  * fill a notify_info_data with the printername (not including the servername).
1145  ********************************************************************/
1146 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1147                                                                                 NT_PRINTER_INFO_LEVEL *printer)
1148 {
1149         /* the notify name should not contain the \\server\ part */
1150         char *p = strrchr(printer->info_2->printername, '\\');
1151         if (!p) {
1152                 p = printer->info_2->printername;
1153         } else {
1154                 p++;
1155         }
1156
1157         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1158                                 p, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1159 }
1160
1161 /*******************************************************************
1162  * fill a notify_info_data with the servicename
1163  ********************************************************************/
1164 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1165 {
1166         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1167                         lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
1168 }
1169
1170 /*******************************************************************
1171  * fill a notify_info_data with the port name
1172  ********************************************************************/
1173 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1174 {
1175         /* even if it's strange, that's consistant in all the code */
1176
1177         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1178                 printer->info_2->portname, sizeof(data->notify_data.data.string), True)  - sizeof(uint16))/sizeof(uint16));
1179 }
1180
1181 /*******************************************************************
1182  * fill a notify_info_data with the printername
1183  * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1184  * but it doesn't exist, have to see what to do
1185  ********************************************************************/
1186 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1187 {
1188         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1189                         printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1190 }
1191
1192 /*******************************************************************
1193  * fill a notify_info_data with the comment
1194  ********************************************************************/
1195 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1196 {
1197         if (*printer->info_2->comment == '\0')
1198                 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1199                         lp_comment(snum), sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1200         else
1201                 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1202                         printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1203 }
1204
1205 /*******************************************************************
1206  * fill a notify_info_data with the comment
1207  * jfm:xxxx incorrect, have to create a new smb.conf option
1208  * location = "Room 1, floor 2, building 3"
1209  ********************************************************************/
1210 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1211 {
1212         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1213                         printer->info_2->location, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1214 }
1215
1216 /*******************************************************************
1217  * fill a notify_info_data with the device mode
1218  * jfm:xxxx don't to it for know but that's a real problem !!!
1219  ********************************************************************/
1220 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1221 {
1222 }
1223
1224 /*******************************************************************
1225  * fill a notify_info_data with the separator file name
1226  * jfm:xxxx just return no file could add an option to smb.conf
1227  * separator file = "separator.txt"
1228  ********************************************************************/
1229 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1230 {
1231         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1232                         printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True)  - sizeof(uint16))/sizeof(uint16));
1233 }
1234
1235 /*******************************************************************
1236  * fill a notify_info_data with the print processor
1237  * jfm:xxxx return always winprint to indicate we don't do anything to it
1238  ********************************************************************/
1239 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1240 {
1241         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1242                         printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1243 }
1244
1245 /*******************************************************************
1246  * fill a notify_info_data with the print processor options
1247  * jfm:xxxx send an empty string
1248  ********************************************************************/
1249 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1250 {
1251         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1252                         printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1253 }
1254
1255 /*******************************************************************
1256  * fill a notify_info_data with the data type
1257  * jfm:xxxx always send RAW as data type
1258  ********************************************************************/
1259 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1260 {
1261         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1262                         printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1263 }
1264
1265 /*******************************************************************
1266  * fill a notify_info_data with the security descriptor
1267  * jfm:xxxx send an null pointer to say no security desc
1268  * have to implement security before !
1269  ********************************************************************/
1270 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1271 {
1272         data->notify_data.data.length=0;
1273         data->notify_data.data.string[0]=0x00;
1274 }
1275
1276 /*******************************************************************
1277  * fill a notify_info_data with the attributes
1278  * jfm:xxxx a samba printer is always shared
1279  ********************************************************************/
1280 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1281 {
1282         data->notify_data.value[0] = printer->info_2->attributes;
1283 }
1284
1285 /*******************************************************************
1286  * fill a notify_info_data with the priority
1287  ********************************************************************/
1288 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1289 {
1290         data->notify_data.value[0] = printer->info_2->priority;
1291 }
1292
1293 /*******************************************************************
1294  * fill a notify_info_data with the default priority
1295  ********************************************************************/
1296 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1297 {
1298         data->notify_data.value[0] = printer->info_2->default_priority;
1299 }
1300
1301 /*******************************************************************
1302  * fill a notify_info_data with the start time
1303  ********************************************************************/
1304 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1305 {
1306         data->notify_data.value[0] = printer->info_2->starttime;
1307 }
1308
1309 /*******************************************************************
1310  * fill a notify_info_data with the until time
1311  ********************************************************************/
1312 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1313 {
1314         data->notify_data.value[0] = printer->info_2->untiltime;
1315 }
1316
1317 /*******************************************************************
1318  * fill a notify_info_data with the status
1319  ********************************************************************/
1320 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1321 {
1322         int count;
1323         print_queue_struct *q=NULL;
1324         print_status_struct status;
1325
1326         memset(&status, 0, sizeof(status));
1327         count = print_queue_status(snum, &q, &status);
1328         data->notify_data.value[0]=(uint32) status.status;
1329         safe_free(q);
1330 }
1331
1332 /*******************************************************************
1333  * fill a notify_info_data with the number of jobs queued
1334  ********************************************************************/
1335 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1336 {
1337         print_queue_struct *q=NULL;
1338         print_status_struct status;
1339
1340         memset(&status, 0, sizeof(status));
1341         data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1342         safe_free(q);
1343 }
1344
1345 /*******************************************************************
1346  * fill a notify_info_data with the average ppm
1347  ********************************************************************/
1348 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1349 {
1350         /* always respond 8 pages per minutes */
1351         /* a little hard ! */
1352         data->notify_data.value[0] = printer->info_2->averageppm;
1353 }
1354
1355 /*******************************************************************
1356  * fill a notify_info_data with username
1357  ********************************************************************/
1358 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1359 {
1360         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1361                         queue->user, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1362 }
1363
1364 /*******************************************************************
1365  * fill a notify_info_data with job status
1366  ********************************************************************/
1367 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1368 {
1369         data->notify_data.value[0]=nt_printj_status(queue->status);
1370 }
1371
1372 /*******************************************************************
1373  * fill a notify_info_data with job name
1374  ********************************************************************/
1375 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1376 {
1377         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1378                         queue->file, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1379 }
1380
1381 /*******************************************************************
1382  * fill a notify_info_data with job status
1383  ********************************************************************/
1384 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1385 {
1386         char *p = "unknown";
1387
1388         switch (queue->status) {
1389         case LPQ_QUEUED:
1390                 p = "Queued";
1391                 break;
1392         case LPQ_PAUSED:
1393                 p = "";    /* NT provides the paused string */
1394                 break;
1395         case LPQ_SPOOLING:
1396                 p = "Spooling";
1397                 break;
1398         case LPQ_PRINTING:
1399                 p = "Printing";
1400                 break;
1401         }
1402         data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1403                                 p, sizeof(data->notify_data.data.string)-1, True)  - sizeof(uint16))/sizeof(uint16));
1404 }
1405
1406 /*******************************************************************
1407  * fill a notify_info_data with job time
1408  ********************************************************************/
1409 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1410 {
1411         data->notify_data.value[0]=0x0;
1412 }
1413
1414 /*******************************************************************
1415  * fill a notify_info_data with job size
1416  ********************************************************************/
1417 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1418 {
1419         data->notify_data.value[0]=queue->size;
1420 }
1421
1422 /*******************************************************************
1423  * fill a notify_info_data with job position
1424  ********************************************************************/
1425 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1426 {
1427         data->notify_data.value[0]=queue->job;
1428 }
1429
1430 /*******************************************************************
1431  * fill a notify_info_data with submitted time
1432  ********************************************************************/
1433 static void spoolss_notify_submitted_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1434 {
1435         struct tm *t;
1436
1437         t=gmtime(&queue->time);
1438
1439         data->notify_data.data.length = sizeof(SYSTEMTIME);
1440         make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1441 }
1442
1443 #define END 65535
1444
1445 struct s_notify_info_data_table
1446 {
1447         uint16 type;
1448         uint16 field;
1449         char *name;
1450         uint32 size;
1451         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1452                     print_queue_struct *queue,
1453                     NT_PRINTER_INFO_LEVEL *printer);
1454 };
1455
1456 struct s_notify_info_data_table notify_info_data_table[] =
1457 {
1458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         POINTER,   spoolss_notify_server_name },
1459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        POINTER,   spoolss_notify_printer_name },
1460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          POINTER,   spoolss_notify_share_name },
1461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           POINTER,   spoolss_notify_port_name },
1462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         POINTER,   spoolss_notify_driver_name },
1463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             POINTER,   spoolss_notify_comment },
1464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            POINTER,   spoolss_notify_location },
1465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             POINTER,   spoolss_notify_devmode },
1466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             POINTER,   spoolss_notify_sepfile },
1467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     POINTER,   spoolss_notify_print_processor },
1468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          POINTER,   spoolss_notify_parameters },
1469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            POINTER,   spoolss_notify_datatype },
1470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER,   spoolss_notify_security_desc },
1471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          ONE_VALUE, spoolss_notify_attributes },
1472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            ONE_VALUE, spoolss_notify_priority },
1473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    ONE_VALUE, spoolss_notify_default_priority },
1474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          ONE_VALUE, spoolss_notify_start_time },
1475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          ONE_VALUE, spoolss_notify_until_time },
1476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              ONE_VALUE, spoolss_notify_status },
1477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       POINTER,   NULL },
1478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               ONE_VALUE, spoolss_notify_cjobs },
1479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         ONE_VALUE, spoolss_notify_average_ppm },
1480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         POINTER,   NULL },
1481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       POINTER,   NULL },
1482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         POINTER,   NULL },
1483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       POINTER,   NULL },
1484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            POINTER,   spoolss_notify_printer_name },
1485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            POINTER,   spoolss_notify_server_name },
1486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               POINTER,   spoolss_notify_port_name },
1487 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               POINTER,   spoolss_notify_username },
1488 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             POINTER,   spoolss_notify_username },
1489 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                POINTER,   spoolss_notify_datatype },
1490 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         POINTER,   spoolss_notify_print_processor },
1491 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              POINTER,   spoolss_notify_parameters },
1492 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             POINTER,   spoolss_notify_driver_name },
1493 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 POINTER,   spoolss_notify_devmode },
1494 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  ONE_VALUE, spoolss_notify_job_status },
1495 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           POINTER,   spoolss_notify_job_status_string },
1496 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     POINTER,   NULL },
1497 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                POINTER,   spoolss_notify_job_name },
1498 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                ONE_VALUE, spoolss_notify_priority },
1499 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                ONE_VALUE, spoolss_notify_job_position },
1500 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               POINTER,   spoolss_notify_submitted_time },
1501 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              ONE_VALUE, spoolss_notify_start_time },
1502 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              ONE_VALUE, spoolss_notify_until_time },
1503 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    ONE_VALUE, spoolss_notify_job_time },
1504 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             ONE_VALUE, NULL },
1505 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           ONE_VALUE, NULL },
1506 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             ONE_VALUE, spoolss_notify_job_size },
1507 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_BYTES_PRINTED,           "JOB_NOTIFY_BYTES_PRINTED",           ONE_VALUE, NULL },
1508 { END,                 END,                                "",                                   END,       NULL }
1509 };
1510
1511 /*******************************************************************
1512 return the size of info_data structure
1513 ********************************************************************/
1514 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1515 {
1516         int i=0;
1517
1518         while (notify_info_data_table[i].type != END)
1519         {
1520                 if ( (notify_info_data_table[i].type == type ) &&
1521                      (notify_info_data_table[i].field == field ) )
1522                 {
1523                         return (notify_info_data_table[i].size);
1524                 }
1525                 i++;
1526         }
1527         return (65535);
1528 }
1529
1530 /*******************************************************************
1531 return the type of notify_info_data
1532 ********************************************************************/
1533 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1534 {
1535         int i=0;
1536
1537         while (notify_info_data_table[i].type != END)
1538         {
1539                 if ( (notify_info_data_table[i].type == type ) &&
1540                      (notify_info_data_table[i].field == field ) )
1541                 {
1542                         if (notify_info_data_table[i].size == POINTER)
1543                         {
1544                                 return (False);
1545                         }
1546                         else
1547                         {
1548                                 return (True);
1549                         }
1550                 }
1551                 i++;
1552         }
1553         return (False);
1554 }
1555
1556 /****************************************************************************
1557 ****************************************************************************/
1558 static int search_notify(uint16 type, uint16 field, int *value)
1559 {       
1560         int j;
1561         BOOL found;
1562
1563         for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1564         {
1565                 if ( (notify_info_data_table[j].type  == type  ) &&
1566                      (notify_info_data_table[j].field == field ) )
1567                         found=True;
1568         }
1569         *value=--j;
1570
1571         if ( found && (notify_info_data_table[j].fn != NULL) )
1572                 return True;
1573         else
1574                 return False;   
1575 }
1576
1577 /****************************************************************************
1578 ****************************************************************************/
1579 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1580 {
1581         info_data->type     = type;
1582         info_data->field    = field;
1583         info_data->reserved = 0;
1584         info_data->id       = id;
1585         info_data->size     = size_of_notify_info_data(type, field);
1586         info_data->enc_type = type_of_notify_info_data(type, field);
1587 }
1588
1589
1590 /*******************************************************************
1591  *
1592  * fill a notify_info struct with info asked
1593  *
1594  ********************************************************************/
1595 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1596 {
1597         int field_num,j;
1598         uint16 type;
1599         uint16 field;
1600
1601         SPOOL_NOTIFY_INFO_DATA *current_data;
1602         NT_PRINTER_INFO_LEVEL *printer = NULL;
1603         print_queue_struct *queue=NULL;
1604         
1605         DEBUG(4,("construct_notify_printer_info\n"));
1606         
1607         type=option_type->type;
1608
1609         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1610                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1611                 option_type->count, lp_servicename(snum)));
1612         
1613         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1614                 return False;
1615
1616         for(field_num=0; field_num<option_type->count; field_num++) {
1617                 field = option_type->fields[field_num];
1618                 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1619
1620                 if (!search_notify(type, field, &j) )
1621                         continue;
1622                 
1623                 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1624                         return False;
1625                 }
1626                 current_data=&info->data[info->count];
1627
1628                 construct_info_data(current_data, type, field, id);             
1629
1630                 DEBUG(10,("construct_notify_printer_info: calling %s\n",
1631                                 notify_info_data_table[j].name ));
1632
1633                 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1634
1635                 info->count++;
1636         }
1637
1638         free_a_printer(&printer, 2);
1639         return True;
1640 }
1641
1642 /*******************************************************************
1643  *
1644  * fill a notify_info struct with info asked
1645  *
1646  ********************************************************************/
1647 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1648 {
1649         int field_num,j;
1650         uint16 type;
1651         uint16 field;
1652
1653         SPOOL_NOTIFY_INFO_DATA *current_data;
1654         NT_PRINTER_INFO_LEVEL *printer = NULL;
1655         
1656         DEBUG(4,("construct_notify_jobs_info\n"));
1657         
1658         type = option_type->type;
1659
1660         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1661                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1662                 option_type->count));
1663
1664         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1665                 return False;
1666         
1667         for(field_num=0; field_num<option_type->count; field_num++) {
1668                 field = option_type->fields[field_num];
1669
1670                 if (!search_notify(type, field, &j) )
1671                         continue;
1672
1673                 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1674                         return False;
1675                 }
1676
1677                 current_data=&(info->data[info->count]);
1678
1679                 construct_info_data(current_data, type, field, id);
1680                 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1681                 info->count++;
1682         }
1683
1684         free_a_printer(&printer, 2);    
1685         return True;
1686 }
1687
1688 /*
1689  * JFM: The enumeration is not that simple, it's even non obvious.
1690  *
1691  * let's take an example: I want to monitor the PRINTER SERVER for
1692  * the printer's name and the number of jobs currently queued.
1693  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1694  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1695  *
1696  * I have 3 printers on the back of my server.
1697  *
1698  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1699  * structures.
1700  *   Number     Data                    Id
1701  *      1       printer 1 name          1
1702  *      2       printer 1 cjob          1
1703  *      3       printer 2 name          2
1704  *      4       printer 2 cjob          2
1705  *      5       printer 3 name          3
1706  *      6       printer 3 name          3
1707  *
1708  * that's the print server case, the printer case is even worse.
1709  */
1710
1711
1712
1713 /*******************************************************************
1714  *
1715  * enumerate all printers on the printserver
1716  * fill a notify_info struct with info asked
1717  *
1718  ********************************************************************/
1719 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1720 {
1721         int snum;
1722         Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1723         int n_services=lp_numservices();
1724         int i;
1725         uint32 id;
1726         SPOOL_NOTIFY_OPTION *option;
1727         SPOOL_NOTIFY_OPTION_TYPE *option_type;
1728
1729         DEBUG(4,("printserver_notify_info\n"));
1730         
1731         option=Printer->notify.option;
1732         id=1;
1733         info->version=2;
1734         info->data=NULL;
1735         info->count=0;
1736
1737         for (i=0; i<option->count; i++) {
1738                 option_type=&(option->ctr.type[i]);
1739                 
1740                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1741                         continue;
1742                 
1743                 for (snum=0; snum<n_services; snum++)
1744                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1745                                 if (construct_notify_printer_info(info, snum, option_type, id))
1746                                         id++;
1747         }
1748                         
1749         /*
1750          * Debugging information, don't delete.
1751          */
1752         /*
1753         DEBUG(1,("dumping the NOTIFY_INFO\n"));
1754         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1755         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1756         
1757         for (i=0; i<info->count; i++) {
1758                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1759                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1760                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1761         }
1762         */
1763         
1764         return NT_STATUS_NO_PROBLEMO;
1765 }
1766
1767 /*******************************************************************
1768  *
1769  * fill a notify_info struct with info asked
1770  *
1771  ********************************************************************/
1772 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1773 {
1774         int snum;
1775         Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1776         int i;
1777         uint32 id;
1778         SPOOL_NOTIFY_OPTION *option;
1779         SPOOL_NOTIFY_OPTION_TYPE *option_type;
1780         int count,j;
1781         print_queue_struct *queue=NULL;
1782         print_status_struct status;
1783         
1784         DEBUG(4,("printer_notify_info\n"));
1785
1786         option=Printer->notify.option;
1787         id=0xffffffff;
1788         info->version=2;
1789         info->data=NULL;
1790         info->count=0;
1791
1792         get_printer_snum(hnd, &snum);
1793
1794         for (i=0; i<option->count; i++) {
1795                 option_type=&option->ctr.type[i];
1796                 
1797                 switch ( option_type->type ) {
1798                 case PRINTER_NOTIFY_TYPE:
1799                         if(construct_notify_printer_info(info, snum, option_type, id))
1800                                 id--;
1801                         break;
1802                         
1803                 case JOB_NOTIFY_TYPE:
1804                         memset(&status, 0, sizeof(status));     
1805                         count = print_queue_status(snum, &queue, &status);
1806                         for (j=0; j<count; j++)
1807                                 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1808                         safe_free(queue);
1809                         break;
1810                 }
1811         }
1812         
1813         /*
1814          * Debugging information, don't delete.
1815          */
1816         /*
1817         DEBUG(1,("dumping the NOTIFY_INFO\n"));
1818         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1819         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1820         
1821         for (i=0; i<info->count; i++) {
1822                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1823                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1824                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1825         }
1826         */
1827         return NT_STATUS_NO_PROBLEMO;
1828 }
1829
1830 /********************************************************************
1831  * spoolss_rfnpcnex
1832  ********************************************************************/
1833 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1834                           SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1835 {
1836         Printer_entry *Printer=find_printer_index_by_hnd(handle);
1837
1838         if (!OPEN_HANDLE(Printer)) {
1839                 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1840                 return ERROR_INVALID_HANDLE;
1841         }
1842
1843         DEBUG(4,("Printer type %x\n",Printer->printer_type));
1844
1845         /* jfm: the change value isn't used right now.
1846          *      we will honour it when
1847          *      a) we'll be able to send notification to the client
1848          *      b) we'll have a way to communicate between the spoolss process.
1849          *
1850          *      same thing for option->flags
1851          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1852          *      I don't have a global notification system, I'm sending back all the
1853          *      informations even when _NOTHING_ has changed.
1854          */
1855
1856         /* just discard the SPOOL_NOTIFY_OPTION */
1857         if (option!=NULL)
1858                 safe_free(option->ctr.type);
1859         
1860         switch (Printer->printer_type) {
1861                 case PRINTER_HANDLE_IS_PRINTSERVER:
1862                         return printserver_notify_info(handle, info);
1863                 case PRINTER_HANDLE_IS_PRINTER:
1864                         return printer_notify_info(handle, info);
1865         }
1866
1867         return ERROR_INVALID_HANDLE;
1868 }
1869
1870 /********************************************************************
1871  * construct_printer_info_0
1872  * fill a printer_info_0 struct
1873  ********************************************************************/
1874 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
1875 {
1876         pstring chaine;
1877         int count;
1878         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1879         counter_printer_0 *session_counter;
1880         uint32 global_counter;
1881         struct tm *t;
1882         time_t setuptime;
1883
1884         print_queue_struct *queue=NULL;
1885         print_status_struct status;
1886         
1887         memset(&status, 0, sizeof(status));     
1888
1889         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1890                 return False;
1891
1892         count = print_queue_status(snum, &queue, &status);
1893
1894         /* check if we already have a counter for this printer */       
1895         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1896
1897         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1898                 if (session_counter->snum == snum)
1899                         break;
1900         }
1901
1902         /* it's the first time, add it to the list */
1903         if (session_counter==NULL) {
1904                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1905                         free_a_printer(&ntprinter, 2);
1906                         return False;
1907                 }
1908                 ZERO_STRUCTP(session_counter);
1909                 session_counter->snum=snum;
1910                 session_counter->counter=0;
1911                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1912         }
1913         
1914         /* increment it */
1915         session_counter->counter++;
1916         
1917         /* JFM:
1918          * the global_counter should be stored in a TDB as it's common to all the clients
1919          * and should be zeroed on samba startup
1920          */
1921         global_counter=session_counter->counter;
1922         
1923         pstrcpy(chaine,ntprinter->info_2->printername);
1924
1925         init_unistr(&printer->printername, chaine);
1926         
1927         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
1928         init_unistr(&printer->servername, chaine);
1929         
1930         printer->cjobs = count;
1931         printer->total_jobs = 0;
1932         printer->total_bytes = 0;
1933
1934         setuptime = (time_t)ntprinter->info_2->setuptime;
1935         t=gmtime(&setuptime);
1936
1937         printer->year = t->tm_year+1900;
1938         printer->month = t->tm_mon+1;
1939         printer->dayofweek = t->tm_wday;
1940         printer->day = t->tm_mday;
1941         printer->hour = t->tm_hour;
1942         printer->minute = t->tm_min;
1943         printer->second = t->tm_sec;
1944         printer->milliseconds = 0;
1945
1946         printer->global_counter = global_counter;
1947         printer->total_pages = 0;
1948         printer->major_version = 0x0004;        /* NT 4 */
1949         printer->build_version = 0x0565;        /* build 1381 */
1950         printer->unknown7 = 0x1;
1951         printer->unknown8 = 0x0;
1952         printer->unknown9 = 0x0;
1953         printer->session_counter = session_counter->counter;
1954         printer->unknown11 = 0x0;
1955         printer->printer_errors = 0x0;          /* number of print failure */
1956         printer->unknown13 = 0x0;
1957         printer->unknown14 = 0x1;
1958         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
1959         printer->unknown16 = 0x0;
1960         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1961         printer->unknown18 = 0x0;
1962         printer->status = nt_printq_status(status.status);
1963         printer->unknown20 = 0x0;
1964         printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1965         printer->unknown22 = 0x0;
1966         printer->unknown23 = 0x6;               /* 6  ???*/
1967         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
1968         printer->unknown25 = 0;
1969         printer->unknown26 = 0;
1970         printer->unknown27 = 0;
1971         printer->unknown28 = 0;
1972         printer->unknown29 = 0;
1973         
1974         safe_free(queue);
1975         free_a_printer(&ntprinter,2);
1976         return (True);  
1977 }
1978
1979 /********************************************************************
1980  * construct_printer_info_1
1981  * fill a printer_info_1 struct
1982  ********************************************************************/
1983 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
1984 {
1985         pstring chaine;
1986         pstring chaine2;
1987         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1988
1989         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1990                 return False;
1991
1992         printer->flags=flags;
1993
1994         if (*ntprinter->info_2->comment == '\0') {
1995                 init_unistr(&printer->comment, lp_comment(snum));
1996                 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
1997                         ntprinter->info_2->drivername, lp_comment(snum));
1998         }
1999         else {
2000                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2001                 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2002                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
2003         }
2004                 
2005         snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2006
2007         init_unistr(&printer->description, chaine);
2008         init_unistr(&printer->name, chaine2);   
2009         
2010         free_a_printer(&ntprinter,2);
2011
2012         return True;
2013 }
2014
2015 /****************************************************************************
2016  Free a DEVMODE struct.
2017 ****************************************************************************/
2018
2019 static void free_dev_mode(DEVICEMODE *dev)
2020 {
2021         if (dev == NULL)
2022                 return;
2023
2024         if (dev->private)
2025                 safe_free(dev->private);
2026
2027         safe_free(dev); 
2028 }
2029
2030 /****************************************************************************
2031  Create a DEVMODE struct. Returns malloced memory.
2032 ****************************************************************************/
2033
2034 static DEVICEMODE *construct_dev_mode(int snum)
2035 {
2036         char adevice[32];
2037         char aform[32];
2038         NT_PRINTER_INFO_LEVEL *printer = NULL;
2039         NT_DEVICEMODE *ntdevmode = NULL;
2040         DEVICEMODE *devmode = NULL;
2041
2042         DEBUG(7,("construct_dev_mode\n"));
2043         
2044         DEBUGADD(8,("getting printer characteristics\n"));
2045
2046         if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2047                 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2048                 return NULL;
2049         }
2050
2051         ZERO_STRUCTP(devmode);  
2052
2053         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2054                 goto fail;
2055
2056         if (printer->info_2->devmode)
2057                 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2058
2059         if (ntdevmode == NULL)
2060                 goto fail;
2061
2062         DEBUGADD(8,("loading DEVICEMODE\n"));
2063
2064         snprintf(adevice, sizeof(adevice), printer->info_2->printername);
2065         init_unistr(&devmode->devicename, adevice);
2066
2067         snprintf(aform, sizeof(aform), ntdevmode->formname);
2068         init_unistr(&devmode->formname, aform);
2069
2070         devmode->specversion      = ntdevmode->specversion;
2071         devmode->driverversion    = ntdevmode->driverversion;
2072         devmode->size             = ntdevmode->size;
2073         devmode->driverextra      = ntdevmode->driverextra;
2074         devmode->fields           = ntdevmode->fields;
2075                                 
2076         devmode->orientation      = ntdevmode->orientation;     
2077         devmode->papersize        = ntdevmode->papersize;
2078         devmode->paperlength      = ntdevmode->paperlength;
2079         devmode->paperwidth       = ntdevmode->paperwidth;
2080         devmode->scale            = ntdevmode->scale;
2081         devmode->copies           = ntdevmode->copies;
2082         devmode->defaultsource    = ntdevmode->defaultsource;
2083         devmode->printquality     = ntdevmode->printquality;
2084         devmode->color            = ntdevmode->color;
2085         devmode->duplex           = ntdevmode->duplex;
2086         devmode->yresolution      = ntdevmode->yresolution;
2087         devmode->ttoption         = ntdevmode->ttoption;
2088         devmode->collate          = ntdevmode->collate;
2089         devmode->icmmethod        = ntdevmode->icmmethod;
2090         devmode->icmintent        = ntdevmode->icmintent;
2091         devmode->mediatype        = ntdevmode->mediatype;
2092         devmode->dithertype       = ntdevmode->dithertype;
2093
2094         if (ntdevmode->private != NULL) {
2095                 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2096                         goto fail;
2097         }
2098
2099         free_nt_devicemode(&ntdevmode);
2100         free_a_printer(&printer,2);
2101
2102         return devmode;
2103
2104   fail:
2105
2106         if (ntdevmode)
2107                 free_nt_devicemode(&ntdevmode);
2108         if (printer)
2109                 free_a_printer(&printer,2);
2110         free_dev_mode(devmode);
2111
2112         return NULL;
2113 }
2114
2115 /********************************************************************
2116  * construct_printer_info_2
2117  * fill a printer_info_2 struct
2118  ********************************************************************/
2119
2120 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2121 {
2122         int count;
2123         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2124
2125         print_queue_struct *queue=NULL;
2126         print_status_struct status;
2127         memset(&status, 0, sizeof(status));     
2128
2129         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2130                 return False;
2131                 
2132         memset(&status, 0, sizeof(status));             
2133         count = print_queue_status(snum, &queue, &status);
2134
2135         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2136         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2137         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
2138         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
2139         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
2140
2141         if (*ntprinter->info_2->comment == '\0')
2142                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
2143         else
2144                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2145
2146         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
2147         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
2148         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2149         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
2150         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
2151
2152         printer->attributes = ntprinter->info_2->attributes;
2153
2154         printer->priority = ntprinter->info_2->priority;                                /* priority */  
2155         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
2156         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
2157         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
2158         printer->status = nt_printq_status(status.status);                      /* status */
2159         printer->cjobs = count;                                                 /* jobs */
2160         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
2161                         
2162         if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2163                 DEBUG(8, ("Returning NULL Devicemode!\n"));
2164         }
2165
2166         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2167                 /* steal the printer info sec_desc structure.  [badly done]. */
2168                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2169                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2170                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2171                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2172         }
2173         else {
2174                 printer->secdesc = NULL;
2175         }
2176
2177         free_a_printer(&ntprinter, 2);
2178         safe_free(queue);
2179         return True;
2180 }
2181
2182 /********************************************************************
2183  * construct_printer_info_3
2184  * fill a printer_info_3 struct
2185  ********************************************************************/
2186 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2187 {
2188         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2189         PRINTER_INFO_3 *printer = NULL;
2190
2191         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2192                 return False;
2193
2194         *pp_printer = NULL;
2195         if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2196                 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2197                 return False;
2198         }
2199
2200         ZERO_STRUCTP(printer);
2201         
2202         printer->flags = 4; /* These are the components of the SD we are returning. */
2203         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2204                 /* steal the printer info sec_desc structure.  [badly done]. */
2205                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2206
2207 #if 0
2208                 /*
2209                  * Set the flags for the components we are returning.
2210                  */
2211
2212                 if (printer->secdesc->owner_sid)
2213                         printer->flags |= OWNER_SECURITY_INFORMATION;
2214
2215                 if (printer->secdesc->grp_sid)
2216                         printer->flags |= GROUP_SECURITY_INFORMATION;
2217
2218                 if (printer->secdesc->dacl)
2219                         printer->flags |= DACL_SECURITY_INFORMATION;
2220
2221                 if (printer->secdesc->sacl)
2222                         printer->flags |= SACL_SECURITY_INFORMATION;
2223 #endif
2224
2225                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2226                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2227                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2228         }
2229
2230         free_a_printer(&ntprinter, 2);
2231
2232         *pp_printer = printer;
2233         return True;
2234 }
2235
2236 /********************************************************************
2237  Spoolss_enumprinters.
2238 ********************************************************************/
2239 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2240 {
2241         int snum;
2242         int i;
2243         int n_services=lp_numservices();
2244         PRINTER_INFO_1 *printers=NULL;
2245         PRINTER_INFO_1 current_prt;
2246         
2247         DEBUG(4,("enum_all_printers_info_1\n"));        
2248
2249         for (snum=0; snum<n_services; snum++) {
2250                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2251                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2252                                 
2253                         if (construct_printer_info_1(flags, &current_prt, snum)) {
2254                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2255                                         *returned=0;
2256                                         return ERROR_NOT_ENOUGH_MEMORY;
2257                                 }
2258                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
2259                                 memcpy(&(printers[*returned]), &current_prt, sizeof(PRINTER_INFO_1));
2260                                 (*returned)++;
2261                         }
2262                 }
2263         }
2264                 
2265         /* check the required size. */  
2266         for (i=0; i<*returned; i++)
2267                 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2268
2269         if (!alloc_buffer_size(buffer, *needed))
2270                 return ERROR_INSUFFICIENT_BUFFER;
2271
2272         /* fill the buffer with the structures */
2273         for (i=0; i<*returned; i++)
2274                 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);       
2275
2276         /* clear memory */
2277         safe_free(printers);
2278
2279         if (*needed > offered) {
2280                 *returned=0;
2281                 return ERROR_INSUFFICIENT_BUFFER;
2282         }
2283         else
2284                 return NT_STATUS_NO_PROBLEMO;
2285 }
2286
2287 /********************************************************************
2288  enum_all_printers_info_1_local.
2289 *********************************************************************/
2290 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2291 {
2292         DEBUG(4,("enum_all_printers_info_1_local\n"));  
2293         
2294         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2295 }
2296
2297 /********************************************************************
2298  enum_all_printers_info_1_name.
2299 *********************************************************************/
2300 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2301 {
2302         fstring temp;
2303         DEBUG(4,("enum_all_printers_info_1_name\n"));   
2304         
2305         fstrcpy(temp, "\\\\");
2306         fstrcat(temp, global_myname);
2307
2308         if (strequal(name, temp)) {
2309                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2310         }
2311         else
2312                 return ERROR_INVALID_NAME;
2313 }
2314
2315 /********************************************************************
2316  enum_all_printers_info_1_remote.
2317 *********************************************************************/
2318 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2319 {
2320         PRINTER_INFO_1 *printer;
2321         fstring printername;
2322         fstring desc;
2323         fstring comment;
2324         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
2325
2326         /* JFM: currently it's more a place holder than anything else.
2327          * In the spooler world there is a notion of server registration.
2328          * the print servers are registring (sp ?) on the PDC (in the same domain)
2329          *
2330          * We should have a TDB here. The registration is done thru an undocumented RPC call.
2331          */
2332         
2333         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2334                 return ERROR_NOT_ENOUGH_MEMORY;
2335
2336         *returned=1;
2337         
2338         snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);               
2339         snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2340         snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2341
2342         init_unistr(&printer->description, desc);
2343         init_unistr(&printer->name, printername);       
2344         init_unistr(&printer->comment, comment);
2345         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2346                 
2347         /* check the required size. */  
2348         *needed += spoolss_size_printer_info_1(printer);
2349
2350         if (!alloc_buffer_size(buffer, *needed)) {
2351                 safe_free(printer);
2352                 return ERROR_INSUFFICIENT_BUFFER;
2353         }
2354
2355         /* fill the buffer with the structures */
2356         new_smb_io_printer_info_1("", buffer, printer, 0);      
2357
2358         /* clear memory */
2359         safe_free(printer);
2360
2361         if (*needed > offered) {
2362                 *returned=0;
2363                 return ERROR_INSUFFICIENT_BUFFER;
2364         }
2365         else
2366                 return NT_STATUS_NO_PROBLEMO;
2367 }
2368
2369 /********************************************************************
2370  enum_all_printers_info_1_network.
2371 *********************************************************************/
2372 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2373 {
2374         DEBUG(4,("enum_all_printers_info_1_network\n"));        
2375         
2376         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2377 }
2378
2379 /********************************************************************
2380  * api_spoolss_enumprinters
2381  *
2382  * called from api_spoolss_enumprinters (see this to understand)
2383  ********************************************************************/
2384 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2385 {
2386         int snum;
2387         int i;
2388         int n_services=lp_numservices();
2389         PRINTER_INFO_2 *printers=NULL;
2390         PRINTER_INFO_2 current_prt;
2391
2392         for (snum=0; snum<n_services; snum++) {
2393                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2394                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2395                                 
2396                         if (construct_printer_info_2(&current_prt, snum)) {
2397                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2398                                         return ERROR_NOT_ENOUGH_MEMORY;
2399                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
2400                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
2401                                 (*returned)++;
2402                         }
2403                 }
2404         }
2405         
2406         /* check the required size. */  
2407         for (i=0; i<*returned; i++)
2408                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2409
2410         if (!alloc_buffer_size(buffer, *needed)) {
2411                 for (i=0; i<*returned; i++) {
2412                         free_devmode(printers[i].devmode);
2413                         free_sec_desc(&printers[i].secdesc);
2414                 }
2415                 safe_free(printers);
2416                 return ERROR_INSUFFICIENT_BUFFER;
2417         }
2418
2419         /* fill the buffer with the structures */
2420         for (i=0; i<*returned; i++)
2421                 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);       
2422         
2423         /* clear memory */
2424         for (i=0; i<*returned; i++) {
2425                 free_devmode(printers[i].devmode);
2426                 free_sec_desc(&printers[i].secdesc);
2427         }
2428         safe_free(printers);
2429
2430         if (*needed > offered) {
2431                 *returned=0;
2432                 return ERROR_INSUFFICIENT_BUFFER;
2433         }
2434         else
2435                 return NT_STATUS_NO_PROBLEMO;
2436 }
2437
2438 /********************************************************************
2439  * handle enumeration of printers at level 1
2440  ********************************************************************/
2441 static uint32 enumprinters_level1( uint32 flags, fstring name,
2442                                  NEW_BUFFER *buffer, uint32 offered,
2443                                  uint32 *needed, uint32 *returned)
2444 {
2445         /* Not all the flags are equals */
2446
2447         if (flags & PRINTER_ENUM_LOCAL)
2448                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2449
2450         if (flags & PRINTER_ENUM_NAME)
2451                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2452
2453         if (flags & PRINTER_ENUM_REMOTE)
2454                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2455
2456         if (flags & PRINTER_ENUM_NETWORK)
2457                 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2458
2459         return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2460 }
2461
2462 /********************************************************************
2463  * handle enumeration of printers at level 2
2464  ********************************************************************/
2465 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2466                                  NEW_BUFFER *buffer, uint32 offered,
2467                                  uint32 *needed, uint32 *returned)
2468 {
2469         fstring temp;
2470         
2471         fstrcpy(temp, "\\\\");
2472         fstrcat(temp, global_myname);
2473
2474         if (flags & PRINTER_ENUM_LOCAL) {
2475                 if (strequal(servername, temp))
2476                         return enum_all_printers_info_2(buffer, offered, needed, returned);
2477                 else
2478                         return enum_all_printers_info_2(buffer, offered, needed, returned);
2479         }
2480
2481         if (flags & PRINTER_ENUM_NAME) {
2482                 if (strequal(servername, temp))
2483                         return enum_all_printers_info_2(buffer, offered, needed, returned);
2484                 else
2485                         return ERROR_INVALID_NAME;
2486         }
2487
2488         if (flags & PRINTER_ENUM_REMOTE)
2489                 return ERROR_INVALID_LEVEL;
2490
2491         return NT_STATUS_NO_PROBLEMO;
2492 }
2493
2494 /********************************************************************
2495  * handle enumeration of printers at level 5
2496  ********************************************************************/
2497 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2498                                  NEW_BUFFER *buffer, uint32 offered,
2499                                  uint32 *needed, uint32 *returned)
2500 {
2501 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2502         return NT_STATUS_NO_PROBLEMO;
2503 }
2504
2505 /********************************************************************
2506  * api_spoolss_enumprinters
2507  *
2508  * called from api_spoolss_enumprinters (see this to understand)
2509  ********************************************************************/
2510 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2511                               NEW_BUFFER *buffer, uint32 offered,
2512                               uint32 *needed, uint32 *returned)
2513 {
2514         fstring name;
2515         
2516         DEBUG(4,("_spoolss_enumprinters\n"));
2517
2518         *needed=0;
2519         *returned=0;
2520         
2521         /*
2522          * Level 1:
2523          *          flags==PRINTER_ENUM_NAME
2524          *           if name=="" then enumerates all printers
2525          *           if name!="" then enumerate the printer
2526          *          flags==PRINTER_ENUM_REMOTE
2527          *          name is NULL, enumerate printers
2528          * Level 2: name!="" enumerates printers, name can't be NULL
2529          * Level 3: doesn't exist
2530          * Level 4: does a local registry lookup
2531          * Level 5: same as Level 2
2532          */
2533
2534         unistr2_to_ascii(name, servername, sizeof(name)-1);
2535         strupper(name);
2536
2537         switch (level) {
2538         case 1:
2539                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2540         case 2:
2541                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2542         case 5:
2543                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2544         case 3:
2545         case 4:
2546         default:
2547                 return ERROR_INVALID_LEVEL;
2548         }
2549 }
2550
2551 /****************************************************************************
2552 ****************************************************************************/
2553 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2554 {
2555         PRINTER_INFO_0 *printer=NULL;
2556
2557         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2558                 return ERROR_NOT_ENOUGH_MEMORY;
2559
2560         construct_printer_info_0(printer, snum);
2561         
2562         /* check the required size. */  
2563         *needed += spoolss_size_printer_info_0(printer);
2564
2565         if (!alloc_buffer_size(buffer, *needed)) {
2566                 safe_free(printer);
2567                 return ERROR_INSUFFICIENT_BUFFER;
2568         }
2569
2570         /* fill the buffer with the structures */
2571         new_smb_io_printer_info_0("", buffer, printer, 0);      
2572         
2573         /* clear memory */
2574         safe_free(printer);
2575
2576         if (*needed > offered) {
2577                 return ERROR_INSUFFICIENT_BUFFER;
2578         }
2579         else
2580                 return NT_STATUS_NO_PROBLEMO;   
2581 }
2582
2583 /****************************************************************************
2584 ****************************************************************************/
2585 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2586 {
2587         PRINTER_INFO_1 *printer=NULL;
2588
2589         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2590                 return ERROR_NOT_ENOUGH_MEMORY;
2591
2592         construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2593         
2594         /* check the required size. */  
2595         *needed += spoolss_size_printer_info_1(printer);
2596
2597         if (!alloc_buffer_size(buffer, *needed)) {
2598                 safe_free(printer);
2599                 return ERROR_INSUFFICIENT_BUFFER;
2600         }
2601
2602         /* fill the buffer with the structures */
2603         new_smb_io_printer_info_1("", buffer, printer, 0);      
2604         
2605         /* clear memory */
2606         safe_free(printer);
2607
2608         if (*needed > offered) {
2609                 return ERROR_INSUFFICIENT_BUFFER;
2610         }
2611         else
2612                 return NT_STATUS_NO_PROBLEMO;   
2613 }
2614
2615 /****************************************************************************
2616 ****************************************************************************/
2617 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2618 {
2619         PRINTER_INFO_2 *printer=NULL;
2620
2621         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2622                 return ERROR_NOT_ENOUGH_MEMORY;
2623         
2624         construct_printer_info_2(printer, snum);
2625         
2626         /* check the required size. */  
2627         *needed += spoolss_size_printer_info_2(printer);
2628
2629         if (!alloc_buffer_size(buffer, *needed)) {
2630                 free_printer_info_2(printer);
2631                 return ERROR_INSUFFICIENT_BUFFER;
2632         }
2633
2634         /* fill the buffer with the structures */
2635         if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2636                 free_printer_info_2(printer);
2637                 return ERROR_NOT_ENOUGH_MEMORY;
2638         }
2639         
2640         /* clear memory */
2641         free_printer_info_2(printer);
2642
2643         if (*needed > offered) {
2644                 return ERROR_INSUFFICIENT_BUFFER;
2645         }
2646         else
2647                 return NT_STATUS_NO_PROBLEMO;   
2648 }
2649
2650 /****************************************************************************
2651 ****************************************************************************/
2652 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2653 {
2654         PRINTER_INFO_3 *printer=NULL;
2655
2656         if (!construct_printer_info_3(&printer, snum))
2657                 return ERROR_NOT_ENOUGH_MEMORY;
2658         
2659         /* check the required size. */  
2660         *needed += spoolss_size_printer_info_3(printer);
2661
2662         if (!alloc_buffer_size(buffer, *needed)) {
2663                 free_printer_info_3(printer);
2664                 return ERROR_INSUFFICIENT_BUFFER;
2665         }
2666
2667         /* fill the buffer with the structures */
2668         new_smb_io_printer_info_3("", buffer, printer, 0);      
2669         
2670         /* clear memory */
2671         free_printer_info_3(printer);
2672         
2673         if (*needed > offered) {
2674                 return ERROR_INSUFFICIENT_BUFFER;
2675         }
2676         else
2677                 return NT_STATUS_NO_PROBLEMO;   
2678 }
2679
2680 /****************************************************************************
2681 ****************************************************************************/
2682 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2683                            NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2684 {
2685         int snum;
2686         
2687         *needed=0;
2688
2689         if (!get_printer_snum(handle, &snum))
2690                 return ERROR_INVALID_HANDLE;
2691
2692         switch (level) {
2693         case 0:
2694                 return getprinter_level_0(snum, buffer, offered, needed);
2695         case 1:
2696                 return getprinter_level_1(snum, buffer, offered, needed);
2697         case 2:         
2698                 return getprinter_level_2(snum, buffer, offered, needed);
2699         case 3:         
2700                 return getprinter_level_3(snum, buffer, offered, needed);
2701         default:
2702                 return ERROR_INVALID_LEVEL;
2703         }
2704 }       
2705                 
2706 /********************************************************************
2707  * fill a DRIVER_INFO_1 struct
2708  ********************************************************************/
2709 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2710 {
2711         init_unistr( &info->name, driver.info_3->name);
2712 }
2713
2714 /********************************************************************
2715  * construct_printer_driver_info_1
2716  ********************************************************************/
2717 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2718 {       
2719         NT_PRINTER_INFO_LEVEL *printer = NULL;
2720         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2721
2722         ZERO_STRUCT(driver);
2723
2724         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2725                 return ERROR_INVALID_PRINTER_NAME;
2726
2727         if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2728                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2729
2730         fill_printer_driver_info_1(info, driver, servername, architecture);
2731
2732         free_a_printer(&printer,2);
2733
2734         return NT_STATUS_NO_PROBLEMO;
2735 }
2736
2737 /********************************************************************
2738  * construct_printer_driver_info_2
2739  * fill a printer_info_2 struct
2740  ********************************************************************/
2741 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2742 {
2743         pstring temp_driverpath;
2744         pstring temp_datafile;
2745         pstring temp_configfile;
2746
2747         info->version=driver.info_3->cversion;
2748
2749         init_unistr( &info->name, driver.info_3->name );
2750         init_unistr( &info->architecture, driver.info_3->environment );
2751
2752         snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2753         init_unistr( &info->driverpath, temp_driverpath );
2754
2755         snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2756         init_unistr( &info->datafile, temp_datafile );
2757
2758         snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2759         init_unistr( &info->configfile, temp_configfile );      
2760 }
2761
2762 /********************************************************************
2763  * construct_printer_driver_info_2
2764  * fill a printer_info_2 struct
2765  ********************************************************************/
2766 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2767 {
2768         NT_PRINTER_INFO_LEVEL *printer = NULL;
2769         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2770
2771         ZERO_STRUCT(printer);
2772         ZERO_STRUCT(driver);
2773
2774         if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2775                 return ERROR_INVALID_PRINTER_NAME;
2776
2777         if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2778                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2779
2780         fill_printer_driver_info_2(info, driver, servername);
2781
2782         free_a_printer(&printer,2);
2783
2784         return NT_STATUS_NO_PROBLEMO;
2785 }
2786
2787 /********************************************************************
2788  * copy a strings array and convert to UNICODE
2789  *
2790  * convert an array of ascii string to a UNICODE string
2791  ********************************************************************/
2792 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2793 {
2794         int i=0;
2795         int j=0;
2796         char *v;
2797         pstring line;
2798
2799         DEBUG(6,("init_unistr_array\n"));
2800         *uni_array=NULL;
2801
2802         while (1) {
2803                 if (char_array == NULL)
2804                         v = "";
2805                 else {
2806                         v = char_array[i];
2807                         if (!v) v = ""; /* hack to handle null lists */
2808                 }
2809                 if (strlen(v) == 0) break;
2810                 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2811                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2812                 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2813                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
2814                         return;
2815                 }
2816                 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2817                 i++;
2818         }
2819         
2820         if (*uni_array) {
2821                 (*uni_array)[j]=0x0000;
2822         }
2823         
2824         DEBUGADD(6,("last one:done\n"));
2825 }
2826
2827 /********************************************************************
2828  * construct_printer_info_3
2829  * fill a printer_info_3 struct
2830  ********************************************************************/
2831 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2832 {
2833         pstring temp_driverpath;
2834         pstring temp_datafile;
2835         pstring temp_configfile;
2836         pstring temp_helpfile;
2837
2838         ZERO_STRUCTP(info);
2839
2840         info->version=driver.info_3->cversion;
2841
2842         init_unistr( &info->name, driver.info_3->name );        
2843         init_unistr( &info->architecture, driver.info_3->environment );
2844
2845         snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);                
2846         init_unistr( &info->driverpath, temp_driverpath );
2847
2848         snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2849         init_unistr( &info->datafile, temp_datafile );
2850
2851         snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2852         init_unistr( &info->configfile, temp_configfile );      
2853
2854         snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2855         init_unistr( &info->helpfile, temp_helpfile );
2856
2857         init_unistr( &info->monitorname, driver.info_3->monitorname );
2858         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2859
2860         info->dependentfiles=NULL;
2861         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2862 }
2863
2864 /********************************************************************
2865  * construct_printer_info_3
2866  * fill a printer_info_3 struct
2867  ********************************************************************/
2868 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2869 {       
2870         NT_PRINTER_INFO_LEVEL *printer = NULL;
2871         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2872         uint32 status=0;
2873         ZERO_STRUCT(driver);
2874
2875         status=get_a_printer(&printer, 2, lp_servicename(snum) );
2876         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2877         if (status != 0)
2878                 return ERROR_INVALID_PRINTER_NAME;
2879
2880         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
2881         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2882         if (status != 0) {
2883                 free_a_printer(&printer,2);
2884                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2885         }
2886
2887         fill_printer_driver_info_3(info, driver, servername);
2888
2889         free_a_printer(&printer,2);
2890
2891         return NT_STATUS_NO_PROBLEMO;
2892 }
2893
2894 /********************************************************************
2895  * construct_printer_info_6
2896  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2897  ********************************************************************/
2898
2899 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2900 {
2901         pstring temp_driverpath;
2902         pstring temp_datafile;
2903         pstring temp_configfile;
2904         pstring temp_helpfile;
2905         fstring nullstr;
2906
2907         ZERO_STRUCTP(info);
2908         memset(&nullstr, '\0', sizeof(fstring));
2909
2910         info->version=driver.info_3->cversion;
2911
2912         init_unistr( &info->name, driver.info_3->name );        
2913         init_unistr( &info->architecture, driver.info_3->environment );
2914
2915         snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);                
2916         init_unistr( &info->driverpath, temp_driverpath );
2917
2918         snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2919         init_unistr( &info->datafile, temp_datafile );
2920
2921         snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2922         init_unistr( &info->configfile, temp_configfile );      
2923
2924         snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2925         init_unistr( &info->helpfile, temp_helpfile );
2926
2927         init_unistr( &info->monitorname, driver.info_3->monitorname );
2928         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2929
2930         info->dependentfiles=NULL;
2931         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2932
2933         info->previousdrivernames=NULL;
2934         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2935
2936         info->driver_date.low=0;
2937         info->driver_date.high=0;
2938
2939         info->padding=0;
2940         info->driver_version_low=0;
2941         info->driver_version_high=0;
2942
2943         init_unistr( &info->mfgname, "");
2944         init_unistr( &info->oem_url, "");
2945         init_unistr( &info->hardware_id, "");
2946         init_unistr( &info->provider, "");
2947 }
2948
2949 /********************************************************************
2950  * construct_printer_info_6
2951  * fill a printer_info_6 struct
2952  ********************************************************************/
2953 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2954 {       
2955         NT_PRINTER_INFO_LEVEL *printer = NULL;
2956         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2957         uint32 status=0;
2958         ZERO_STRUCT(driver);
2959
2960         status=get_a_printer(&printer, 2, lp_servicename(snum) );
2961         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2962         if (status != 0)
2963                 return ERROR_INVALID_PRINTER_NAME;
2964
2965         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
2966         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2967         if (status != 0) {
2968                 /*
2969                  * Is this a W2k client ?
2970                  */
2971
2972                 if (version < 3) {
2973                         free_a_printer(&printer,2);
2974                         return ERROR_UNKNOWN_PRINTER_DRIVER;
2975                 }
2976
2977                 /* Yes - try again with a WinNT driver. */
2978                 version = 2;
2979                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
2980                 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2981                 if (status != 0) {
2982                         free_a_printer(&printer,2);
2983                         return ERROR_UNKNOWN_PRINTER_DRIVER;
2984                 }
2985         }
2986
2987         fill_printer_driver_info_6(info, driver, servername);
2988
2989         free_a_printer(&printer,2);
2990
2991         return NT_STATUS_NO_PROBLEMO;
2992 }
2993
2994 /****************************************************************************
2995 ****************************************************************************/
2996
2997 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2998 {
2999         safe_free(info->dependentfiles);
3000 }
3001
3002 /****************************************************************************
3003 ****************************************************************************/
3004
3005 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3006 {
3007         safe_free(info->dependentfiles);
3008         
3009 }
3010
3011 /****************************************************************************
3012 ****************************************************************************/
3013 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3014 {
3015         DRIVER_INFO_1 *info=NULL;
3016         uint32 status;
3017         
3018         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3019                 return ERROR_NOT_ENOUGH_MEMORY;
3020         
3021         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3022         if (status != NT_STATUS_NO_PROBLEMO) {
3023                 safe_free(info);
3024                 return status;
3025         }
3026
3027         /* check the required size. */  
3028         *needed += spoolss_size_printer_driver_info_1(info);
3029
3030         if (!alloc_buffer_size(buffer, *needed)) {
3031                 safe_free(info);
3032                 return ERROR_INSUFFICIENT_BUFFER;
3033         }
3034
3035         /* fill the buffer with the structures */
3036         new_smb_io_printer_driver_info_1("", buffer, info, 0);  
3037
3038         /* clear memory */
3039         safe_free(info);
3040
3041         if (*needed > offered)
3042                 return ERROR_INSUFFICIENT_BUFFER;
3043         else
3044                 return NT_STATUS_NO_PROBLEMO;
3045 }
3046
3047 /****************************************************************************
3048 ****************************************************************************/
3049 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3050 {
3051         DRIVER_INFO_2 *info=NULL;
3052         uint32 status;
3053         
3054         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3055                 return ERROR_NOT_ENOUGH_MEMORY;
3056         
3057         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3058         if (status != NT_STATUS_NO_PROBLEMO) {
3059                 safe_free(info);
3060                 return status;
3061         }
3062
3063         /* check the required size. */  
3064         *needed += spoolss_size_printer_driver_info_2(info);
3065
3066         if (!alloc_buffer_size(buffer, *needed)) {
3067                 safe_free(info);
3068                 return ERROR_INSUFFICIENT_BUFFER;
3069         }
3070
3071         /* fill the buffer with the structures */
3072         new_smb_io_printer_driver_info_2("", buffer, info, 0);  
3073
3074         /* clear memory */
3075         safe_free(info);
3076
3077         if (*needed > offered)
3078                 return ERROR_INSUFFICIENT_BUFFER;
3079         else
3080                 return NT_STATUS_NO_PROBLEMO;
3081 }
3082
3083 /****************************************************************************
3084 ****************************************************************************/
3085 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3086 {
3087         DRIVER_INFO_3 info;
3088         uint32 status;
3089
3090         ZERO_STRUCT(info);
3091
3092         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3093         if (status != NT_STATUS_NO_PROBLEMO) {
3094                 return status;
3095         }
3096
3097         /* check the required size. */  
3098         *needed += spoolss_size_printer_driver_info_3(&info);
3099
3100         if (!alloc_buffer_size(buffer, *needed)) {
3101                 free_printer_driver_info_3(&info);
3102                 return ERROR_INSUFFICIENT_BUFFER;
3103         }
3104
3105         /* fill the buffer with the structures */
3106         new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3107
3108         free_printer_driver_info_3(&info);
3109
3110         if (*needed > offered)
3111                 return ERROR_INSUFFICIENT_BUFFER;
3112         else
3113                 return NT_STATUS_NO_PROBLEMO;
3114 }
3115
3116 /****************************************************************************
3117 ****************************************************************************/
3118 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3119 {
3120         DRIVER_INFO_6 info;
3121         uint32 status;
3122
3123         ZERO_STRUCT(info);
3124
3125         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3126         if (status != NT_STATUS_NO_PROBLEMO) {
3127                 return status;
3128         }
3129
3130         /* check the required size. */  
3131         *needed += spoolss_size_printer_driver_info_6(&info);
3132
3133         if (!alloc_buffer_size(buffer, *needed)) {
3134                 free_printer_driver_info_6(&info);
3135                 return ERROR_INSUFFICIENT_BUFFER;
3136         }
3137
3138         /* fill the buffer with the structures */
3139         new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3140
3141         free_printer_driver_info_6(&info);
3142
3143         if (*needed > offered)
3144                 return ERROR_INSUFFICIENT_BUFFER;
3145         else
3146                 return NT_STATUS_NO_PROBLEMO;
3147 }
3148
3149 /****************************************************************************
3150 ****************************************************************************/
3151 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3152                                 uint32 clientmajorversion, uint32 clientminorversion,
3153                                 NEW_BUFFER *buffer, uint32 offered,
3154                                 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3155 {
3156         fstring servername;
3157         fstring architecture;
3158         int snum;
3159
3160         DEBUG(4,("_spoolss_getprinterdriver2\n"));
3161
3162         *needed=0;
3163         *servermajorversion=0;
3164         *serverminorversion=0;
3165
3166         pstrcpy(servername, global_myname);
3167         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3168
3169         if (!get_printer_snum(handle, &snum))
3170                 return ERROR_INVALID_HANDLE;
3171
3172         switch (level) {
3173         case 1:
3174                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3175         case 2:
3176                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3177         case 3:
3178                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3179         case 6:
3180                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3181         default:
3182                 return ERROR_INVALID_LEVEL;
3183         }
3184 }
3185
3186 /****************************************************************************
3187 ****************************************************************************/
3188 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3189 {
3190         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3191
3192         if (OPEN_HANDLE(Printer)) {
3193                 Printer->page_started=True;
3194                 return 0x0;
3195         }
3196
3197         DEBUG(3,("Error in startpageprinter printer handle\n"));
3198         return ERROR_INVALID_HANDLE;
3199 }
3200
3201 /****************************************************************************
3202 ****************************************************************************/
3203 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3204 {
3205         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3206
3207         if (!OPEN_HANDLE(Printer)) {
3208                 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3209                 return ERROR_INVALID_HANDLE;
3210         }
3211         
3212         Printer->page_started=False;
3213
3214         return NT_STATUS_NO_PROBLEMO;
3215 }
3216
3217 /****************************************************************************
3218  Return a user struct for a pipe user.
3219 ****************************************************************************/
3220
3221 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3222 {
3223         if (p->ntlmssp_auth_validated) {
3224                 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3225         } else {
3226                 extern struct current_user current_user;
3227                 memcpy(user, &current_user, sizeof(struct current_user));
3228         }
3229
3230         return user;
3231 }
3232
3233 /********************************************************************
3234  * api_spoolss_getprinter
3235  * called from the spoolss dispatcher
3236  *
3237  ********************************************************************/
3238 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3239                                 pipes_struct *p, DOC_INFO *docinfo,
3240                                 uint32 *jobid)
3241 {
3242         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3243         int snum;
3244         pstring jobname;
3245         fstring datatype;
3246         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3247         struct current_user user;
3248
3249         if (!OPEN_HANDLE(Printer)) {
3250                 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3251                 return ERROR_INVALID_HANDLE;
3252         }
3253
3254         get_current_user(&user, p);
3255
3256         /*
3257          * a nice thing with NT is it doesn't listen to what you tell it.
3258          * when asked to send _only_ RAW datas, it tries to send datas
3259          * in EMF format.
3260          *
3261          * So I add checks like in NT Server ...
3262          *
3263          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
3264          * there's a bug in NT client-side code, so we'll fix it in the
3265          * server-side code. *nnnnnggggh!*
3266          */
3267         
3268         if (info_1->p_datatype != 0) {
3269                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3270                 if (strcmp(datatype, "RAW") != 0) {
3271                         (*jobid)=0;
3272                         return ERROR_INVALID_DATATYPE;
3273                 }               
3274         }               
3275         
3276         /* get the share number of the printer */
3277         if (!get_printer_snum(handle, &snum)) {
3278                 return ERROR_INVALID_HANDLE;
3279         }
3280
3281         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3282         
3283         Printer->jobid = print_job_start(&user, snum, jobname);
3284
3285         /* An error occured in print_job_start() so return an appropriate
3286            NT error code. */
3287
3288         if (Printer->jobid == -1) {
3289                 return map_nt_error_from_unix(errno);
3290         }
3291         
3292         Printer->document_started=True;
3293         (*jobid) = Printer->jobid;
3294
3295         srv_spoolss_sendnotify(handle);
3296         return 0x0;
3297 }
3298
3299 /********************************************************************
3300  * api_spoolss_getprinter
3301  * called from the spoolss dispatcher
3302  *
3303  ********************************************************************/
3304 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3305 {
3306         Printer_entry *Printer=find_printer_index_by_hnd(handle);
3307         
3308         if (!OPEN_HANDLE(Printer)) {
3309                 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3310                 return ERROR_INVALID_HANDLE;
3311         }
3312         
3313         Printer->document_started=False;
3314         print_job_end(Printer->jobid);
3315         /* error codes unhandled so far ... */
3316
3317         srv_spoolss_sendnotify(handle);
3318
3319         return 0x0;
3320 }
3321
3322 /****************************************************************************
3323 ****************************************************************************/
3324 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3325                                 uint32 buffer_size,
3326                                 uint8 *buffer,
3327                                 uint32 *buffer_written)
3328 {
3329         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3330         
3331         if (!OPEN_HANDLE(Printer)) {
3332                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3333                 return ERROR_INVALID_HANDLE;
3334         }
3335
3336         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3337                                             buffer_size);
3338
3339         return 0x0;
3340 }
3341
3342 /********************************************************************
3343  * api_spoolss_getprinter
3344  * called from the spoolss dispatcher
3345  *
3346  ********************************************************************/
3347 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3348                               pipes_struct *p)
3349 {
3350         struct current_user user;
3351         int snum, errcode = ERROR_INVALID_FUNCTION;
3352         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3353
3354         get_current_user(&user, p);
3355
3356         if (!OPEN_HANDLE(Printer)) {
3357                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3358                 return ERROR_INVALID_HANDLE;
3359         }
3360
3361         if (!get_printer_snum(handle, &snum))
3362                 return ERROR_INVALID_HANDLE;
3363
3364         switch (command) {
3365         case PRINTER_CONTROL_PAUSE:
3366                 if (print_queue_pause(&user, snum, &errcode)) {
3367                         errcode = 0;
3368                 }
3369                 break;
3370         case PRINTER_CONTROL_RESUME:
3371         case PRINTER_CONTROL_UNPAUSE:
3372                 if (print_queue_resume(&user, snum, &errcode)) {
3373                         errcode = 0;
3374                 }
3375                 break;
3376         case PRINTER_CONTROL_PURGE:
3377                 if (print_queue_purge(&user, snum, &errcode)) {
3378                         errcode = 0;
3379                 }
3380                 break;
3381         default:
3382                 return ERROR_INVALID_LEVEL;
3383         }
3384
3385         return errcode;
3386 }
3387
3388 /********************************************************************
3389  * api_spoolss_abortprinter
3390  ********************************************************************/
3391
3392 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3393 {
3394         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3395 }
3396
3397 /********************************************************************
3398  * called by spoolss_api_setprinter
3399  * when updating a printer description
3400  ********************************************************************/
3401 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3402                                  const SPOOL_PRINTER_INFO_LEVEL *info,
3403                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3404 {
3405         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3406         struct current_user user;
3407         uint32 result;
3408         int snum;
3409
3410         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3411
3412         if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3413                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3414                          OUR_HANDLE(handle)));
3415
3416                 result = ERROR_INVALID_HANDLE;
3417                 goto done;
3418         }
3419
3420         /* NT seems to like setting the security descriptor even though
3421            nothing may have actually changed.  This causes annoying
3422            dialog boxes when the user doesn't have permission to change
3423            the security descriptor. */
3424
3425         nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3426
3427         if (DEBUGLEVEL >= 10) {
3428                 SEC_ACL *acl;
3429                 int i;
3430
3431                 acl = old_secdesc_ctr->sec->dacl;
3432                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
3433                            PRINTERNAME(snum), acl->num_aces));
3434
3435                 for (i = 0; i < acl->num_aces; i++) {
3436                         fstring sid_str;
3437
3438                         sid_to_string(sid_str, &acl->ace[i].sid);
3439
3440                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
3441                                   acl->ace[i].info.mask));
3442                 }
3443
3444                 acl = secdesc_ctr->sec->dacl;
3445
3446                 if (acl) {
3447                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
3448                                    PRINTERNAME(snum), acl->num_aces));
3449
3450                         for (i = 0; i < acl->num_aces; i++) {
3451                                 fstring sid_str;
3452                                 
3453                                 sid_to_string(sid_str, &acl->ace[i].sid);
3454                                 
3455                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
3456                                            acl->ace[i].info.mask));
3457                         }
3458                 } else {
3459                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3460                 }
3461         }
3462
3463         new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3464
3465         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3466                 result = NT_STATUS_NO_PROBLEMO;
3467                 goto done;
3468         }
3469
3470         /* Work out which user is performing the operation */
3471
3472         get_current_user(&user, p);
3473
3474         /* Check the user has permissions to change the security
3475            descriptor.  By experimentation with two NT machines, the user
3476            requires Full Access to the printer to change security
3477            information. */
3478
3479         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3480                 result = ERROR_ACCESS_DENIED;
3481                 goto done;
3482         }
3483
3484         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3485
3486  done:
3487         free_sec_desc_buf(&new_secdesc_ctr);
3488         free_sec_desc_buf(&old_secdesc_ctr);
3489
3490         return result;
3491 }
3492
3493 /********************************************************************
3494  Do Samba sanity checks on a printer info struct.
3495  this has changed purpose: it now "canonicalises" printer
3496  info from a client rather than just checking it is correct
3497  ********************************************************************/
3498
3499 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3500 {
3501         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3502                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3503
3504         /* we force some elements to "correct" values */
3505         slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3506         slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3507                  global_myname, lp_servicename(snum));
3508         fstrcpy(info->sharename, lp_servicename(snum));
3509         info->attributes = PRINTER_ATTRIBUTE_SHARED   \
3510                 | PRINTER_ATTRIBUTE_LOCAL  \
3511                 | PRINTER_ATTRIBUTE_RAW_ONLY \
3512                 | PRINTER_ATTRIBUTE_QUEUED ;
3513         
3514         return True;
3515 }
3516
3517 /****************************************************************************
3518 ****************************************************************************/
3519 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3520 {
3521         pid_t local_pid = sys_getpid();
3522         char *cmd = lp_addprinter_cmd();
3523         char *path;
3524         char **qlines;
3525         pstring tmp_file;
3526         pstring command;
3527         pstring driverlocation;
3528         int numlines;
3529         int ret;
3530
3531         if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3532                 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3533         else
3534                 path = tmpdir();
3535
3536         /* build driver path... only 9X architecture is needed for legacy reasons */
3537         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3538                         global_myname);
3539         /* change \ to \\ for the shell */
3540         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3541         
3542         slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3543         slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3544                         cmd, printer->info_2->printername, printer->info_2->sharename,
3545                         printer->info_2->portname, printer->info_2->drivername,
3546                         printer->info_2->location, driverlocation);
3547
3548         unlink(tmp_file);
3549
3550         /* Convert script args to unix-codepage */
3551         dos_to_unix(command, True);
3552         DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3553         ret = smbrun(command, tmp_file, False);
3554         DEBUGADD(10,("returned [%d]\n", ret));
3555
3556         if ( ret != 0 ) {
3557                 unlink(tmp_file);
3558                 return False;
3559         }
3560
3561         numlines = 0;
3562         /* Get lines and convert them back to dos-codepage */
3563         qlines = file_lines_load(tmp_file, &numlines, True);
3564         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3565         DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3566         unlink(tmp_file);
3567
3568         if(numlines) {
3569                 /* Set the portname to what the script says the portname should be. */
3570                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3571                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3572
3573                 /* Send SIGHUP to process group... is there a better way? */
3574                 kill(0, SIGHUP);
3575                 add_all_printers();
3576         }
3577
3578         file_lines_free(qlines);
3579         return True;
3580 }
3581
3582 /* Return true if two devicemodes are equal */
3583
3584 #define DEVMODE_CHECK_INT(field) \
3585     if (d1->field != d2->field) { \
3586         DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3587             d1->field, d2->field)); \
3588         return False; \
3589     }
3590
3591 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3592 {
3593         if (!d1 && !d2) goto equal;  /* if both are NULL they are equal */
3594
3595         if (!d1 ^ !d2) {
3596                 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3597                 return False; /* if either is exclusively NULL are not equal */
3598         }
3599
3600         if (!strequal(d1->devicename, d2->devicename) ||
3601             !strequal(d1->formname, d2->formname)) {
3602                 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3603                 return False;
3604         }
3605
3606         DEVMODE_CHECK_INT(specversion);
3607         DEVMODE_CHECK_INT(driverversion);
3608         DEVMODE_CHECK_INT(driverextra);
3609         DEVMODE_CHECK_INT(orientation);
3610         DEVMODE_CHECK_INT(papersize);
3611         DEVMODE_CHECK_INT(paperlength);
3612         DEVMODE_CHECK_INT(paperwidth);
3613         DEVMODE_CHECK_INT(scale);
3614         DEVMODE_CHECK_INT(copies);
3615         DEVMODE_CHECK_INT(defaultsource);
3616         DEVMODE_CHECK_INT(printquality);
3617         DEVMODE_CHECK_INT(color);
3618         DEVMODE_CHECK_INT(duplex);
3619         DEVMODE_CHECK_INT(yresolution);
3620         DEVMODE_CHECK_INT(ttoption);
3621         DEVMODE_CHECK_INT(collate);
3622         DEVMODE_CHECK_INT(logpixels);
3623
3624         DEVMODE_CHECK_INT(fields);
3625         DEVMODE_CHECK_INT(bitsperpel);
3626         DEVMODE_CHECK_INT(pelswidth);
3627         DEVMODE_CHECK_INT(pelsheight);
3628         DEVMODE_CHECK_INT(displayflags);
3629         DEVMODE_CHECK_INT(displayfrequency);
3630         DEVMODE_CHECK_INT(icmmethod);
3631         DEVMODE_CHECK_INT(icmintent);
3632         DEVMODE_CHECK_INT(mediatype);
3633         DEVMODE_CHECK_INT(dithertype);
3634         DEVMODE_CHECK_INT(reserved1);
3635         DEVMODE_CHECK_INT(reserved2);
3636         DEVMODE_CHECK_INT(panningwidth);
3637         DEVMODE_CHECK_INT(panningheight);
3638
3639         /* compare the private data if it exists */
3640         if (!d1->driverextra && !d2->driverextra) goto equal;
3641
3642
3643         DEVMODE_CHECK_INT(driverextra);
3644
3645         if (memcmp(d1->private, d2->private, d1->driverextra)) {
3646                 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
3647                 return False;
3648         }
3649
3650  equal:
3651         DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
3652         return True;
3653 }
3654
3655 /* Return true if two NT_PRINTER_PARAM structures are equal */
3656
3657 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3658                                    NT_PRINTER_PARAM *p2)
3659 {
3660         if (!p1 && !p2) goto equal;
3661
3662         if ((!p1 && p2) || (p1 && !p2)) {
3663                 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
3664                 return False;
3665         }
3666
3667         /* Compare lists of printer parameters */
3668
3669         while (p1) {
3670                 BOOL found = False;
3671                 NT_PRINTER_PARAM *q = p1;
3672
3673                 /* Find the parameter in the second structure */
3674
3675                 while(q) {
3676
3677                         if (strequal(p1->value, q->value)) {
3678
3679                                 if (p1->type != q->type) {
3680                                         DEBUG(10, ("nt_printer_param_equal():"
3681                                                    "types for %s differ (%d != %d)\n",
3682                                                    p1->value, p1->type,
3683                                                    q->type));
3684                                         break;
3685                                 }
3686
3687                                 if (p1->data_len != q->data_len) {
3688                                         DEBUG(10, ("nt_printer_param_equal():"
3689                                                    "len for %s differs (%d != %d)\n",
3690                                                    p1->value, p1->data_len,
3691                                                    q->data_len));
3692                                         break;
3693                                 }
3694
3695                                 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
3696                                         found = True;
3697                                 } else {
3698                                         DEBUG(10, ("nt_printer_param_equal():"
3699                                                    "data for %s differs\n", p1->value));
3700                                 }
3701
3702                                 break;
3703                         }
3704
3705                         q = q->next;
3706                 }
3707
3708                 if (!found) {
3709                         DEBUG(10, ("nt_printer_param_equal(): param %s "
3710                                    "does not exist\n", p1->value));
3711                         return False;
3712                 }
3713
3714                 p1 = p1->next;
3715         }
3716
3717         equal:
3718
3719         DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
3720         return True;
3721 }
3722
3723 /********************************************************************
3724  * Called by update_printer when trying to work out whether to
3725  * actually update printer info.
3726  ********************************************************************/
3727
3728 #define PI_CHECK_INT(field) \
3729     if (pi1->field != pi2->field) { \
3730         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
3731             pi1->field, pi2->field)); \
3732         return False; \
3733     }
3734
3735 #define PI_CHECK_STR(field) \
3736     if (!strequal(pi1->field, pi2->field)) { \
3737         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
3738             pi1->field, pi2->field)); \
3739         return False; \
3740     }
3741
3742 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3743                                         NT_PRINTER_INFO_LEVEL *p2)
3744 {
3745         NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3746
3747         /* Trivial conditions */
3748
3749         if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3750                 goto equal;
3751         }
3752
3753         if ((!p1 && p2) || (p1 && !p2) ||
3754             (!p1->info_2 && p2->info_2) ||
3755             (p1->info_2 && !p2->info_2)) {
3756                 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
3757                            "differ\n"));
3758                 return False;
3759         }
3760
3761         /* Compare two nt_printer_info_level structures.  Don't compare
3762            status or cjobs as they seem to have something to do with the
3763            printer queue. */
3764
3765         pi1 = p1->info_2;
3766         pi2 = p2->info_2;
3767
3768         PI_CHECK_INT(attributes);
3769         PI_CHECK_INT(priority);
3770         PI_CHECK_INT(default_priority);
3771         PI_CHECK_INT(starttime);
3772         PI_CHECK_INT(untiltime);
3773         PI_CHECK_INT(averageppm);
3774
3775         /* Yuck - don't check the printername or servername as the
3776            add_a_printer() code plays games with them.  You can't
3777            change the printername or the sharename through this interface
3778            in Samba. */
3779
3780         PI_CHECK_STR(sharename);
3781         PI_CHECK_STR(portname);
3782         PI_CHECK_STR(drivername);
3783         PI_CHECK_STR(comment);
3784         PI_CHECK_STR(location);
3785
3786         if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3787                 return False;
3788         }
3789
3790         PI_CHECK_STR(sepfile);
3791         PI_CHECK_STR(printprocessor);
3792         PI_CHECK_STR(datatype);
3793         PI_CHECK_STR(parameters);
3794
3795         if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3796                 return False;
3797         }
3798
3799         if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3800                 return False;
3801         }
3802
3803         PI_CHECK_INT(changeid);
3804         PI_CHECK_INT(c_setprinter);
3805         PI_CHECK_INT(setuptime);
3806
3807  equal:
3808         DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
3809         return True;
3810 }
3811
3812 /********************************************************************
3813  * called by spoolss_api_setprinter
3814  * when updating a printer description
3815  ********************************************************************/
3816
3817 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3818                            const SPOOL_PRINTER_INFO_LEVEL *info,
3819                            DEVICEMODE *devmode)
3820 {
3821         int snum;
3822         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3823         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3824         uint32 result;
3825
3826         DEBUG(8,("update_printer\n"));
3827         
3828         result = NT_STATUS_NO_PROBLEMO;
3829
3830         if (level!=2) {
3831                 DEBUG(0,("Send a mail to samba@samba.org\n"));
3832                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3833                 result = ERROR_INVALID_LEVEL;
3834                 goto done;
3835         }
3836
3837         if (!OPEN_HANDLE(Printer)) {
3838                 result = ERROR_INVALID_HANDLE;
3839                 goto done;
3840         }
3841
3842         if (!get_printer_snum(handle, &snum)) {
3843                 result = ERROR_INVALID_HANDLE;
3844                 goto done;
3845         }
3846
3847         if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3848            (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3849                 result = ERROR_INVALID_HANDLE;
3850                 goto done;
3851         }
3852
3853         DEBUGADD(8,("Converting info_2 struct\n"));
3854
3855         /*
3856          * convert_printer_info converts the incoming
3857          * info from the client and overwrites the info
3858          * just read from the tdb in the pointer 'printer'.
3859          */
3860
3861         convert_printer_info(info, printer, level);
3862
3863         if (info->info_2->devmode_ptr != 0) {
3864                 /* we have a valid devmode
3865                    convert it and link it*/
3866
3867                 /*
3868                  * Ensure printer->info_2->devmode is a valid pointer
3869                  * as we will be overwriting it in convert_devicemode().
3870                  */
3871                 
3872                 if (printer->info_2->devmode == NULL)
3873                         printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3874
3875                 DEBUGADD(8,("Converting the devicemode struct\n"));
3876                 convert_devicemode(devmode, printer->info_2->devmode);
3877
3878         } else {
3879                 if (printer->info_2->devmode != NULL)
3880                         free_nt_devicemode(&printer->info_2->devmode);
3881                 printer->info_2->devmode=NULL;
3882         }
3883
3884         /* Do sanity check on the requested changes for Samba */
3885
3886         if (!check_printer_ok(printer->info_2, snum)) {
3887                 result = ERROR_INVALID_PARAMETER;
3888                 goto done;
3889         }
3890
3891         /* NT likes to call this function even though nothing has actually
3892            changed.  Check this so the user doesn't end up with an
3893            annoying permission denied dialog box. */
3894
3895         if (nt_printer_info_level_equal(printer, old_printer)) {
3896                 DEBUG(3, ("printer info has not changed\n"));
3897                 result = NT_STATUS_NO_PROBLEMO;
3898                 goto done;
3899         }
3900
3901         /* Check calling user has permission to update printer description */
3902
3903         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {