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