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