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