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