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