Changes from APPLIANCE_HEAD:
[nivanova/samba-autobuild/.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;
2744
2745         info->version=driver.info_3->cversion;
2746
2747         init_unistr( &info->name, driver.info_3->name );
2748         init_unistr( &info->architecture, driver.info_3->environment );
2749
2750
2751     if (strlen(driver.info_3->driverpath)) {
2752                 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2753                 init_unistr( &info->driverpath, temp );
2754     } else
2755         init_unistr( &info->driverpath, "" );
2756
2757         if (strlen(driver.info_3->datafile)) {
2758                 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2759                 init_unistr( &info->datafile, temp );
2760         } else
2761                 init_unistr( &info->datafile, "" );
2762         
2763         if (strlen(driver.info_3->configfile)) {
2764                 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2765                 init_unistr( &info->configfile, temp ); 
2766         } else
2767                 init_unistr( &info->configfile, "" );
2768 }
2769
2770 /********************************************************************
2771  * construct_printer_driver_info_2
2772  * fill a printer_info_2 struct
2773  ********************************************************************/
2774 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2775 {
2776         NT_PRINTER_INFO_LEVEL *printer = NULL;
2777         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2778
2779         ZERO_STRUCT(printer);
2780         ZERO_STRUCT(driver);
2781
2782         if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2783                 return ERROR_INVALID_PRINTER_NAME;
2784
2785         if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2786                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2787
2788         fill_printer_driver_info_2(info, driver, servername);
2789
2790         free_a_printer(&printer,2);
2791
2792         return NT_STATUS_NO_PROBLEMO;
2793 }
2794
2795 /********************************************************************
2796  * copy a strings array and convert to UNICODE
2797  *
2798  * convert an array of ascii string to a UNICODE string
2799  ********************************************************************/
2800 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2801 {
2802         int i=0;
2803         int j=0;
2804         char *v;
2805         pstring line;
2806
2807         DEBUG(6,("init_unistr_array\n"));
2808         *uni_array=NULL;
2809
2810         while (1) {
2811                 if (char_array == NULL)
2812                         v = "";
2813                 else {
2814                         v = char_array[i];
2815                         if (!v) v = ""; /* hack to handle null lists */
2816                 }
2817                 if (strlen(v) == 0) break;
2818                 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2819                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2820                 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2821                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
2822                         return;
2823                 }
2824                 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2825                 i++;
2826         }
2827         
2828         if (*uni_array) {
2829                 (*uni_array)[j]=0x0000;
2830         }
2831         
2832         DEBUGADD(6,("last one:done\n"));
2833 }
2834
2835 /********************************************************************
2836  * construct_printer_info_3
2837  * fill a printer_info_3 struct
2838  ********************************************************************/
2839 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2840 {
2841         pstring temp;
2842
2843         ZERO_STRUCTP(info);
2844
2845         info->version=driver.info_3->cversion;
2846
2847         init_unistr( &info->name, driver.info_3->name );        
2848         init_unistr( &info->architecture, driver.info_3->environment );
2849
2850     if (strlen(driver.info_3->driverpath)) {
2851         snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
2852         init_unistr( &info->driverpath, temp );
2853     } else
2854         init_unistr( &info->driverpath, "" );
2855     
2856     if (strlen(driver.info_3->datafile)) {
2857         snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2858         init_unistr( &info->datafile, temp );
2859     } else
2860         init_unistr( &info->datafile, "" );
2861
2862     if (strlen(driver.info_3->configfile)) {
2863         snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2864         init_unistr( &info->configfile, temp ); 
2865     } else
2866         init_unistr( &info->configfile, "" );
2867
2868     if (strlen(driver.info_3->helpfile)) {
2869         snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2870         init_unistr( &info->helpfile, temp );
2871     } else
2872         init_unistr( &info->helpfile, "" );
2873
2874         init_unistr( &info->monitorname, driver.info_3->monitorname );
2875         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2876
2877         info->dependentfiles=NULL;
2878         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2879 }
2880
2881 /********************************************************************
2882  * construct_printer_info_3
2883  * fill a printer_info_3 struct
2884  ********************************************************************/
2885 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2886 {       
2887         NT_PRINTER_INFO_LEVEL *printer = NULL;
2888         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2889         uint32 status=0;
2890         ZERO_STRUCT(driver);
2891
2892         status=get_a_printer(&printer, 2, lp_servicename(snum) );
2893         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2894         if (status != 0)
2895                 return ERROR_INVALID_PRINTER_NAME;
2896
2897         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
2898         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2899         if (status != 0) {
2900                 free_a_printer(&printer,2);
2901                 return ERROR_UNKNOWN_PRINTER_DRIVER;
2902         }
2903
2904         fill_printer_driver_info_3(info, driver, servername);
2905
2906         free_a_printer(&printer,2);
2907
2908         return NT_STATUS_NO_PROBLEMO;
2909 }
2910
2911 /********************************************************************
2912  * construct_printer_info_6
2913  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2914  ********************************************************************/
2915
2916 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2917 {
2918         pstring temp;
2919         fstring nullstr;
2920
2921         ZERO_STRUCTP(info);
2922         memset(&nullstr, '\0', sizeof(fstring));
2923
2924         info->version=driver.info_3->cversion;
2925
2926         init_unistr( &info->name, driver.info_3->name );        
2927         init_unistr( &info->architecture, driver.info_3->environment );
2928
2929         if (strlen(driver.info_3->driverpath)) {
2930                 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
2931                 init_unistr( &info->driverpath, temp );
2932         } else
2933                 init_unistr( &info->driverpath, "" );
2934
2935         if (strlen(driver.info_3->datafile)) {
2936                 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2937                 init_unistr( &info->datafile, temp );
2938         } else
2939                 init_unistr( &info->datafile, "" );
2940
2941         if (strlen(driver.info_3->configfile)) {
2942                 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2943                 init_unistr( &info->configfile, temp ); 
2944         } else
2945                 init_unistr( &info->configfile, "" );
2946
2947         if (strlen(driver.info_3->helpfile)) {
2948                 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2949                 init_unistr( &info->helpfile, temp );
2950         } else
2951                 init_unistr( &info->helpfile, "" );
2952         
2953         init_unistr( &info->monitorname, driver.info_3->monitorname );
2954         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2955
2956         info->dependentfiles=NULL;
2957         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2958
2959         info->previousdrivernames=NULL;
2960         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2961
2962         info->driver_date.low=0;
2963         info->driver_date.high=0;
2964
2965         info->padding=0;
2966         info->driver_version_low=0;
2967         info->driver_version_high=0;
2968
2969         init_unistr( &info->mfgname, "");
2970         init_unistr( &info->oem_url, "");
2971         init_unistr( &info->hardware_id, "");
2972         init_unistr( &info->provider, "");
2973 }
2974
2975 /********************************************************************
2976  * construct_printer_info_6
2977  * fill a printer_info_6 struct
2978  ********************************************************************/
2979 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2980 {       
2981         NT_PRINTER_INFO_LEVEL *printer = NULL;
2982         NT_PRINTER_DRIVER_INFO_LEVEL driver;
2983         uint32 status=0;
2984         ZERO_STRUCT(driver);
2985
2986         status=get_a_printer(&printer, 2, lp_servicename(snum) );
2987         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2988         if (status != 0)
2989                 return ERROR_INVALID_PRINTER_NAME;
2990
2991         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
2992         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2993         if (status != 0) {
2994                 /*
2995                  * Is this a W2k client ?
2996                  */
2997
2998                 if (version < 3) {
2999                         free_a_printer(&printer,2);
3000                         return ERROR_UNKNOWN_PRINTER_DRIVER;
3001                 }
3002
3003                 /* Yes - try again with a WinNT driver. */
3004                 version = 2;
3005                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3006                 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3007                 if (status != 0) {
3008                         free_a_printer(&printer,2);
3009                         return ERROR_UNKNOWN_PRINTER_DRIVER;
3010                 }
3011         }
3012
3013         fill_printer_driver_info_6(info, driver, servername);
3014
3015         free_a_printer(&printer,2);
3016
3017         return NT_STATUS_NO_PROBLEMO;
3018 }
3019
3020 /****************************************************************************
3021 ****************************************************************************/
3022
3023 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3024 {
3025         safe_free(info->dependentfiles);
3026 }
3027
3028 /****************************************************************************
3029 ****************************************************************************/
3030
3031 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3032 {
3033         safe_free(info->dependentfiles);
3034         
3035 }
3036
3037 /****************************************************************************
3038 ****************************************************************************/
3039 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3040 {
3041         DRIVER_INFO_1 *info=NULL;
3042         uint32 status;
3043         
3044         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3045                 return ERROR_NOT_ENOUGH_MEMORY;
3046         
3047         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3048         if (status != NT_STATUS_NO_PROBLEMO) {
3049                 safe_free(info);
3050                 return status;
3051         }
3052
3053         /* check the required size. */  
3054         *needed += spoolss_size_printer_driver_info_1(info);
3055
3056         if (!alloc_buffer_size(buffer, *needed)) {
3057                 safe_free(info);
3058                 return ERROR_INSUFFICIENT_BUFFER;
3059         }
3060
3061         /* fill the buffer with the structures */
3062         new_smb_io_printer_driver_info_1("", buffer, info, 0);  
3063
3064         /* clear memory */
3065         safe_free(info);
3066
3067         if (*needed > offered)
3068                 return ERROR_INSUFFICIENT_BUFFER;
3069         else
3070                 return NT_STATUS_NO_PROBLEMO;
3071 }
3072
3073 /****************************************************************************
3074 ****************************************************************************/
3075 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3076 {
3077         DRIVER_INFO_2 *info=NULL;
3078         uint32 status;
3079         
3080         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3081                 return ERROR_NOT_ENOUGH_MEMORY;
3082         
3083         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3084         if (status != NT_STATUS_NO_PROBLEMO) {
3085                 safe_free(info);
3086                 return status;
3087         }
3088
3089         /* check the required size. */  
3090         *needed += spoolss_size_printer_driver_info_2(info);
3091
3092         if (!alloc_buffer_size(buffer, *needed)) {
3093                 safe_free(info);
3094                 return ERROR_INSUFFICIENT_BUFFER;
3095         }
3096
3097         /* fill the buffer with the structures */
3098         new_smb_io_printer_driver_info_2("", buffer, info, 0);  
3099
3100         /* clear memory */
3101         safe_free(info);
3102
3103         if (*needed > offered)
3104                 return ERROR_INSUFFICIENT_BUFFER;
3105         else
3106                 return NT_STATUS_NO_PROBLEMO;
3107 }
3108
3109 /****************************************************************************
3110 ****************************************************************************/
3111 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3112 {
3113         DRIVER_INFO_3 info;
3114         uint32 status;
3115
3116         ZERO_STRUCT(info);
3117
3118         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3119         if (status != NT_STATUS_NO_PROBLEMO) {
3120                 return status;
3121         }
3122
3123         /* check the required size. */  
3124         *needed += spoolss_size_printer_driver_info_3(&info);
3125
3126         if (!alloc_buffer_size(buffer, *needed)) {
3127                 free_printer_driver_info_3(&info);
3128                 return ERROR_INSUFFICIENT_BUFFER;
3129         }
3130
3131         /* fill the buffer with the structures */
3132         new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3133
3134         free_printer_driver_info_3(&info);
3135
3136         if (*needed > offered)
3137                 return ERROR_INSUFFICIENT_BUFFER;
3138         else
3139                 return NT_STATUS_NO_PROBLEMO;
3140 }
3141
3142 /****************************************************************************
3143 ****************************************************************************/
3144 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3145 {
3146         DRIVER_INFO_6 info;
3147         uint32 status;
3148
3149         ZERO_STRUCT(info);
3150
3151         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3152         if (status != NT_STATUS_NO_PROBLEMO) {
3153                 return status;
3154         }
3155
3156         /* check the required size. */  
3157         *needed += spoolss_size_printer_driver_info_6(&info);
3158
3159         if (!alloc_buffer_size(buffer, *needed)) {
3160                 free_printer_driver_info_6(&info);
3161                 return ERROR_INSUFFICIENT_BUFFER;
3162         }
3163
3164         /* fill the buffer with the structures */
3165         new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3166
3167         free_printer_driver_info_6(&info);
3168
3169         if (*needed > offered)
3170                 return ERROR_INSUFFICIENT_BUFFER;
3171         else
3172                 return NT_STATUS_NO_PROBLEMO;
3173 }
3174
3175 /****************************************************************************
3176 ****************************************************************************/
3177 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3178                                 uint32 clientmajorversion, uint32 clientminorversion,
3179                                 NEW_BUFFER *buffer, uint32 offered,
3180                                 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3181 {
3182         fstring servername;
3183         fstring architecture;
3184         int snum;
3185
3186         DEBUG(4,("_spoolss_getprinterdriver2\n"));
3187
3188         *needed=0;
3189         *servermajorversion=0;
3190         *serverminorversion=0;
3191
3192         pstrcpy(servername, global_myname);
3193         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3194
3195         if (!get_printer_snum(handle, &snum))
3196                 return ERROR_INVALID_HANDLE;
3197
3198         switch (level) {
3199         case 1:
3200                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3201         case 2:
3202                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3203         case 3:
3204                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3205         case 6:
3206                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3207         default:
3208                 return ERROR_INVALID_LEVEL;
3209         }
3210 }
3211
3212 /****************************************************************************
3213 ****************************************************************************/
3214 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3215 {
3216         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3217
3218         if (OPEN_HANDLE(Printer)) {
3219                 Printer->page_started=True;
3220                 return 0x0;
3221         }
3222
3223         DEBUG(3,("Error in startpageprinter printer handle\n"));
3224         return ERROR_INVALID_HANDLE;
3225 }
3226
3227 /****************************************************************************
3228 ****************************************************************************/
3229 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3230 {
3231         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3232
3233         if (!OPEN_HANDLE(Printer)) {
3234                 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3235                 return ERROR_INVALID_HANDLE;
3236         }
3237         
3238         Printer->page_started=False;
3239
3240         return NT_STATUS_NO_PROBLEMO;
3241 }
3242
3243 /****************************************************************************
3244  Return a user struct for a pipe user.
3245 ****************************************************************************/
3246
3247 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3248 {
3249         if (p->ntlmssp_auth_validated) {
3250                 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3251         } else {
3252                 extern struct current_user current_user;
3253                 memcpy(user, &current_user, sizeof(struct current_user));
3254         }
3255
3256         return user;
3257 }
3258
3259 /********************************************************************
3260  * api_spoolss_getprinter
3261  * called from the spoolss dispatcher
3262  *
3263  ********************************************************************/
3264 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3265                                 pipes_struct *p, DOC_INFO *docinfo,
3266                                 uint32 *jobid)
3267 {
3268         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3269         int snum;
3270         pstring jobname;
3271         fstring datatype;
3272         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3273         struct current_user user;
3274
3275         if (!OPEN_HANDLE(Printer)) {
3276                 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3277                 return ERROR_INVALID_HANDLE;
3278         }
3279
3280         get_current_user(&user, p);
3281
3282         /*
3283          * a nice thing with NT is it doesn't listen to what you tell it.
3284          * when asked to send _only_ RAW datas, it tries to send datas
3285          * in EMF format.
3286          *
3287          * So I add checks like in NT Server ...
3288          *
3289          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
3290          * there's a bug in NT client-side code, so we'll fix it in the
3291          * server-side code. *nnnnnggggh!*
3292          */
3293         
3294         if (info_1->p_datatype != 0) {
3295                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3296                 if (strcmp(datatype, "RAW") != 0) {
3297                         (*jobid)=0;
3298                         return ERROR_INVALID_DATATYPE;
3299                 }               
3300         }               
3301         
3302         /* get the share number of the printer */
3303         if (!get_printer_snum(handle, &snum)) {
3304                 return ERROR_INVALID_HANDLE;
3305         }
3306
3307         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3308         
3309         Printer->jobid = print_job_start(&user, snum, jobname);
3310
3311         /* An error occured in print_job_start() so return an appropriate
3312            NT error code. */
3313
3314         if (Printer->jobid == -1) {
3315                 return map_nt_error_from_unix(errno);
3316         }
3317         
3318         Printer->document_started=True;
3319         (*jobid) = Printer->jobid;
3320
3321         srv_spoolss_sendnotify(handle);
3322         return 0x0;
3323 }
3324
3325 /********************************************************************
3326  * api_spoolss_getprinter
3327  * called from the spoolss dispatcher
3328  *
3329  ********************************************************************/
3330 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3331 {
3332         Printer_entry *Printer=find_printer_index_by_hnd(handle);
3333         
3334         if (!OPEN_HANDLE(Printer)) {
3335                 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3336                 return ERROR_INVALID_HANDLE;
3337         }
3338         
3339         Printer->document_started=False;
3340         print_job_end(Printer->jobid);
3341         /* error codes unhandled so far ... */
3342
3343         srv_spoolss_sendnotify(handle);
3344
3345         return 0x0;
3346 }
3347
3348 /****************************************************************************
3349 ****************************************************************************/
3350 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3351                                 uint32 buffer_size,
3352                                 uint8 *buffer,
3353                                 uint32 *buffer_written)
3354 {
3355         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3356         
3357         if (!OPEN_HANDLE(Printer)) {
3358                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3359                 return ERROR_INVALID_HANDLE;
3360         }
3361
3362         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3363                                             buffer_size);
3364
3365         return 0x0;
3366 }
3367
3368 /********************************************************************
3369  * api_spoolss_getprinter
3370  * called from the spoolss dispatcher
3371  *
3372  ********************************************************************/
3373 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3374                               pipes_struct *p)
3375 {
3376         struct current_user user;
3377         int snum, errcode = ERROR_INVALID_FUNCTION;
3378         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3379
3380         get_current_user(&user, p);
3381
3382         if (!OPEN_HANDLE(Printer)) {
3383                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3384                 return ERROR_INVALID_HANDLE;
3385         }
3386
3387         if (!get_printer_snum(handle, &snum))
3388                 return ERROR_INVALID_HANDLE;
3389
3390         switch (command) {
3391         case PRINTER_CONTROL_PAUSE:
3392                 if (print_queue_pause(&user, snum, &errcode)) {
3393                         errcode = 0;
3394                 }
3395                 break;
3396         case PRINTER_CONTROL_RESUME:
3397         case PRINTER_CONTROL_UNPAUSE:
3398                 if (print_queue_resume(&user, snum, &errcode)) {
3399                         errcode = 0;
3400                 }
3401                 break;
3402         case PRINTER_CONTROL_PURGE:
3403                 if (print_queue_purge(&user, snum, &errcode)) {
3404                         errcode = 0;
3405                 }
3406                 break;
3407         default:
3408                 return ERROR_INVALID_LEVEL;
3409         }
3410
3411         return errcode;
3412 }
3413
3414 /********************************************************************
3415  * api_spoolss_abortprinter
3416  ********************************************************************/
3417
3418 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3419 {
3420         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3421 }
3422
3423 /********************************************************************
3424  * called by spoolss_api_setprinter
3425  * when updating a printer description
3426  ********************************************************************/
3427 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3428                                  const SPOOL_PRINTER_INFO_LEVEL *info,
3429                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3430 {
3431         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3432         struct current_user user;
3433         uint32 result;
3434         int snum;
3435
3436         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3437
3438         if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3439                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3440                          OUR_HANDLE(handle)));
3441
3442                 result = ERROR_INVALID_HANDLE;
3443                 goto done;
3444         }
3445
3446         /* NT seems to like setting the security descriptor even though
3447            nothing may have actually changed.  This causes annoying
3448            dialog boxes when the user doesn't have permission to change
3449            the security descriptor. */
3450
3451         nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3452
3453         if (DEBUGLEVEL >= 10) {
3454                 SEC_ACL *acl;
3455                 int i;
3456
3457                 acl = old_secdesc_ctr->sec->dacl;
3458                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
3459                            PRINTERNAME(snum), acl->num_aces));
3460
3461                 for (i = 0; i < acl->num_aces; i++) {
3462                         fstring sid_str;
3463
3464                         sid_to_string(sid_str, &acl->ace[i].sid);
3465
3466                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
3467                                   acl->ace[i].info.mask));
3468                 }
3469
3470                 acl = secdesc_ctr->sec->dacl;
3471
3472                 if (acl) {
3473                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
3474                                    PRINTERNAME(snum), acl->num_aces));
3475
3476                         for (i = 0; i < acl->num_aces; i++) {
3477                                 fstring sid_str;
3478                                 
3479                                 sid_to_string(sid_str, &acl->ace[i].sid);
3480                                 
3481                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
3482                                            acl->ace[i].info.mask));
3483                         }
3484                 } else {
3485                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3486                 }
3487         }
3488
3489         new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3490
3491         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3492                 result = NT_STATUS_NO_PROBLEMO;
3493                 goto done;
3494         }
3495
3496         /* Work out which user is performing the operation */
3497
3498         get_current_user(&user, p);
3499
3500         /* Check the user has permissions to change the security
3501            descriptor.  By experimentation with two NT machines, the user
3502            requires Full Access to the printer to change security
3503            information. */
3504
3505         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3506                 result = ERROR_ACCESS_DENIED;
3507                 goto done;
3508         }
3509
3510         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3511
3512  done:
3513         free_sec_desc_buf(&new_secdesc_ctr);
3514         free_sec_desc_buf(&old_secdesc_ctr);
3515
3516         return result;
3517 }
3518
3519 /********************************************************************
3520  Do Samba sanity checks on a printer info struct.
3521  this has changed purpose: it now "canonicalises" printer
3522  info from a client rather than just checking it is correct
3523  ********************************************************************/
3524
3525 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3526 {
3527         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3528                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3529
3530         /* we force some elements to "correct" values */
3531         slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3532         slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3533                  global_myname, lp_servicename(snum));
3534         fstrcpy(info->sharename, lp_servicename(snum));
3535         info->attributes = PRINTER_ATTRIBUTE_SHARED   \
3536                 | PRINTER_ATTRIBUTE_LOCAL  \
3537                 | PRINTER_ATTRIBUTE_RAW_ONLY \
3538                 | PRINTER_ATTRIBUTE_QUEUED ;
3539         
3540         return True;
3541 }
3542
3543 /****************************************************************************
3544 ****************************************************************************/
3545 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3546 {
3547         pid_t local_pid = sys_getpid();
3548         char *cmd = lp_addprinter_cmd();
3549         char *path;
3550         char **qlines;
3551         pstring tmp_file;
3552         pstring command;
3553         pstring driverlocation;
3554         int numlines;
3555         int ret;
3556
3557         if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3558                 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3559         else
3560                 path = tmpdir();
3561
3562         /* build driver path... only 9X architecture is needed for legacy reasons */
3563         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3564                         global_myname);
3565         /* change \ to \\ for the shell */
3566         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3567         
3568         slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3569         slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3570                         cmd, printer->info_2->printername, printer->info_2->sharename,
3571                         printer->info_2->portname, printer->info_2->drivername,
3572                         printer->info_2->location, driverlocation);
3573
3574         unlink(tmp_file);
3575
3576     /* Convert script args to unix-codepage */
3577     dos_to_unix(command, True);
3578         DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3579         ret = smbrun(command, tmp_file, False);
3580         DEBUGADD(10,("returned [%d]\n", ret));
3581
3582         if ( ret != 0 ) {
3583                 unlink(tmp_file);
3584                 return False;
3585         }
3586
3587         numlines = 0;
3588     /* Get lines and convert them back to dos-codepage */
3589         qlines = file_lines_load(tmp_file, &numlines, True);
3590         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3591         DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3592         unlink(tmp_file);
3593
3594         if(numlines) {
3595                 /* Set the portname to what the script says the portname should be. */
3596                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3597                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3598
3599                 /* Send SIGHUP to process group... is there a better way? */
3600                 kill(0, SIGHUP);
3601                 add_all_printers();
3602         }
3603
3604         file_lines_free(qlines);
3605         return True;
3606 }
3607
3608 /* Return true if two devicemodes are equal */
3609
3610 #define DEVMODE_CHECK_INT(field) \
3611     if (d1->field != d2->field) { \
3612         DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3613             d1->field, d2->field)); \
3614         return False; \
3615     }
3616
3617 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3618 {
3619         if (!d1 && !d2) goto equal;  /* if both are NULL they are equal */
3620
3621         if (!d1 ^ !d2) {
3622                 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3623                 return False; /* if either is exclusively NULL are not equal */
3624         }
3625
3626         if (!strequal(d1->devicename, d2->devicename) ||
3627             !strequal(d1->formname, d2->formname)) {
3628                 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3629                 return False;
3630         }
3631
3632         DEVMODE_CHECK_INT(specversion);
3633         DEVMODE_CHECK_INT(driverversion);
3634         DEVMODE_CHECK_INT(driverextra);
3635         DEVMODE_CHECK_INT(orientation);
3636         DEVMODE_CHECK_INT(papersize);
3637         DEVMODE_CHECK_INT(paperlength);
3638         DEVMODE_CHECK_INT(paperwidth);
3639         DEVMODE_CHECK_INT(scale);
3640         DEVMODE_CHECK_INT(copies);
3641         DEVMODE_CHECK_INT(defaultsource);
3642         DEVMODE_CHECK_INT(printquality);
3643         DEVMODE_CHECK_INT(color);
3644         DEVMODE_CHECK_INT(duplex);
3645         DEVMODE_CHECK_INT(yresolution);
3646         DEVMODE_CHECK_INT(ttoption);
3647         DEVMODE_CHECK_INT(collate);
3648         DEVMODE_CHECK_INT(logpixels);
3649
3650         DEVMODE_CHECK_INT(fields);
3651         DEVMODE_CHECK_INT(bitsperpel);
3652         DEVMODE_CHECK_INT(pelswidth);
3653         DEVMODE_CHECK_INT(pelsheight);
3654         DEVMODE_CHECK_INT(displayflags);
3655         DEVMODE_CHECK_INT(displayfrequency);
3656         DEVMODE_CHECK_INT(icmmethod);
3657         DEVMODE_CHECK_INT(icmintent);
3658         DEVMODE_CHECK_INT(mediatype);
3659         DEVMODE_CHECK_INT(dithertype);
3660         DEVMODE_CHECK_INT(reserved1);
3661         DEVMODE_CHECK_INT(reserved2);
3662         DEVMODE_CHECK_INT(panningwidth);
3663         DEVMODE_CHECK_INT(panningheight);
3664
3665         /* compare the private data if it exists */
3666         if (!d1->driverextra && !d2->driverextra) goto equal;
3667
3668
3669         DEVMODE_CHECK_INT(driverextra);
3670
3671         if (memcmp(d1->private, d2->private, d1->driverextra)) {
3672                 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
3673                 return False;
3674         }
3675
3676  equal:
3677         DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
3678         return True;
3679 }
3680
3681 /* Return true if two NT_PRINTER_PARAM structures are equal */
3682
3683 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3684                                    NT_PRINTER_PARAM *p2)
3685 {
3686         if (!p1 && !p2) goto equal;
3687
3688         if ((!p1 && p2) || (p1 && !p2)) {
3689                 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
3690                 return False;
3691         }
3692
3693         /* Compare lists of printer parameters */
3694
3695         while (p1) {
3696                 BOOL found = False;
3697                 NT_PRINTER_PARAM *q = p1;
3698
3699                 /* Find the parameter in the second structure */
3700
3701                 while(q) {
3702
3703                         if (strequal(p1->value, q->value)) {
3704
3705                                 if (p1->type != q->type) {
3706                                         DEBUG(10, ("nt_printer_param_equal():"
3707                                                    "types for %s differ (%d != %d)\n",
3708                                                    p1->value, p1->type,
3709                                                    q->type));
3710                                         break;
3711                                 }
3712
3713                                 if (p1->data_len != q->data_len) {
3714                                         DEBUG(10, ("nt_printer_param_equal():"
3715                                                    "len for %s differs (%d != %d)\n",
3716                                                    p1->value, p1->data_len,
3717                                                    q->data_len));
3718                                         break;
3719                                 }
3720
3721                                 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
3722                                         found = True;
3723                                 } else {
3724                                         DEBUG(10, ("nt_printer_param_equal():"
3725                                                    "data for %s differs\n", p1->value));
3726                                 }
3727
3728                                 break;
3729                         }
3730
3731                         q = q->next;
3732                 }
3733
3734                 if (!found) {
3735                         DEBUG(10, ("nt_printer_param_equal(): param %s "
3736                                    "does not exist\n", p1->value));
3737                         return False;
3738                 }
3739
3740                 p1 = p1->next;
3741         }
3742
3743         equal:
3744
3745         DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
3746         return True;
3747 }
3748
3749 /********************************************************************
3750  * Called by update_printer when trying to work out whether to
3751  * actually update printer info.
3752  ********************************************************************/
3753
3754 #define PI_CHECK_INT(field) \
3755     if (pi1->field != pi2->field) { \
3756         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
3757             pi1->field, pi2->field)); \
3758         return False; \
3759     }
3760
3761 #define PI_CHECK_STR(field) \
3762     if (!strequal(pi1->field, pi2->field)) { \
3763         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
3764             pi1->field, pi2->field)); \
3765         return False; \
3766     }
3767
3768 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3769                                         NT_PRINTER_INFO_LEVEL *p2)
3770 {
3771         NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3772
3773         /* Trivial conditions */
3774
3775         if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3776                 goto equal;
3777         }
3778
3779         if ((!p1 && p2) || (p1 && !p2) ||
3780             (!p1->info_2 && p2->info_2) ||
3781             (p1->info_2 && !p2->info_2)) {
3782                 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
3783                            "differ\n"));
3784                 return False;
3785         }
3786
3787         /* Compare two nt_printer_info_level structures.  Don't compare
3788            status or cjobs as they seem to have something to do with the
3789            printer queue. */
3790
3791         pi1 = p1->info_2;
3792         pi2 = p2->info_2;
3793
3794         PI_CHECK_INT(attributes);
3795         PI_CHECK_INT(priority);
3796         PI_CHECK_INT(default_priority);
3797         PI_CHECK_INT(starttime);
3798         PI_CHECK_INT(untiltime);
3799         PI_CHECK_INT(averageppm);
3800
3801         /* Yuck - don't check the printername or servername as the
3802            add_a_printer() code plays games with them.  You can't
3803            change the printername or the sharename through this interface
3804            in Samba. */
3805
3806         PI_CHECK_STR(sharename);
3807         PI_CHECK_STR(portname);
3808         PI_CHECK_STR(drivername);
3809         PI_CHECK_STR(comment);
3810         PI_CHECK_STR(location);
3811
3812         if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3813                 return False;
3814         }
3815
3816         PI_CHECK_STR(sepfile);
3817         PI_CHECK_STR(printprocessor);
3818         PI_CHECK_STR(datatype);
3819         PI_CHECK_STR(parameters);
3820
3821         if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3822                 return False;
3823         }
3824
3825         if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3826                 return False;
3827         }
3828
3829         PI_CHECK_INT(changeid);
3830         PI_CHECK_INT(c_setprinter);
3831         PI_CHECK_INT(setuptime);
3832
3833  equal:
3834         DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
3835         return True;
3836 }
3837
3838 /********************************************************************
3839  * called by spoolss_api_setprinter
3840  * when updating a printer description
3841  ********************************************************************/
3842
3843 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3844                            const SPOOL_PRINTER_INFO_LEVEL *info,
3845                            DEVICEMODE *devmode)
3846 {
3847         int snum;
3848         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3849         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3850         uint32 result;
3851
3852         DEBUG(8,("update_printer\n"));
3853         
3854         result = NT_STATUS_NO_PROBLEMO;
3855
3856         if (level!=2) {
3857                 DEBUG(0,("Send a mail to samba@samba.org\n"));
3858                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3859                 result = ERROR_INVALID_LEVEL;
3860                 goto done;
3861         }
3862
3863         if (!OPEN_HANDLE(Printer)) {
3864                 result = ERROR_INVALID_HANDLE;
3865                 goto done;
3866         }
3867
3868         if (!get_printer_snum(handle, &snum)) {
3869                 result = ERROR_INVALID_HANDLE;
3870                 goto done;
3871         }
3872
3873         if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3874            (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3875                 result = ERROR_INVALID_HANDLE;
3876                 goto done;
3877         }
3878
3879         DEBUGADD(8,("Converting info_2 struct\n"));
3880
3881         /*
3882          * convert_printer_info converts the incoming
3883          * info from the client and overwrites the info
3884          * just read from the tdb in the pointer 'printer'.
3885          */
3886
3887         convert_printer_info(info, printer, level);
3888
3889         if (info->info_2->devmode_ptr != 0) {
3890                 /* we have a valid devmode
3891                    convert it and link it*/
3892
3893                 /*
3894                  * Ensure printer->info_2->devmode is a valid pointer
3895                  * as we will be overwriting it in convert_devicemode().
3896                  */
3897                 
3898                 if (printer->info_2->devmode == NULL)
3899                         printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3900
3901                 DEBUGADD(8,("Converting the devicemode struct\n"));
3902                 convert_devicemode(devmode, printer->info_2->devmode);
3903
3904         } else {
3905                 if (printer->info_2->devmode != NULL)
3906                         free_nt_devicemode(&printer->info_2->devmode);
3907                 printer->info_2->devmode=NULL;
3908         }
3909
3910         /* Do sanity check on the requested changes for Samba */
3911
3912         if (!check_printer_ok(printer->info_2, snum)) {
3913                 result = ERROR_INVALID_PARAMETER;
3914                 goto done;
3915         }
3916
3917         /* NT likes to call this function even though nothing has actually
3918            changed.  Check this so the user doesn't end up with an
3919            annoying permission denied dialog box. */
3920
3921         if (nt_printer_info_level_equal(printer, old_printer)) {
3922                 DEBUG(3, ("printer info has not changed\n"));
3923                 result = NT_STATUS_NO_PROBLEMO;
3924                 goto done;
3925         }
3926
3927         /* Check calling user has permission to update printer description */
3928
3929         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3930                 DEBUG(3, ("printer property change denied by security "
3931                           "descriptor\n"));
3932                 result = ERROR_ACCESS_DENIED;
3933                 goto done;
3934         }
3935
3936         /* Call addprinter hook */
3937
3938         if (*lp_addprinter_cmd() )
3939                 if ( !add_printer_hook(printer) ) {
3940                         result = ERROR_ACCESS_DENIED;
3941                         goto done;
3942                 }
3943         
3944         /* Update printer info */
3945
3946         if (add_a_printer(*printer, 2)!=0) {
3947                 /* I don't really know what to return here !!! */
3948                 result = ERROR_ACCESS_DENIED;
3949                 goto done;
3950         }
3951
3952  done:
3953         free_a_printer(&printer, 2);
3954         free_a_printer(&old_printer, 2);
3955
3956         srv_spoolss_sendnotify(handle);
3957
3958         return result;
3959 }
3960
3961 /****************************************************************************
3962 ****************************************************************************/
3963 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3964                            const SPOOL_PRINTER_INFO_LEVEL *info,
3965                            DEVMODE_CTR devmode_ctr,
3966                            SEC_DESC_BUF *secdesc_ctr,
3967                            uint32 command, pipes_struct *p)
3968 {
3969         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3970         
3971         if (!OPEN_HANDLE(Printer)) {
3972                 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3973                 return ERROR_INVALID_HANDLE;
3974         }
3975
3976         /* check the level */   
3977         switch (level) {
3978                 case 0:
3979                         return control_printer(handle, command, p);
3980                 case 2:
3981                         return update_printer(handle, level, info, devmode_ctr.devmode);
3982                 case 3:
3983                         return update_printer_sec(handle, level, info, p,
3984                                                   secdesc_ctr);
3985                 default:
3986                         return ERROR_INVALID_LEVEL;
3987         }
3988 }
3989
3990 /****************************************************************************
3991 ****************************************************************************/
3992 uint32 _spoolss_fcpn(POLICY_HND *handle)
3993 {
3994         Printer_entry *Printer= find_printer_index_by_hnd(handle);
3995         
3996         if (!OPEN_HANDLE(Printer)) {
3997                 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3998                 return ERROR_INVALID_HANDLE;
3999         }
4000
4001         if (Printer->notify.client_connected==True)
4002                 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4003                         return ERROR_INVALID_HANDLE;
4004
4005         Printer->notify.flags=0;
4006         Printer->notify.options=0;
4007         Printer->notify.localmachine[0]='\0';
4008         Printer->notify.printerlocal=0;
4009         if (Printer->notify.option)
4010                 safe_free(Printer->notify.option->ctr.type);
4011         safe_free(Printer->notify.option);
4012         Printer->notify.option=NULL;
4013         Printer->notify.client_connected=False;
4014
4015         return NT_STATUS_NO_PROBLEMO;
4016 }
4017
4018 /****************************************************************************
4019 ****************************************************************************/
4020 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4021                        NEW_BUFFER *buffer, uint32 offered,
4022                        uint32 *needed)
4023 {
4024         *needed = 0;
4025         return ERROR_INVALID_PARAMETER; /* this is what a NT server
4026                                            returns for AddJob. AddJob
4027                                            must fail on non-local
4028                                            printers */
4029 }
4030
4031 /****************************************************************************
4032 ****************************************************************************/
4033 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4034                             int position, int snum)
4035 {
4036         pstring temp_name;
4037         
4038         struct tm *t;
4039         
4040         t=gmtime(&queue->time);
4041         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4042
4043         job_info->jobid=queue->job;     
4044         init_unistr(&job_info->printername, lp_servicename(snum));
4045         init_unistr(&job_info->machinename, temp_name);
4046         init_unistr(&job_info->username, queue->user);
4047         init_unistr(&job_info->document, queue->file);
4048         init_unistr(&job_info->datatype, "RAW");
4049         init_unistr(&job_info->text_status, "");
4050         job_info->status=nt_printj_status(queue->status);
4051         job_info->priority=queue->priority;
4052         job_info->position=position;
4053         job_info->totalpages=0;
4054         job_info->pagesprinted=0;
4055
4056         make_systemtime(&job_info->submitted, t);
4057 }
4058
4059 /****************************************************************************
4060 ****************************************************************************/
4061 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4062                             int position, int snum)
4063 {
4064         pstring temp_name;
4065         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4066         pstring chaine;
4067         struct tm *t;
4068
4069         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
4070                 return False;
4071         
4072         t=gmtime(&queue->time);
4073         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4074
4075         job_info->jobid=queue->job;
4076         
4077         snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4078
4079         init_unistr(&job_info->printername, chaine);
4080         
4081         init_unistr(&job_info->machinename, temp_name);
4082         init_unistr(&job_info->username, queue->user);
4083         init_unistr(&job_info->document, queue->file);
4084         init_unistr(&job_info->notifyname, queue->user);
4085         init_unistr(&job_info->datatype, "RAW");
4086         init_unistr(&job_info->printprocessor, "winprint");
4087         init_unistr(&job_info->parameters, "");
4088         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4089         init_unistr(&job_info->text_status, "");
4090         
4091 /* and here the security descriptor */
4092
4093         job_info->status=nt_printj_status(queue->status);
4094         job_info->priority=queue->priority;
4095         job_info->position=position;
4096         job_info->starttime=0;
4097         job_info->untiltime=0;
4098         job_info->totalpages=0;
4099         job_info->size=queue->size;
4100         make_systemtime(&(job_info->submitted), t);
4101         job_info->timeelapsed=0;
4102         job_info->pagesprinted=0;
4103
4104         if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4105                 free_a_printer(&ntprinter, 2);
4106                 return False;
4107         }
4108
4109         free_a_printer(&ntprinter, 2);
4110         return (True);
4111 }
4112
4113 /****************************************************************************
4114  Enumjobs at level 1.
4115 ****************************************************************************/
4116 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4117                               NEW_BUFFER *buffer, uint32 offered,
4118                               uint32 *needed, uint32 *returned)
4119 {
4120         JOB_INFO_1 *info;
4121         int i;
4122         
4123         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4124         if (info==NULL) {
4125                 safe_free(queue);
4126                 *returned=0;
4127                 return ERROR_NOT_ENOUGH_MEMORY;
4128         }
4129         
4130         for (i=0; i<*returned; i++)
4131                 fill_job_info_1(&info[i], &queue[i], i, snum);
4132
4133         safe_free(queue);
4134
4135         /* check the required size. */  
4136         for (i=0; i<*returned; i++)
4137                 (*needed) += spoolss_size_job_info_1(&info[i]);
4138
4139         if (!alloc_buffer_size(buffer, *needed)) {
4140                 safe_free(info);
4141                 return ERROR_INSUFFICIENT_BUFFER;
4142         }
4143
4144         /* fill the buffer with the structures */
4145         for (i=0; i<*returned; i++)
4146                 new_smb_io_job_info_1("", buffer, &info[i], 0); 
4147
4148         /* clear memory */
4149         safe_free(info);
4150
4151         if (*needed > offered) {
4152                 *returned=0;
4153                 return ERROR_INSUFFICIENT_BUFFER;
4154         }
4155         else
4156                 return NT_STATUS_NO_PROBLEMO;
4157 }
4158
4159 /****************************************************************************
4160  Enumjobs at level 2.
4161 ****************************************************************************/
4162 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4163                               NEW_BUFFER *buffer, uint32 offered,
4164                               uint32 *needed, uint32 *returned)
4165 {
4166         JOB_INFO_2 *info;
4167         int i;
4168         
4169         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4170         if (info==NULL) {
4171                 safe_free(queue);
4172                 *returned=0;
4173                 return ERROR_NOT_ENOUGH_MEMORY;
4174         }
4175         
4176         for (i=0; i<*returned; i++)
4177                 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4178
4179         safe_free(queue);
4180
4181         /* check the required size. */  
4182         for (i=0; i<*returned; i++)
4183                 (*needed) += spoolss_size_job_info_2(&info[i]);
4184
4185         if (!alloc_buffer_size(buffer, *needed)) {
4186                 safe_free(info);
4187                 return ERROR_INSUFFICIENT_BUFFER;
4188         }
4189
4190         /* fill the buffer with the structures */
4191         for (i=0; i<*returned; i++)
4192                 new_smb_io_job_info_2("", buffer, &info[i], 0); 
4193
4194         /* clear memory */
4195         free_job_info_2(info);
4196
4197         if (*needed > offered) {
4198                 *returned=0;
4199                 return ERROR_INSUFFICIENT_BUFFER;
4200         }
4201         else
4202                 return NT_STATUS_NO_PROBLEMO;
4203 }
4204
4205 /****************************************************************************
4206  Enumjobs.
4207 ****************************************************************************/
4208 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,                  
4209                           NEW_BUFFER *buffer, uint32 offered,
4210                           uint32 *needed, uint32 *returned)
4211 {       
4212         int snum;
4213         print_queue_struct *queue=NULL;
4214         print_status_struct prt_status;
4215
4216         DEBUG(4,("_spoolss_enumjobs\n"));
4217
4218         ZERO_STRUCT(prt_status);
4219
4220         *needed=0;
4221         *returned=0;
4222
4223         if (!get_printer_snum(handle, &snum))
4224                 return ERROR_INVALID_HANDLE;
4225
4226         *returned = print_queue_status(snum, &queue, &prt_status);
4227         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4228
4229         if (*returned == 0) {
4230                 safe_free(queue);
4231                 return NT_STATUS_NO_PROBLEMO;
4232         }
4233
4234         switch (level) {
4235         case 1:
4236                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4237         case 2:
4238                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4239         default:
4240                 safe_free(queue);
4241                 *returned=0;
4242                 return ERROR_INVALID_LEVEL;
4243         }
4244 }
4245
4246
4247 /****************************************************************************
4248 ****************************************************************************/
4249 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4250 {
4251         return 0x0;
4252 }
4253
4254 /****************************************************************************
4255 ****************************************************************************/
4256 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4257                        pipes_struct *p, JOB_INFO *ctr, uint32 command)
4258 {
4259         struct current_user user;
4260         print_status_struct prt_status;
4261         int snum, errcode = ERROR_INVALID_FUNCTION;
4262                 
4263         memset(&prt_status, 0, sizeof(prt_status));
4264
4265         if (!get_printer_snum(handle, &snum)) {
4266                 return ERROR_INVALID_HANDLE;
4267         }
4268
4269         if (!print_job_exists(jobid)) {
4270                 return ERROR_INVALID_PRINTER_NAME;
4271         }
4272
4273         get_current_user(&user, p);     
4274
4275         switch (command) {
4276         case JOB_CONTROL_CANCEL:
4277         case JOB_CONTROL_DELETE:
4278                 if (print_job_delete(&user, jobid, &errcode)) {
4279                         errcode = 0;
4280                 }
4281                 break;
4282         case JOB_CONTROL_PAUSE:
4283                 if (print_job_pause(&user, jobid, &errcode)) {
4284                         errcode = 0;
4285                 }               
4286                 break;
4287         case JOB_CONTROL_RESTART:
4288         case JOB_CONTROL_RESUME:
4289                 if (print_job_resume(&user, jobid, &errcode)) {
4290                         errcode = 0;
4291                 }
4292                 break;
4293         default:
4294                 return ERROR_INVALID_LEVEL;
4295         }
4296
4297         return errcode;
4298 }
4299
4300 /****************************************************************************
4301  Enumerates all printer drivers at level 1.
4302 ****************************************************************************/
4303 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4304 {
4305         int i;
4306         int ndrivers;
4307         uint32 version;
4308         fstring *list = NULL;
4309
4310         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4311         DRIVER_INFO_1 *driver_info_1=NULL;
4312
4313         *returned=0;
4314
4315 #define MAX_VERSION 4
4316
4317         for (version=0; version<MAX_VERSION; version++) {
4318                 list=NULL;
4319                 ndrivers=get_ntdrivers(&list, architecture, version);
4320                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4321
4322                 if(ndrivers == -1)
4323                         return ERROR_NOT_ENOUGH_MEMORY;
4324
4325                 if(ndrivers != 0) {
4326                         if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4327                                 safe_free(list);
4328                                 return ERROR_NOT_ENOUGH_MEMORY;
4329                         }
4330                 }
4331
4332                 for (i=0; i<ndrivers; i++) {
4333                         uint32 status;
4334                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4335                         ZERO_STRUCT(driver);
4336                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4337                                 safe_free(list);
4338                                 return status;
4339                         }
4340                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
4341                         free_a_printer_driver(driver, 3);
4342                 }       
4343
4344                 *returned+=ndrivers;
4345                 safe_free(list);
4346         }
4347         
4348         /* check the required size. */
4349         for (i=0; i<*returned; i++) {
4350                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4351                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4352         }
4353
4354         if (!alloc_buffer_size(buffer, *needed)) {
4355                 safe_free(driver_info_1);
4356                 return ERROR_INSUFFICIENT_BUFFER;
4357         }
4358
4359         /* fill the buffer with the form structures */
4360         for (i=0; i<*returned; i++) {
4361                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4362                 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4363         }
4364
4365         safe_free(driver_info_1);
4366
4367         if (*needed > offered) {
4368                 *returned=0;
4369                 return ERROR_INSUFFICIENT_BUFFER;
4370         }
4371         else
4372                 return NT_STATUS_NO_PROBLEMO;
4373 }
4374
4375 /****************************************************************************
4376  Enumerates all printer drivers at level 2.
4377 ****************************************************************************/
4378 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4379 {
4380         int i;
4381         int ndrivers;
4382         uint32 version;
4383         fstring *list = NULL;
4384
4385         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4386         DRIVER_INFO_2 *driver_info_2=NULL;
4387
4388         *returned=0;
4389
4390 #define MAX_VERSION 4
4391
4392         for (version=0; version<MAX_VERSION; version++) {
4393                 list=NULL;
4394                 ndrivers=get_ntdrivers(&list, architecture, version);
4395                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4396
4397                 if(ndrivers == -1)
4398                         return ERROR_NOT_ENOUGH_MEMORY;
4399
4400                 if(ndrivers != 0) {
4401                         if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4402                                 safe_free(list);
4403                                 return ERROR_NOT_ENOUGH_MEMORY;
4404                         }
4405                 }
4406                 
4407                 for (i=0; i<ndrivers; i++) {
4408                         uint32 status;
4409
4410                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4411                         ZERO_STRUCT(driver);
4412                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4413                                 safe_free(list);
4414                                 return status;
4415                         }
4416                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
4417                         free_a_printer_driver(driver, 3);
4418                 }       
4419
4420                 *returned+=ndrivers;
4421                 safe_free(list);
4422         }
4423         
4424         /* check the required size. */
4425         for (i=0; i<*returned; i++) {
4426                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4427                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4428         }
4429
4430         if (!alloc_buffer_size(buffer, *needed)) {
4431                 safe_free(driver_info_2);
4432                 return ERROR_INSUFFICIENT_BUFFER;
4433         }
4434
4435         /* fill the buffer with the form structures */
4436         for (i=0; i<*returned; i++) {
4437                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4438                 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4439         }
4440
4441         safe_free(driver_info_2);
4442
4443         if (*needed > offered) {
4444                 *returned=0;
4445                 return ERROR_INSUFFICIENT_BUFFER;
4446         }
4447         else
4448                 return NT_STATUS_NO_PROBLEMO;
4449 }
4450
4451 /****************************************************************************
4452  Enumerates all printer drivers at level 3.
4453 ****************************************************************************/
4454 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4455 {
4456         int i;
4457         int ndrivers;
4458         uint32 version;
4459         fstring *list = NULL;
4460
4461         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4462         DRIVER_INFO_3 *driver_info_3=NULL;
4463
4464         *returned=0;
4465
4466 #define MAX_VERSION 4
4467
4468         for (version=0; version<MAX_VERSION; version++) {
4469                 list=NULL;
4470                 ndrivers=get_ntdrivers(&list, architecture, version);
4471                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4472
4473                 if(ndrivers == -1)
4474                         return ERROR_NOT_ENOUGH_MEMORY;
4475
4476                 if(ndrivers != 0) {
4477                         if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4478                                 safe_free(list);
4479                                 return ERROR_NOT_ENOUGH_MEMORY;
4480                         }
4481                 }
4482
4483                 for (i=0; i<ndrivers; i++) {
4484                         uint32 status;
4485
4486                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4487                         ZERO_STRUCT(driver);
4488                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4489                                 safe_free(list);
4490                                 return status;
4491                         }
4492                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
4493                         free_a_printer_driver(driver, 3);
4494                 }       
4495
4496                 *returned+=ndrivers;
4497                 safe_free(list);
4498         }
4499
4500         /* check the required size. */
4501         for (i=0; i<*returned; i++) {
4502                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4503                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4504         }
4505
4506         if (!alloc_buffer_size(buffer, *needed)) {
4507                 safe_free(driver_info_3);
4508                 return ERROR_INSUFFICIENT_BUFFER;
4509         }
4510         
4511         /* fill the buffer with the driver structures */
4512         for (i=0; i<*returned; i++) {
4513                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4514                 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4515         }
4516
4517         for (i=0; i<*returned; i++)
4518                 safe_free(driver_info_3[i].dependentfiles);
4519         
4520         safe_free(driver_info_3);
4521         
4522         if (*needed > offered) {
4523                 *returned=0;
4524                 return ERROR_INSUFFICIENT_BUFFER;
4525         }
4526         else
4527                 return NT_STATUS_NO_PROBLEMO;
4528 }
4529
4530 /****************************************************************************
4531  Enumerates all printer drivers.
4532 ****************************************************************************/
4533 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4534                                     NEW_BUFFER *buffer, uint32 offered,
4535                                     uint32 *needed, uint32 *returned)
4536 {
4537         fstring *list = NULL;
4538         fstring servername;
4539         fstring architecture;
4540
4541         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4542         fstrcpy(servername, global_myname);
4543         *needed=0;
4544         *returned=0;
4545
4546         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4547
4548         switch (level) {
4549         case 1:
4550                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4551         case 2:
4552                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4553         case 3:
4554                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4555         default:
4556                 *returned=0;
4557                 safe_free(list);
4558                 return ERROR_INVALID_LEVEL;
4559         }
4560 }
4561
4562 /****************************************************************************
4563 ****************************************************************************/
4564 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4565 {
4566         form->flag=list->flag;
4567         init_unistr(&form->name, list->name);
4568         form->width=list->width;
4569         form->length=list->length;
4570         form->left=list->left;
4571         form->top=list->top;
4572         form->right=list->right;
4573         form->bottom=list->bottom;      
4574 }
4575         
4576 /****************************************************************************
4577 ****************************************************************************/
4578 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4579                                NEW_BUFFER *buffer, uint32 offered,
4580                                uint32 *needed, uint32 *numofforms)
4581 {
4582         nt_forms_struct *list=NULL;
4583         FORM_1 *forms_1;
4584         int buffer_size=0;
4585         int i;
4586
4587         DEBUG(4,("_new_spoolss_enumforms\n"));
4588         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4589         DEBUGADD(5,("Info level [%d]\n",          level));
4590
4591         *numofforms = get_ntforms(&list);
4592         DEBUGADD(5,("Number of forms [%d]\n",     *numofforms));
4593
4594         if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4595
4596         switch (level) {
4597         case 1:
4598                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4599                         *numofforms=0;
4600                         return ERROR_NOT_ENOUGH_MEMORY;
4601                 }
4602
4603                 /* construct the list of form structures */
4604                 for (i=0; i<*numofforms; i++) {
4605                         DEBUGADD(6,("Filling form number [%d]\n",i));
4606                         fill_form_1(&forms_1[i], &list[i]);
4607                 }
4608                 
4609                 safe_free(list);
4610
4611                 /* check the required size. */
4612                 for (i=0; i<*numofforms; i++) {
4613                         DEBUGADD(6,("adding form [%d]'s size\n",i));
4614                         buffer_size += spoolss_size_form_1(&forms_1[i]);
4615                 }
4616
4617                 *needed=buffer_size;            
4618                 
4619                 if (!alloc_buffer_size(buffer, buffer_size)){
4620                         safe_free(forms_1);
4621                         return ERROR_INSUFFICIENT_BUFFER;
4622                 }
4623
4624                 /* fill the buffer with the form structures */
4625                 for (i=0; i<*numofforms; i++) {
4626                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
4627                         new_smb_io_form_1("", buffer, &forms_1[i], 0);
4628                 }
4629
4630                 safe_free(forms_1);
4631
4632                 if (*needed > offered) {
4633                         *numofforms=0;
4634                         return ERROR_INSUFFICIENT_BUFFER;
4635                 }
4636                 else
4637                         return NT_STATUS_NO_PROBLEMO;
4638                         
4639         default:
4640                 safe_free(list);
4641                 return ERROR_INVALID_LEVEL;
4642         }
4643
4644 }
4645
4646 /****************************************************************************
4647 ****************************************************************************/
4648 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4649 {
4650         nt_forms_struct *list=NULL;
4651         FORM_1 form_1;
4652         fstring form_name;
4653         int buffer_size=0;
4654         int numofforms, i;
4655
4656         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4657
4658         DEBUG(4,("_spoolss_getform\n"));
4659         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4660         DEBUGADD(5,("Info level [%d]\n",          level));
4661
4662         numofforms = get_ntforms(&list);
4663         DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
4664
4665         if (numofforms == 0)
4666                 return ERROR_NO_MORE_ITEMS;
4667
4668         switch (level) {
4669         case 1:
4670
4671                 /* Check if the requested name is in the list of form structures */
4672                 for (i=0; i<numofforms; i++) {
4673
4674                         DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4675
4676                         if (strequal(form_name, list[i].name)) {
4677                                 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4678                                 fill_form_1(&form_1, &list[i]);
4679                                 break;
4680                         }
4681                 }
4682                 
4683                 safe_free(list);
4684
4685                 /* check the required size. */
4686
4687                 *needed=spoolss_size_form_1(&form_1);
4688                 
4689                 if (!alloc_buffer_size(buffer, buffer_size)){
4690                         return ERROR_INSUFFICIENT_BUFFER;
4691                 }
4692
4693                 if (*needed > offered) {
4694                         return ERROR_INSUFFICIENT_BUFFER;
4695                 }
4696
4697                 /* fill the buffer with the form structures */
4698                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4699                 new_smb_io_form_1("", buffer, &form_1, 0);
4700
4701                 return NT_STATUS_NO_PROBLEMO;
4702                         
4703         default:
4704                 safe_free(list);
4705                 return ERROR_INVALID_LEVEL;
4706         }
4707 }
4708
4709 /****************************************************************************
4710 ****************************************************************************/
4711 static void fill_port_1(PORT_INFO_1 *port, char *name)
4712 {
4713         init_unistr(&port->port_name, name);
4714 }
4715
4716 /****************************************************************************
4717 ****************************************************************************/
4718 static void fill_port_2(PORT_INFO_2 *port, char *name)
4719 {
4720         init_unistr(&port->port_name, name);
4721         init_unistr(&port->monitor_name, "Local Monitor");
4722         init_unistr(&port->description, "Local Port");
4723 #define PORT_TYPE_WRITE 1
4724         port->port_type=PORT_TYPE_WRITE;
4725         port->reserved=0x0;     
4726 }
4727
4728 /****************************************************************************
4729  enumports level 1.
4730 ****************************************************************************/
4731 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4732 {
4733         PORT_INFO_1 *ports=NULL;
4734         int i=0;
4735
4736         if (*lp_enumports_cmd()) {
4737                 pid_t local_pid = sys_getpid();
4738                 char *cmd = lp_enumports_cmd();
4739                 char *path;
4740                 char **qlines;
4741                 pstring tmp_file;
4742                 pstring command;
4743                 int numlines;
4744                 int ret;
4745
4746                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4747                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4748                 else
4749                         path = tmpdir();
4750
4751                 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4752                 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4753
4754                 unlink(tmp_file);
4755                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4756                 ret = smbrun(command, tmp_file, False);
4757                 DEBUG(10,("Returned [%d]\n", ret));
4758                 if (ret != 0) {
4759                         unlink(tmp_file);
4760                         /* Is this the best error to return here? */
4761                         return ERROR_ACCESS_DENIED;
4762                 }
4763
4764                 numlines = 0;
4765                 qlines = file_lines_load(tmp_file, &numlines,True);
4766                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4767                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4768                 unlink(tmp_file);
4769
4770                 if(numlines) {
4771                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4772                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4773                                 file_lines_free(qlines);
4774                                 return ERROR_NOT_ENOUGH_MEMORY;
4775                         }
4776
4777                         for (i=0; i<numlines; i++) {
4778                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4779                                 fill_port_1(&ports[i], qlines[i]);
4780                         }
4781
4782                         file_lines_free(qlines);
4783                 }
4784
4785                 *returned = numlines;
4786
4787         } else {
4788                 *returned = 1; /* Sole Samba port returned. */
4789
4790                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4791                         return ERROR_NOT_ENOUGH_MEMORY;
4792         
4793                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4794
4795                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4796         }
4797
4798         /* check the required size. */
4799         for (i=0; i<*returned; i++) {
4800                 DEBUGADD(6,("adding port [%d]'s size\n", i));
4801                 *needed += spoolss_size_port_info_1(&ports[i]);
4802         }
4803                 
4804         if (!alloc_buffer_size(buffer, *needed)) {
4805                 safe_free(ports);
4806                 return ERROR_INSUFFICIENT_BUFFER;
4807         }
4808
4809         /* fill the buffer with the ports structures */
4810         for (i=0; i<*returned; i++) {
4811                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4812                 new_smb_io_port_1("", buffer, &ports[i], 0);
4813         }
4814
4815         safe_free(ports);
4816
4817         if (*needed > offered) {
4818                 *returned=0;
4819                 return ERROR_INSUFFICIENT_BUFFER;
4820         }
4821         else
4822                 return NT_STATUS_NO_PROBLEMO;
4823 }
4824
4825 /****************************************************************************
4826  enumports level 2.
4827 ****************************************************************************/
4828
4829 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4830 {
4831         PORT_INFO_2 *ports=NULL;
4832         int i=0;
4833
4834         if (*lp_enumports_cmd()) {
4835                 pid_t local_pid = sys_getpid();
4836                 char *cmd = lp_enumports_cmd();
4837                 char *path;
4838                 char **qlines;
4839                 pstring tmp_file;
4840                 pstring command;
4841                 int numlines;
4842                 int ret;
4843
4844                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4845                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4846                 else
4847                         path = tmpdir();
4848
4849                 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4850                 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4851
4852                 unlink(tmp_file);
4853                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4854                 ret = smbrun(command, tmp_file, False);
4855                 DEBUGADD(10,("returned [%d]\n", ret));
4856                 if (ret != 0) {
4857                         unlink(tmp_file);
4858                         /* Is this the best error to return here? */
4859                         return ERROR_ACCESS_DENIED;
4860                 }
4861
4862                 numlines = 0;
4863                 qlines = file_lines_load(tmp_file, &numlines,True);
4864                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4865                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4866                 unlink(tmp_file);
4867
4868                 if(numlines) {
4869                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4870                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4871                                 file_lines_free(qlines);
4872                                 return ERROR_NOT_ENOUGH_MEMORY;
4873                         }
4874
4875                         for (i=0; i<numlines; i++) {
4876                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4877                                 fill_port_2(&(ports[i]), qlines[i]);
4878                         }
4879
4880                         file_lines_free(qlines);
4881                 }
4882
4883                 *returned = numlines;
4884
4885         } else {
4886
4887                 *returned = 1;
4888
4889                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4890                         return ERROR_NOT_ENOUGH_MEMORY;
4891         
4892                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4893
4894                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4895         }
4896
4897         /* check the required size. */
4898         for (i=0; i<*returned; i++) {
4899                 DEBUGADD(6,("adding port [%d]'s size\n", i));
4900                 *needed += spoolss_size_port_info_2(&ports[i]);
4901         }
4902                 
4903         if (!alloc_buffer_size(buffer, *needed)) {
4904                 safe_free(ports);
4905                 return ERROR_INSUFFICIENT_BUFFER;
4906         }
4907
4908         /* fill the buffer with the ports structures */
4909         for (i=0; i<*returned; i++) {
4910                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4911                 new_smb_io_port_2("", buffer, &ports[i], 0);
4912         }
4913
4914         safe_free(ports);
4915
4916         if (*needed > offered) {
4917                 *returned=0;
4918                 return ERROR_INSUFFICIENT_BUFFER;
4919         }
4920         else
4921                 return NT_STATUS_NO_PROBLEMO;
4922 }
4923
4924 /****************************************************************************
4925  enumports.
4926 ****************************************************************************/
4927 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4928                            NEW_BUFFER *buffer, uint32 offered,
4929                            uint32 *needed, uint32 *returned)
4930 {
4931         DEBUG(4,("_spoolss_enumports\n"));
4932         
4933         *returned=0;
4934         *needed=0;
4935         
4936         switch (level) {
4937         case 1:
4938                 return enumports_level_1(buffer, offered, needed, returned);
4939         case 2:
4940                 return enumports_level_2(buffer, offered, needed, returned);
4941         default:
4942                 return ERROR_INVALID_LEVEL;
4943         }
4944 }
4945
4946 /****************************************************************************
4947 ****************************************************************************/
4948 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4949                                 const SPOOL_PRINTER_INFO_LEVEL *info,
4950                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4951                                 uint32 user_switch, const SPOOL_USER_CTR *user,
4952                                 POLICY_HND *handle)
4953 {
4954         NT_PRINTER_INFO_LEVEL *printer = NULL;
4955         fstring name;
4956         int snum;
4957
4958         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4959                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4960                 return ERROR_NOT_ENOUGH_MEMORY;
4961         }
4962
4963         ZERO_STRUCTP(printer);
4964
4965         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4966         convert_printer_info(info, printer, 2);
4967
4968         if (*lp_addprinter_cmd() )
4969                 if ( !add_printer_hook(printer) ) {
4970                         free_a_printer(&printer,2);
4971                         return ERROR_ACCESS_DENIED;
4972         }
4973
4974         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4975              printer->info_2->sharename);
4976
4977         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4978                 free_a_printer(&printer,2);
4979                 return ERROR_ACCESS_DENIED;
4980         }
4981
4982         /* you must be a printer admin to add a new printer */
4983         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4984                 free_a_printer(&printer,2);
4985                 return ERROR_ACCESS_DENIED;             
4986         }
4987         
4988         /*
4989          * Do sanity check on the requested changes for Samba.
4990          */
4991
4992         if (!check_printer_ok(printer->info_2, snum)) {
4993                 free_a_printer(&printer,2);
4994                 return ERROR_INVALID_PARAMETER;
4995         }
4996
4997         /* write the ASCII on disk */
4998         if (add_a_printer(*printer, 2) != 0) {
4999                 free_a_printer(&printer,2);
5000                 return ERROR_ACCESS_DENIED;
5001         }
5002
5003         if (!open_printer_hnd(handle, name)) {
5004                 /* Handle open failed - remove addition. */
5005                 del_a_printer(printer->info_2->sharename);
5006                 free_a_printer(&printer,2);
5007                 return ERROR_ACCESS_DENIED;
5008         }
5009
5010         free_a_printer(&printer,2);
5011
5012         srv_spoolss_sendnotify(handle);
5013
5014         return NT_STATUS_NO_PROBLEMO;
5015 }
5016
5017 /****************************************************************************
5018 ****************************************************************************/
5019 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5020                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5021                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5022                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5023                                 POLICY_HND *handle)
5024 {
5025         switch (level) {
5026                 case 1:
5027                         /* we don't handle yet */
5028                         /* but I know what to do ... */
5029                         return ERROR_INVALID_LEVEL;
5030                 case 2:
5031                         return spoolss_addprinterex_level_2(uni_srv_name, info,
5032                                                             unk0, unk1, unk2, unk3,
5033                                                             user_switch, user, handle);
5034                 default:
5035                         return ERROR_INVALID_LEVEL;
5036         }
5037 }
5038
5039 /****************************************************************************
5040 ****************************************************************************/
5041 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5042                                  uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5043 {
5044         uint32 err = NT_STATUS_NO_PROBLEMO;
5045         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5046         struct current_user user;
5047         
5048         ZERO_STRUCT(driver);
5049
5050         get_current_user(&user, p);     
5051         
5052         convert_printer_driver_info(info, &driver, level);
5053
5054         DEBUG(5,("Cleaning driver's information\n"));
5055         if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5056                 goto done;
5057
5058         DEBUG(5,("Moving driver to final destination\n"));
5059         if(!move_driver_to_download_area(driver, level, &user, &err)) {
5060                 if (err == 0)
5061                         err = ERROR_ACCESS_DENIED;
5062                 goto done;
5063         }
5064
5065         if (add_a_printer_driver(driver, level)!=0) {
5066                 err = ERROR_ACCESS_DENIED;
5067                 goto done;
5068         }
5069
5070  done:
5071         free_a_printer_driver(driver, level);
5072         return err;
5073 }
5074
5075 /****************************************************************************
5076 ****************************************************************************/
5077 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5078 {
5079         init_unistr(&info->name, name);
5080 }
5081
5082 /****************************************************************************
5083 ****************************************************************************/
5084 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5085 {
5086         pstring path;
5087         pstring long_archi;
5088         pstring short_archi;
5089         DRIVER_DIRECTORY_1 *info=NULL;
5090
5091         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5092
5093         if (get_short_archi(short_archi, long_archi)==FALSE)
5094                 return ERROR_INVALID_ENVIRONMENT;
5095
5096         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5097                 return ERROR_NOT_ENOUGH_MEMORY;
5098
5099         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5100
5101         DEBUG(4,("printer driver directory: [%s]\n", path));
5102
5103         fill_driverdir_1(info, path);
5104         
5105         *needed += spoolss_size_driverdir_info_1(info);
5106
5107         if (!alloc_buffer_size(buffer, *needed)) {
5108                 safe_free(info);
5109                 return ERROR_INSUFFICIENT_BUFFER;
5110         }
5111
5112         new_smb_io_driverdir_1("", buffer, info, 0);
5113
5114         safe_free(info);
5115         
5116         if (*needed > offered)
5117                 return ERROR_INSUFFICIENT_BUFFER;
5118         else
5119                 return NT_STATUS_NO_PROBLEMO;
5120 }
5121
5122 /****************************************************************************
5123 ****************************************************************************/
5124 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5125                                         NEW_BUFFER *buffer, uint32 offered,
5126                                         uint32 *needed)
5127 {
5128         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5129
5130         *needed=0;
5131
5132         switch(level) {
5133         case 1:
5134                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5135         default:
5136                 return ERROR_INVALID_LEVEL;
5137         }
5138 }
5139         
5140 /****************************************************************************
5141 ****************************************************************************/
5142 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5143                                 uint32 in_value_len, uint32 in_data_len,
5144                                 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5145                                 uint32 *out_type,
5146                                 uint32 *out_max_data_len, uint8  **data_out, uint32 *out_data_len)
5147 {
5148         NT_PRINTER_INFO_LEVEL *printer = NULL;
5149         
5150         fstring value;
5151         
5152         uint32 param_index;
5153         uint32 biggest_valuesize;
5154         uint32 biggest_datasize;
5155         uint32 data_len;
5156         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5157         int snum;
5158         uint8 *data=NULL;
5159         uint32 type;
5160
5161         ZERO_STRUCT(printer);
5162         
5163         *out_max_value_len=0;
5164         *out_value=NULL;
5165         *out_value_len=0;
5166
5167         *out_type=0;
5168
5169         *out_max_data_len=0;
5170         *data_out=NULL;
5171         *out_data_len=0;
5172
5173         DEBUG(5,("spoolss_enumprinterdata\n"));
5174
5175         if (!OPEN_HANDLE(Printer)) {
5176                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5177                 return ERROR_INVALID_HANDLE;
5178         }
5179
5180         if (!get_printer_snum(handle, &snum))
5181                 return ERROR_INVALID_HANDLE;
5182         
5183         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5184                 return ERROR_INVALID_HANDLE;
5185
5186         /*
5187          * The NT machine wants to know the biggest size of value and data
5188          *
5189          * cf: MSDN EnumPrinterData remark section
5190          */
5191         if ( (in_value_len==0) && (in_data_len==0) ) {
5192                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5193
5194 #if 0
5195                 /*
5196                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5197                  * if this parameter size doesn't exist.
5198                  * Ok - my opinion here is that the client is not asking for the greatest
5199                  * possible size of all the parameters, but is asking specifically for the size needed
5200                  * for this specific parameter. In that case we can remove the loop below and
5201                  * simplify this lookup code considerably. JF - comments welcome. JRA.
5202                  */
5203
5204                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5205                         safe_free(data);
5206                         free_a_printer(&printer, 2);
5207                         return ERROR_NO_MORE_ITEMS;
5208                 }
5209 #endif
5210
5211                 safe_free(data);
5212                 data = NULL;
5213
5214                 param_index=0;
5215                 biggest_valuesize=0;
5216                 biggest_datasize=0;
5217                 
5218                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5219                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5220                         if (data_len > biggest_datasize) biggest_datasize=data_len;
5221
5222                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5223
5224                         safe_free(data);
5225                         data = NULL;
5226                         param_index++;
5227                 }
5228
5229                 /*
5230                  * I think this is correct, it doesn't break APW and
5231                  * allows Gerald's Win32 test programs to work correctly,
5232                  * but may need altering.... JRA.
5233                  */
5234
5235                 if (param_index == 0) {
5236                         /* No parameters found. */
5237                         free_a_printer(&printer, 2);
5238                         return ERROR_NO_MORE_ITEMS;
5239                 }
5240
5241                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5242                 *out_value_len=2*(1+biggest_valuesize);
5243                 *out_data_len=biggest_datasize;
5244
5245                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5246
5247                 free_a_printer(&printer, 2);
5248                 return NT_STATUS_NO_PROBLEMO;
5249         }
5250         
5251         /*
5252          * the value len is wrong in NT sp3
5253          * that's the number of bytes not the number of unicode chars
5254          */
5255
5256         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5257                 safe_free(data);
5258                 free_a_printer(&printer, 2);
5259                 return ERROR_NO_MORE_ITEMS;
5260         }
5261
5262         free_a_printer(&printer, 2);
5263
5264         /*
5265          * the value is:
5266          * - counted in bytes in the request
5267          * - counted in UNICODE chars in the max reply
5268          * - counted in bytes in the real size
5269          *
5270          * take a pause *before* coding not *during* coding
5271          */
5272         
5273         *out_max_value_len=(in_value_len/sizeof(uint16));
5274         if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5275                 safe_free(data);
5276                 return ERROR_NOT_ENOUGH_MEMORY;
5277         }
5278         
5279         ZERO_STRUCTP(*out_value);
5280         *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5281
5282         *out_type=type;
5283
5284         /* the data is counted in bytes */
5285         *out_max_data_len=in_data_len;
5286         if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5287                 safe_free(data);
5288                 return ERROR_NOT_ENOUGH_MEMORY;
5289         }
5290         
5291         memset(*data_out,'\0',in_data_len);
5292         memcpy(*data_out, data, (size_t)data_len);
5293         *out_data_len=data_len;
5294
5295         safe_free(data);
5296         
5297         return NT_STATUS_NO_PROBLEMO;
5298 }
5299
5300 /****************************************************************************
5301 ****************************************************************************/
5302 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5303                                 const UNISTR2 *value,
5304                                 uint32 type,
5305                                 uint32 max_len,
5306                                 const uint8 *data,
5307                                 uint32 real_len,
5308                                 uint32 numeric_data)
5309 {
5310         NT_PRINTER_INFO_LEVEL *printer = NULL;
5311         NT_PRINTER_PARAM *param = NULL, old_param;
5312         int snum=0;
5313         uint32 status = 0x0;
5314         Printer_entry *Printer=find_printer_index_by_hnd(handle);
5315         
5316         DEBUG(5,("spoolss_setprinterdata\n"));
5317
5318         if (!OPEN_HANDLE(Printer)) {
5319                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5320                 return ERROR_INVALID_HANDLE;
5321         }
5322
5323         if (!get_printer_snum(handle, &snum))
5324                 return ERROR_INVALID_HANDLE;
5325
5326         status = get_a_printer(&printer, 2, lp_servicename(snum));
5327         if (status != 0x0)
5328                 return ERROR_INVALID_NAME;
5329
5330         convert_specific_param(&param, value , type, data, real_len);
5331
5332         /* Check if we are making any changes or not.  Return true if
5333            nothing is actually changing. */
5334
5335         ZERO_STRUCT(old_param);
5336
5337         if (get_specific_param(*printer, 2, param->value, &old_param.data,
5338                                &old_param.type, (unsigned int *)&old_param.data_len)) {
5339
5340                 if (param->type == old_param.type &&
5341                     param->data_len == old_param.data_len &&
5342                     memcmp(param->data, old_param.data,
5343                            old_param.data_len) == 0) {
5344
5345                         DEBUG(3, ("setprinterdata hasn't changed\n"));
5346                         status = NT_STATUS_NO_PROBLEMO;
5347                         goto done;
5348                 }
5349         }
5350
5351         /* Access check */
5352
5353         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5354                 DEBUG(3, ("security descriptor change denied by existing "
5355                           "security descriptor\n"));
5356                 status = ERROR_ACCESS_DENIED;
5357                 goto done;
5358         }
5359
5360         unlink_specific_param_if_exist(printer->info_2, param);
5361         
5362         add_a_specific_param(printer->info_2, &param);
5363         status = mod_a_printer(*printer, 2);
5364
5365  done:
5366         free_a_printer(&printer, 2);
5367         if (param)
5368                 free_nt_printer_param(&param);
5369         safe_free(old_param.data);
5370
5371         return status;
5372 }
5373
5374 /****************************************************************************
5375 ****************************************************************************/
5376 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5377 {
5378         NT_PRINTER_INFO_LEVEL *printer = NULL;
5379         NT_PRINTER_PARAM param;
5380         int snum=0;
5381         uint32 status = 0x0;
5382         Printer_entry *Printer=find_printer_index_by_hnd(handle);
5383         
5384         DEBUG(5,("spoolss_deleteprinterdata\n"));
5385         
5386         if (!OPEN_HANDLE(Printer)) {
5387                 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5388                 return ERROR_INVALID_HANDLE;
5389         }
5390
5391         if (!get_printer_snum(handle, &snum))
5392                 return ERROR_INVALID_HANDLE;
5393
5394         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5395                 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5396                           "security descriptor\n"));
5397                 return ERROR_ACCESS_DENIED;
5398         }
5399
5400         status = get_a_printer(&printer, 2, lp_servicename(snum));
5401         if (status != 0x0)
5402                 return ERROR_INVALID_NAME;
5403
5404         ZERO_STRUCTP(&param);
5405         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5406
5407         if(!unlink_specific_param_if_exist(printer->info_2, &param))
5408                 status = ERROR_INVALID_PARAMETER;
5409         else
5410                 status = mod_a_printer(*printer, 2);
5411
5412         free_a_printer(&printer, 2);
5413         return status;
5414 }
5415
5416 /****************************************************************************
5417 ****************************************************************************/
5418 uint32 _spoolss_addform( POLICY_HND *handle,
5419                                 uint32 level,
5420                                 const FORM *form)
5421 {
5422         int count=0;
5423         nt_forms_struct *list=NULL;
5424         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5425
5426         DEBUG(5,("spoolss_addform\n"));
5427
5428         if (!OPEN_HANDLE(Printer)) {
5429                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5430                 return ERROR_INVALID_HANDLE;
5431         }
5432
5433         count=get_ntforms(&list);
5434         if(!add_a_form(&list, form, &count))
5435                 return ERROR_NOT_ENOUGH_MEMORY;
5436         write_ntforms(&list, count);
5437
5438         safe_free(list);
5439
5440         return 0x0;
5441 }
5442
5443 /****************************************************************************
5444 ****************************************************************************/
5445 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5446 {
5447         int count=0;
5448         uint32 ret = 0;
5449         nt_forms_struct *list=NULL;
5450         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5451
5452         DEBUG(5,("spoolss_deleteform\n"));
5453
5454         if (!OPEN_HANDLE(Printer)) {
5455                 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5456                 return ERROR_INVALID_HANDLE;
5457         }
5458
5459         count = get_ntforms(&list);
5460         if(!delete_a_form(&list, form_name, &count, &ret))
5461                 return ERROR_INVALID_PARAMETER;
5462
5463         safe_free(list);
5464
5465         return ret;
5466 }
5467
5468 /****************************************************************************
5469 ****************************************************************************/
5470 uint32 _spoolss_setform( POLICY_HND *handle,
5471                                 const UNISTR2 *uni_name,
5472                                 uint32 level,
5473                                 const FORM *form)
5474 {
5475         int count=0;
5476         nt_forms_struct *list=NULL;
5477         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5478
5479         DEBUG(5,("spoolss_setform\n"));
5480
5481         if (!OPEN_HANDLE(Printer)) {
5482                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5483                 return ERROR_INVALID_HANDLE;
5484         }
5485         count=get_ntforms(&list);
5486         update_a_form(&list, form, count);
5487         write_ntforms(&list, count);
5488
5489         safe_free(list);
5490
5491         return 0x0;
5492 }
5493
5494 /****************************************************************************
5495  enumprintprocessors level 1.
5496 ****************************************************************************/
5497 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5498 {
5499         PRINTPROCESSOR_1 *info_1=NULL;
5500         
5501         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5502                 return ERROR_NOT_ENOUGH_MEMORY;
5503
5504         (*returned) = 0x1;
5505         
5506         init_unistr(&info_1->name, "winprint");
5507
5508         *needed += spoolss_size_printprocessor_info_1(info_1);
5509
5510         if (!alloc_buffer_size(buffer, *needed))
5511                 return ERROR_INSUFFICIENT_BUFFER;
5512
5513         smb_io_printprocessor_info_1("", buffer, info_1, 0);
5514
5515         safe_free(info_1);
5516
5517         if (*needed > offered) {
5518                 *returned=0;
5519                 return ERROR_INSUFFICIENT_BUFFER;
5520         }
5521         else
5522                 return NT_STATUS_NO_PROBLEMO;
5523 }
5524
5525 /****************************************************************************
5526 ****************************************************************************/
5527 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5528                                     NEW_BUFFER *buffer, uint32 offered,
5529                                     uint32 *needed, uint32 *returned)
5530 {
5531         DEBUG(5,("spoolss_enumprintprocessors\n"));
5532
5533         /*
5534          * Enumerate the print processors ...
5535          *
5536          * Just reply with "winprint", to keep NT happy
5537          * and I can use my nice printer checker.
5538          */
5539         
5540         *returned=0;
5541         *needed=0;
5542         
5543         switch (level) {
5544         case 1:
5545                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5546         default:
5547                 return ERROR_INVALID_LEVEL;
5548         }
5549 }
5550
5551 /****************************************************************************
5552  enumprintprocdatatypes level 1.
5553 ****************************************************************************/
5554 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5555 {
5556         PRINTPROCDATATYPE_1 *info_1=NULL;
5557         
5558         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5559                 return ERROR_NOT_ENOUGH_MEMORY;
5560
5561         (*returned) = 0x1;
5562         
5563         init_unistr(&info_1->name, "RAW");
5564
5565         *needed += spoolss_size_printprocdatatype_info_1(info_1);
5566
5567         if (!alloc_buffer_size(buffer, *needed))
5568                 return ERROR_INSUFFICIENT_BUFFER;
5569
5570         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5571
5572         safe_free(info_1);
5573
5574         if (*needed > offered) {
5575                 *returned=0;
5576                 return ERROR_INSUFFICIENT_BUFFER;
5577         }
5578         else
5579                 return NT_STATUS_NO_PROBLEMO;
5580 }
5581
5582 /****************************************************************************
5583 ****************************************************************************/
5584 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5585                                         NEW_BUFFER *buffer, uint32 offered,
5586                                         uint32 *needed, uint32 *returned)
5587 {
5588         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5589         
5590         *returned=0;
5591         *needed=0;
5592         
5593         switch (level) {
5594         case 1:
5595                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5596         default:
5597                 return ERROR_INVALID_LEVEL;
5598         }
5599 }
5600
5601 /****************************************************************************
5602  enumprintmonitors level 1.
5603 ****************************************************************************/
5604 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5605 {
5606         PRINTMONITOR_1 *info_1=NULL;
5607         
5608         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5609                 return ERROR_NOT_ENOUGH_MEMORY;
5610
5611         (*returned) = 0x1;
5612         
5613         init_unistr(&info_1->name, "Local Port");
5614
5615         *needed += spoolss_size_printmonitor_info_1(info_1);
5616
5617         if (!alloc_buffer_size(buffer, *needed))
5618                 return ERROR_INSUFFICIENT_BUFFER;
5619
5620         smb_io_printmonitor_info_1("", buffer, info_1, 0);
5621
5622         safe_free(info_1);
5623
5624         if (*needed > offered) {
5625                 *returned=0;
5626                 return ERROR_INSUFFICIENT_BUFFER;
5627         }
5628         else
5629                 return NT_STATUS_NO_PROBLEMO;
5630 }
5631
5632 /****************************************************************************
5633  enumprintmonitors level 2.
5634 ****************************************************************************/
5635 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5636 {
5637         PRINTMONITOR_2 *info_2=NULL;
5638         
5639         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5640                 return ERROR_NOT_ENOUGH_MEMORY;
5641
5642         (*returned) = 0x1;
5643         
5644         init_unistr(&info_2->name, "Local Port");
5645         init_unistr(&info_2->environment, "Windows NT X86");
5646         init_unistr(&info_2->dll_name, "localmon.dll");
5647
5648         *needed += spoolss_size_printmonitor_info_2(info_2);
5649
5650         if (!alloc_buffer_size(buffer, *needed))
5651                 return ERROR_INSUFFICIENT_BUFFER;
5652
5653         smb_io_printmonitor_info_2("", buffer, info_2, 0);
5654
5655         safe_free(info_2);
5656
5657         if (*needed > offered) {
5658                 *returned=0;
5659                 return ERROR_INSUFFICIENT_BUFFER;
5660         }
5661         else
5662                 return NT_STATUS_NO_PROBLEMO;
5663 }
5664
5665 /****************************************************************************
5666 ****************************************************************************/
5667 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5668                                     NEW_BUFFER *buffer, uint32 offered,
5669                                     uint32 *needed, uint32 *returned)
5670 {
5671         DEBUG(5,("spoolss_enumprintmonitors\n"));
5672
5673         /*
5674          * Enumerate the print monitors ...
5675          *
5676          * Just reply with "Local Port", to keep NT happy
5677          * and I can use my nice printer checker.
5678          */
5679         
5680         *returned=0;
5681         *needed=0;
5682         
5683         switch (level) {
5684         case 1:
5685                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5686         case 2:
5687                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5688         default:
5689                 return ERROR_INVALID_LEVEL;
5690         }
5691 }
5692
5693 /****************************************************************************
5694 ****************************************************************************/
5695 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5696 {
5697         int i=0;
5698         BOOL found=False;
5699         JOB_INFO_1 *info_1=NULL;
5700
5701         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5702
5703         if (info_1 == NULL) {
5704                 safe_free(queue);
5705                 return ERROR_NOT_ENOUGH_MEMORY;
5706         }
5707                 
5708         for (i=0; i<count && found==False; i++) {
5709                 if (queue[i].job==(int)jobid)
5710                         found=True;
5711         }
5712         
5713         if (found==False) {
5714                 safe_free(queue);
5715                 safe_free(info_1);
5716                 /* I shoud reply something else ... I can't find the good one */
5717                 return NT_STATUS_NO_PROBLEMO;
5718         }
5719         
5720         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5721         
5722         safe_free(queue);
5723         
5724         *needed += spoolss_size_job_info_1(info_1);
5725
5726         if (!alloc_buffer_size(buffer, *needed)) {
5727                 safe_free(info_1);
5728                 return ERROR_INSUFFICIENT_BUFFER;
5729         }
5730
5731         new_smb_io_job_info_1("", buffer, info_1, 0);
5732
5733         safe_free(info_1);
5734
5735         if (*needed > offered)
5736                 return ERROR_INSUFFICIENT_BUFFER;
5737         else
5738                 return NT_STATUS_NO_PROBLEMO;
5739 }
5740
5741
5742 /****************************************************************************
5743 ****************************************************************************/
5744 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5745 {
5746         int i=0;
5747         BOOL found=False;
5748         JOB_INFO_2 *info_2;
5749         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5750
5751         ZERO_STRUCTP(info_2);
5752
5753         if (info_2 == NULL) {
5754                 safe_free(queue);
5755                 return ERROR_NOT_ENOUGH_MEMORY;
5756         }
5757
5758         for (i=0; i<count && found==False; i++) {
5759                 if (queue[i].job==(int)jobid)
5760                         found=True;
5761         }
5762         
5763         if (found==False) {
5764                 safe_free(queue);
5765                 safe_free(info_2);
5766                 /* I shoud reply something else ... I can't find the good one */
5767                 return NT_STATUS_NO_PROBLEMO;
5768         }
5769         
5770         fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5771         
5772         safe_free(queue);
5773         
5774         *needed += spoolss_size_job_info_2(info_2);
5775
5776         if (!alloc_buffer_size(buffer, *needed)) {
5777                 safe_free(info_2);
5778                 return ERROR_INSUFFICIENT_BUFFER;
5779         }
5780
5781         new_smb_io_job_info_2("", buffer, info_2, 0);
5782
5783         free_job_info_2(info_2);
5784
5785         if (*needed > offered)
5786                 return ERROR_INSUFFICIENT_BUFFER;
5787         else
5788                 return NT_STATUS_NO_PROBLEMO;
5789 }
5790
5791 /****************************************************************************
5792 ****************************************************************************/
5793 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5794                         NEW_BUFFER *buffer, uint32 offered,
5795                         uint32 *needed)
5796 {
5797         int snum;
5798         int count;
5799         print_queue_struct *queue=NULL;
5800         print_status_struct prt_status;
5801
5802         DEBUG(5,("spoolss_getjob\n"));
5803         
5804         memset(&prt_status, 0, sizeof(prt_status));
5805
5806         *needed=0;
5807         
5808         if (!get_printer_snum(handle, &snum))
5809                 return ERROR_INVALID_HANDLE;
5810         
5811         count = print_queue_status(snum, &queue, &prt_status);
5812         
5813         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5814                      count, prt_status.status, prt_status.message));
5815                 
5816         switch (level) {
5817         case 1:
5818                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5819         case 2:
5820                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5821         default:
5822                 safe_free(queue);
5823                 return ERROR_INVALID_LEVEL;
5824         }
5825 }
5826 #undef OLD_NTDOMAIN