Changes from APPLIANCE_HEAD:
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 #define OLD_NTDOMAIN 1
2 /*
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-2000,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8  *  Copyright (C) Jean François Micouleau      1998-2000.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #include "includes.h"
26
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
29
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
32 #endif
33
34 #define PRINTER_HANDLE_IS_PRINTER       0
35 #define PRINTER_HANDLE_IS_PRINTSERVER   1
36
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer{
42         ubi_dlNode Next;
43         ubi_dlNode Prev;
44
45         BOOL open;
46         BOOL document_started;
47         BOOL page_started;
48         int jobid; /* jobid in printing backend */
49         POLICY_HND printer_hnd;
50         BOOL printer_type;
51         union {
52                 fstring handlename;
53                 fstring printerservername;
54         } dev;
55         uint32 type;
56         uint32 access;
57         struct {
58                 uint32 flags;
59                 uint32 options;
60                 fstring localmachine;
61                 uint32 printerlocal;
62                 SPOOL_NOTIFY_OPTION *option;
63                 POLICY_HND client_hnd;
64                 uint32 client_connected;
65         } notify;
66         struct {
67                 fstring machine;
68                 fstring user;
69         } client;
70 } Printer_entry;
71
72 typedef struct _counter_printer_0 {
73         ubi_dlNode Next;
74         ubi_dlNode Prev;
75         
76         int snum;
77         uint32 counter;
78 } counter_printer_0;
79
80 static ubi_dlList Printer_list;
81 static ubi_dlList counter_list;
82
83 static struct cli_state cli;
84 static uint32 smb_connections=0;
85
86 #define OPEN_HANDLE(pnum)    ((pnum!=NULL) && (pnum->open!=False) && (IVAL(pnum->printer_hnd.data,16)==(uint32)sys_getpid()))
87 #define OUR_HANDLE(pnum) ((pnum==NULL)?"NULL":(IVAL(pnum->data,16)==sys_getpid()?"OURS":"OTHER"))
88
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
91 {
92         switch (v) {
93         case LPQ_PAUSED:
94                 return PRINTER_STATUS_PAUSED;
95         case LPQ_QUEUED:
96         case LPQ_SPOOLING:
97         case LPQ_PRINTING:
98                 return 0;
99         }
100         return 0;
101 }
102
103 static int nt_printq_status(int v)
104 {
105         switch (v) {
106         case LPQ_PAUSED:
107                 return PRINTER_STATUS_PAUSED;
108         case LPQ_QUEUED:
109         case LPQ_SPOOLING:
110         case LPQ_PRINTING:
111                 return 0;
112         }
113         return 0;
114 }
115
116 /****************************************************************************
117   initialise printer handle states...
118 ****************************************************************************/
119 void init_printer_hnd(void)
120 {
121         ubi_dlInitList(&Printer_list);
122         ubi_dlInitList(&counter_list);
123 }
124
125 /****************************************************************************
126   create a unique printer handle
127 ****************************************************************************/
128 static void create_printer_hnd(POLICY_HND *hnd)
129 {
130         static uint32 prt_hnd_low  = 0;
131         static uint32 prt_hnd_high = 0;
132
133         if (hnd == NULL) return;
134
135         /* i severely doubt that prt_hnd_high will ever be non-zero... */
136         prt_hnd_low++;
137         if (prt_hnd_low == 0) prt_hnd_high++;
138
139         SIVAL(hnd->data, 0 , 0x0);          /* first bit must be null */
140         SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
141         SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
142         SIVAL(hnd->data, 12, time(NULL));   /* something random */
143         SIVAL(hnd->data, 16, sys_getpid());     /* something more random */
144 }
145
146 /****************************************************************************
147   find printer index by handle
148 ****************************************************************************/
149 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
150 {
151         Printer_entry *find_printer;
152
153         find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
154
155         for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
156
157                 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
158                         DEBUG(4,("Found printer handle \n"));
159                         /*dump_data(4, hnd->data, sizeof(hnd->data));*/
160                         return find_printer;
161                 }
162         }
163         
164         DEBUG(3,("Whoops, Printer handle not found: "));
165         /*dump_data(4, hnd->data, sizeof(hnd->data));*/
166         return NULL;
167 }
168
169 /****************************************************************************
170   clear an handle
171 ****************************************************************************/
172 static void clear_handle(POLICY_HND *hnd)
173 {
174         ZERO_STRUCTP(hnd);
175 }
176
177 /***************************************************************************
178  Disconnect from the client
179 ****************************************************************************/
180 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
181 {
182         uint32 status;
183
184         /* weird if the test succeds !!! */
185         if (smb_connections==0) {
186                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
187                 return False;
188         }
189
190         if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
191                 return False;
192
193         /* if it's the last connection, deconnect the IPC$ share */
194         if (smb_connections==1) {
195                 if(!spoolss_disconnect_from_client(&cli))
196                         return False;
197
198                 message_deregister(MSG_PRINTER_NOTIFY);
199         }
200
201         smb_connections--;
202
203         return True;
204 }
205
206 /****************************************************************************
207   close printer index by handle
208 ****************************************************************************/
209 static BOOL close_printer_handle(POLICY_HND *hnd)
210 {
211         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
212
213         if (!OPEN_HANDLE(Printer)) {
214                 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
215                 return False;
216         }
217
218         if (Printer->notify.client_connected==True)
219                 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
220                         return ERROR_INVALID_HANDLE;
221
222         Printer->open=False;
223         Printer->notify.flags=0;
224         Printer->notify.options=0;
225         Printer->notify.localmachine[0]='\0';
226         Printer->notify.printerlocal=0;
227         safe_free(Printer->notify.option);
228         Printer->notify.option=NULL;
229         Printer->notify.client_connected=False;
230
231         clear_handle(hnd);
232
233         ubi_dlRemThis(&Printer_list, Printer);
234
235         safe_free(Printer);
236
237         return True;
238 }       
239
240 /****************************************************************************
241   delete a printer given a handle
242 ****************************************************************************/
243 static BOOL delete_printer_handle(POLICY_HND *hnd)
244 {
245         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
246
247         if (!OPEN_HANDLE(Printer)) {
248                 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
249                 return False;
250         }
251
252         if (del_a_printer(Printer->dev.handlename) != 0) {
253                 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
254                 return False;
255         }
256
257         if (*lp_deleteprinter_cmd()) {
258
259                 pid_t local_pid = sys_getpid();
260                 char *cmd = lp_deleteprinter_cmd();
261                 char *path;
262                 pstring tmp_file;
263                 pstring command;
264                 int ret;
265                 int i;
266
267                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
268                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
269                 else
270                         path = tmpdir();
271                 
272                 /* Printer->dev.handlename equals portname equals sharename */
273                 slprintf(command, sizeof(command), "%s \"%s\"", cmd,
274                                         Printer->dev.handlename);
275                 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         return 0x0;
3662 }
3663
3664 /********************************************************************
3665  * api_spoolss_getprinter
3666  * called from the spoolss dispatcher
3667  *
3668  ********************************************************************/
3669 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3670 {
3671         Printer_entry *Printer=find_printer_index_by_hnd(handle);
3672         
3673         if (!OPEN_HANDLE(Printer)) {
3674                 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3675                 return ERROR_INVALID_HANDLE;
3676         }
3677         
3678         Printer->document_started=False;
3679         print_job_end(Printer->jobid);
3680         /* error codes unhandled so far ... */
3681
3682         return 0x0;
3683 }
3684
3685 /****************************************************************************
3686 ****************************************************************************/
3687 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3688                                 uint32 buffer_size,
3689                                 uint8 *buffer,
3690                                 uint32 *buffer_written)
3691 {
3692         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3693         
3694         if (!OPEN_HANDLE(Printer)) {
3695                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3696                 return ERROR_INVALID_HANDLE;
3697         }
3698
3699         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3700                                             buffer_size);
3701
3702         return 0x0;
3703 }
3704
3705 /********************************************************************
3706  * api_spoolss_getprinter
3707  * called from the spoolss dispatcher
3708  *
3709  ********************************************************************/
3710 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3711                               pipes_struct *p)
3712 {
3713         struct current_user user;
3714         int snum, errcode = ERROR_INVALID_FUNCTION;
3715         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3716
3717         get_current_user(&user, p);
3718
3719         if (!OPEN_HANDLE(Printer)) {
3720                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3721                 return ERROR_INVALID_HANDLE;
3722         }
3723
3724         if (!get_printer_snum(handle, &snum))
3725                 return ERROR_INVALID_HANDLE;
3726
3727         switch (command) {
3728         case PRINTER_CONTROL_PAUSE:
3729                 if (print_queue_pause(&user, snum, &errcode)) {
3730                         errcode = 0;
3731                 }
3732                 break;
3733         case PRINTER_CONTROL_RESUME:
3734         case PRINTER_CONTROL_UNPAUSE:
3735                 if (print_queue_resume(&user, snum, &errcode)) {
3736                         errcode = 0;
3737                 }
3738                 break;
3739         case PRINTER_CONTROL_PURGE:
3740                 if (print_queue_purge(&user, snum, &errcode)) {
3741                         errcode = 0;
3742                 }
3743                 break;
3744         default:
3745                 return ERROR_INVALID_LEVEL;
3746         }
3747
3748         return errcode;
3749 }
3750
3751 /********************************************************************
3752  * api_spoolss_abortprinter
3753  ********************************************************************/
3754
3755 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3756 {
3757         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3758 }
3759
3760 /********************************************************************
3761  * called by spoolss_api_setprinter
3762  * when updating a printer description
3763  ********************************************************************/
3764 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3765                                  const SPOOL_PRINTER_INFO_LEVEL *info,
3766                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3767 {
3768         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3769         struct current_user user;
3770         uint32 result;
3771         int snum;
3772
3773         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3774
3775         if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3776                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3777                          OUR_HANDLE(handle)));
3778
3779                 result = ERROR_INVALID_HANDLE;
3780                 goto done;
3781         }
3782
3783         /* NT seems to like setting the security descriptor even though
3784            nothing may have actually changed.  This causes annoying
3785            dialog boxes when the user doesn't have permission to change
3786            the security descriptor. */
3787
3788         nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3789
3790         if (DEBUGLEVEL >= 10) {
3791                 SEC_ACL *acl;
3792                 int i;
3793
3794                 acl = old_secdesc_ctr->sec->dacl;
3795                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
3796                            PRINTERNAME(snum), acl->num_aces));
3797
3798                 for (i = 0; i < acl->num_aces; i++) {
3799                         fstring sid_str;
3800
3801                         sid_to_string(sid_str, &acl->ace[i].sid);
3802
3803                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
3804                                   acl->ace[i].info.mask));
3805                 }
3806
3807                 acl = secdesc_ctr->sec->dacl;
3808
3809                 if (acl) {
3810                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
3811                                    PRINTERNAME(snum), acl->num_aces));
3812
3813                         for (i = 0; i < acl->num_aces; i++) {
3814                                 fstring sid_str;
3815                                 
3816                                 sid_to_string(sid_str, &acl->ace[i].sid);
3817                                 
3818                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
3819                                            acl->ace[i].info.mask));
3820                         }
3821                 } else {
3822                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3823                 }
3824         }
3825
3826         new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3827
3828         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3829                 result = NT_STATUS_NO_PROBLEMO;
3830                 goto done;
3831         }
3832
3833         /* Work out which user is performing the operation */
3834
3835         get_current_user(&user, p);
3836
3837         /* Check the user has permissions to change the security
3838            descriptor.  By experimentation with two NT machines, the user
3839            requires Full Access to the printer to change security
3840            information. */
3841
3842         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3843                 result = ERROR_ACCESS_DENIED;
3844                 goto done;
3845         }
3846
3847         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3848
3849  done:
3850         free_sec_desc_buf(&new_secdesc_ctr);
3851         free_sec_desc_buf(&old_secdesc_ctr);
3852
3853         return result;
3854 }
3855
3856 /********************************************************************
3857  Do Samba sanity checks on a printer info struct.
3858  this has changed purpose: it now "canonicalises" printer
3859  info from a client rather than just checking it is correct
3860  ********************************************************************/
3861
3862 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3863 {
3864         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3865                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3866
3867         /* we force some elements to "correct" values */
3868         slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3869         slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3870                  global_myname, lp_servicename(snum));
3871         fstrcpy(info->sharename, lp_servicename(snum));
3872         info->attributes = PRINTER_ATTRIBUTE_SHARED   \
3873                 | PRINTER_ATTRIBUTE_LOCAL  \
3874                 | PRINTER_ATTRIBUTE_RAW_ONLY \
3875                 | PRINTER_ATTRIBUTE_QUEUED ;
3876         
3877         return True;
3878 }
3879
3880 /****************************************************************************
3881 ****************************************************************************/
3882 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3883 {
3884         pid_t local_pid = sys_getpid();
3885         char *cmd = lp_addprinter_cmd();
3886         char *path;
3887         char **qlines;
3888         pstring tmp_file;
3889         pstring command;
3890         pstring driverlocation;
3891         int numlines;
3892         int ret;
3893
3894         if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3895                 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3896         else
3897                 path = tmpdir();
3898
3899         /* build driver path... only 9X architecture is needed for legacy reasons */
3900         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3901                         global_myname);
3902         /* change \ to \\ for the shell */
3903         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3904         
3905         slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3906         slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3907                         cmd, printer->info_2->printername, printer->info_2->sharename,
3908                         printer->info_2->portname, printer->info_2->drivername,
3909                         printer->info_2->location, driverlocation);
3910
3911         unlink(tmp_file);
3912
3913     /* Convert script args to unix-codepage */
3914     dos_to_unix(command, True);
3915         DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3916         ret = smbrun(command, tmp_file, False);
3917         DEBUGADD(10,("returned [%d]\n", ret));
3918
3919         if ( ret != 0 ) {
3920                 unlink(tmp_file);
3921                 return False;
3922         }
3923
3924         numlines = 0;
3925     /* Get lines and convert them back to dos-codepage */
3926         qlines = file_lines_load(tmp_file, &numlines, True);
3927         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3928         DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3929         unlink(tmp_file);
3930
3931         if(numlines) {
3932                 /* Set the portname to what the script says the portname should be. */
3933                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3934                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3935
3936                 /* Send SIGHUP to process group... is there a better way? */
3937                 kill(0, SIGHUP);
3938                 add_all_printers();
3939         }
3940
3941         file_lines_free(qlines);
3942         return True;
3943 }
3944
3945 /* Return true if two devicemodes are equal */
3946
3947 #define DEVMODE_CHECK_INT(field) \
3948     if (d1->field != d2->field) { \
3949         DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3950             d1->field, d2->field)); \
3951         return False; \
3952     }
3953
3954 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3955 {
3956         if (!d1 && !d2) goto equal;  /* if both are NULL they are equal */
3957
3958         if (!d1 ^ !d2) {
3959                 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3960                 return False; /* if either is exclusively NULL are not equal */
3961         }
3962
3963         if (!strequal(d1->devicename, d2->devicename) ||
3964             !strequal(d1->formname, d2->formname)) {
3965                 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3966                 return False;
3967         }
3968
3969         DEVMODE_CHECK_INT(specversion);
3970         DEVMODE_CHECK_INT(driverversion);
3971         DEVMODE_CHECK_INT(driverextra);
3972         DEVMODE_CHECK_INT(orientation);
3973         DEVMODE_CHECK_INT(papersize);
3974         DEVMODE_CHECK_INT(paperlength);
3975         DEVMODE_CHECK_INT(paperwidth);
3976         DEVMODE_CHECK_INT(scale);
3977         DEVMODE_CHECK_INT(copies);
3978         DEVMODE_CHECK_INT(defaultsource);
3979         DEVMODE_CHECK_INT(printquality);
3980         DEVMODE_CHECK_INT(color);
3981         DEVMODE_CHECK_INT(duplex);
3982         DEVMODE_CHECK_INT(yresolution);
3983         DEVMODE_CHECK_INT(ttoption);
3984         DEVMODE_CHECK_INT(collate);
3985         DEVMODE_CHECK_INT(logpixels);
3986
3987         DEVMODE_CHECK_INT(fields);
3988         DEVMODE_CHECK_INT(bitsperpel);
3989         DEVMODE_CHECK_INT(pelswidth);
3990         DEVMODE_CHECK_INT(pelsheight);
3991         DEVMODE_CHECK_INT(displayflags);
3992         DEVMODE_CHECK_INT(displayfrequency);
3993         DEVMODE_CHECK_INT(icmmethod);
3994         DEVMODE_CHECK_INT(icmintent);
3995         DEVMODE_CHECK_INT(mediatype);
3996         DEVMODE_CHECK_INT(dithertype);
3997         DEVMODE_CHECK_INT(reserved1);
3998         DEVMODE_CHECK_INT(reserved2);
3999         DEVMODE_CHECK_INT(panningwidth);
4000         DEVMODE_CHECK_INT(panningheight);
4001
4002         /* compare the private data if it exists */
4003         if (!d1->driverextra && !d2->driverextra) goto equal;
4004
4005
4006         DEVMODE_CHECK_INT(driverextra);
4007
4008         if (memcmp(d1->private, d2->private, d1->driverextra)) {
4009                 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4010                 return False;
4011         }
4012
4013  equal:
4014         DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4015         return True;
4016 }
4017
4018 /* Return true if two NT_PRINTER_PARAM structures are equal */
4019
4020 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4021                                    NT_PRINTER_PARAM *p2)
4022 {
4023         if (!p1 && !p2) goto equal;
4024
4025         if ((!p1 && p2) || (p1 && !p2)) {
4026                 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4027                 return False;
4028         }
4029
4030         /* Compare lists of printer parameters */
4031
4032         while (p1) {
4033                 BOOL found = False;
4034                 NT_PRINTER_PARAM *q = p1;
4035
4036                 /* Find the parameter in the second structure */
4037
4038                 while(q) {
4039
4040                         if (strequal(p1->value, q->value)) {
4041
4042                                 if (p1->type != q->type) {
4043                                         DEBUG(10, ("nt_printer_param_equal():"
4044                                                    "types for %s differ (%d != %d)\n",
4045                                                    p1->value, p1->type,
4046                                                    q->type));
4047                                         break;
4048                                 }
4049
4050                                 if (p1->data_len != q->data_len) {
4051                                         DEBUG(10, ("nt_printer_param_equal():"
4052                                                    "len for %s differs (%d != %d)\n",
4053                                                    p1->value, p1->data_len,
4054                                                    q->data_len));
4055                                         break;
4056                                 }
4057
4058                                 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4059                                         found = True;
4060                                 } else {
4061                                         DEBUG(10, ("nt_printer_param_equal():"
4062                                                    "data for %s differs\n", p1->value));
4063                                 }
4064
4065                                 break;
4066                         }
4067
4068                         q = q->next;
4069                 }
4070
4071                 if (!found) {
4072                         DEBUG(10, ("nt_printer_param_equal(): param %s "
4073                                    "does not exist\n", p1->value));
4074                         return False;
4075                 }
4076
4077                 p1 = p1->next;
4078         }
4079
4080         equal:
4081
4082         DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4083         return True;
4084 }
4085
4086 /********************************************************************
4087  * Called by update_printer when trying to work out whether to
4088  * actually update printer info.
4089  ********************************************************************/
4090
4091 #define PI_CHECK_INT(field) \
4092     if (pi1->field != pi2->field) { \
4093         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4094             pi1->field, pi2->field)); \
4095         return False; \
4096     }
4097
4098 #define PI_CHECK_STR(field) \
4099     if (!strequal(pi1->field, pi2->field)) { \
4100         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4101             pi1->field, pi2->field)); \
4102         return False; \
4103     }
4104
4105 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4106                                         NT_PRINTER_INFO_LEVEL *p2)
4107 {
4108         NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4109
4110         /* Trivial conditions */
4111
4112         if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4113                 goto equal;
4114         }
4115
4116         if ((!p1 && p2) || (p1 && !p2) ||
4117             (!p1->info_2 && p2->info_2) ||
4118             (p1->info_2 && !p2->info_2)) {
4119                 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4120                            "differ\n"));
4121                 return False;
4122         }
4123
4124         /* Compare two nt_printer_info_level structures.  Don't compare
4125            status or cjobs as they seem to have something to do with the
4126            printer queue. */
4127
4128         pi1 = p1->info_2;
4129         pi2 = p2->info_2;
4130
4131         PI_CHECK_INT(attributes);
4132         PI_CHECK_INT(priority);
4133         PI_CHECK_INT(default_priority);
4134         PI_CHECK_INT(starttime);
4135         PI_CHECK_INT(untiltime);
4136         PI_CHECK_INT(averageppm);
4137
4138         /* Yuck - don't check the printername or servername as the
4139            add_a_printer() code plays games with them.  You can't
4140            change the printername or the sharename through this interface
4141            in Samba. */
4142
4143         PI_CHECK_STR(sharename);
4144         PI_CHECK_STR(portname);
4145         PI_CHECK_STR(drivername);
4146         PI_CHECK_STR(comment);
4147         PI_CHECK_STR(location);
4148
4149         if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4150                 return False;
4151         }
4152
4153         PI_CHECK_STR(sepfile);
4154         PI_CHECK_STR(printprocessor);
4155         PI_CHECK_STR(datatype);
4156         PI_CHECK_STR(parameters);
4157
4158         if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4159                 return False;
4160         }
4161
4162         if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4163                 return False;
4164         }
4165
4166         PI_CHECK_INT(changeid);
4167         PI_CHECK_INT(c_setprinter);
4168         PI_CHECK_INT(setuptime);
4169
4170  equal:
4171         DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4172         return True;
4173 }
4174
4175 /********************************************************************
4176  * called by spoolss_api_setprinter
4177  * when updating a printer description
4178  ********************************************************************/
4179
4180 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4181                            const SPOOL_PRINTER_INFO_LEVEL *info,
4182                            DEVICEMODE *devmode)
4183 {
4184         int snum;
4185         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4186         Printer_entry *Printer = find_printer_index_by_hnd(handle);
4187         uint32 result;
4188
4189         DEBUG(8,("update_printer\n"));
4190         
4191         result = NT_STATUS_NO_PROBLEMO;
4192
4193         if (level!=2) {
4194                 DEBUG(0,("Send a mail to samba@samba.org\n"));
4195                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4196                 result = ERROR_INVALID_LEVEL;
4197                 goto done;
4198         }
4199
4200         if (!OPEN_HANDLE(Printer)) {
4201                 result = ERROR_INVALID_HANDLE;
4202                 goto done;
4203         }
4204
4205         if (!get_printer_snum(handle, &snum)) {
4206                 result = ERROR_INVALID_HANDLE;
4207                 goto done;
4208         }
4209
4210         if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4211            (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4212                 result = ERROR_INVALID_HANDLE;
4213                 goto done;
4214         }
4215
4216         DEBUGADD(8,("Converting info_2 struct\n"));
4217
4218         /*
4219          * convert_printer_info converts the incoming
4220          * info from the client and overwrites the info
4221          * just read from the tdb in the pointer 'printer'.
4222          */
4223
4224         convert_printer_info(info, printer, level);
4225
4226         if (info->info_2->devmode_ptr != 0) {
4227                 /* we have a valid devmode
4228                    convert it and link it*/
4229
4230                 /*
4231                  * Ensure printer->info_2->devmode is a valid pointer
4232                  * as we will be overwriting it in convert_devicemode().
4233                  */
4234                 
4235                 if (printer->info_2->devmode == NULL)
4236                         printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
4237
4238                 DEBUGADD(8,("Converting the devicemode struct\n"));
4239                 convert_devicemode(devmode, printer->info_2->devmode);
4240
4241         } else {
4242                 if (printer->info_2->devmode != NULL)
4243                         free_nt_devicemode(&printer->info_2->devmode);
4244                 printer->info_2->devmode=NULL;
4245         }
4246
4247         /* Do sanity check on the requested changes for Samba */
4248
4249         if (!check_printer_ok(printer->info_2, snum)) {
4250                 result = ERROR_INVALID_PARAMETER;
4251                 goto done;
4252         }
4253
4254         /* NT likes to call this function even though nothing has actually
4255            changed.  Check this so the user doesn't end up with an
4256            annoying permission denied dialog box. */
4257
4258         if (nt_printer_info_level_equal(printer, old_printer)) {
4259                 DEBUG(3, ("printer info has not changed\n"));
4260                 result = NT_STATUS_NO_PROBLEMO;
4261                 goto done;
4262         }
4263
4264         /* Check calling user has permission to update printer description */
4265
4266         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4267                 DEBUG(3, ("printer property change denied by security "
4268                           "descriptor\n"));
4269                 result = ERROR_ACCESS_DENIED;
4270                 goto done;
4271         }
4272
4273         /* Call addprinter hook */
4274
4275         if (*lp_addprinter_cmd() )
4276                 if ( !add_printer_hook(printer) ) {
4277                         result = ERROR_ACCESS_DENIED;
4278                         goto done;
4279                 }
4280         
4281         /* Update printer info */
4282
4283         if (add_a_printer(*printer, 2)!=0) {
4284                 /* I don't really know what to return here !!! */
4285                 result = ERROR_ACCESS_DENIED;
4286                 goto done;
4287         }
4288
4289  done:
4290         free_a_printer(&printer, 2);
4291         free_a_printer(&old_printer, 2);
4292
4293         srv_spoolss_sendnotify(handle);
4294
4295         return result;
4296 }
4297
4298 /****************************************************************************
4299 ****************************************************************************/
4300 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4301                            const SPOOL_PRINTER_INFO_LEVEL *info,
4302                            DEVMODE_CTR devmode_ctr,
4303                            SEC_DESC_BUF *secdesc_ctr,
4304                            uint32 command, pipes_struct *p)
4305 {
4306         Printer_entry *Printer = find_printer_index_by_hnd(handle);
4307         
4308         if (!OPEN_HANDLE(Printer)) {
4309                 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4310                 return ERROR_INVALID_HANDLE;
4311         }
4312
4313         /* check the level */   
4314         switch (level) {
4315                 case 0:
4316                         return control_printer(handle, command, p);
4317                 case 2:
4318                         return update_printer(handle, level, info, devmode_ctr.devmode);
4319                 case 3:
4320                         return update_printer_sec(handle, level, info, p,
4321                                                   secdesc_ctr);
4322                 default:
4323                         return ERROR_INVALID_LEVEL;
4324         }
4325 }
4326
4327 /****************************************************************************
4328 ****************************************************************************/
4329 uint32 _spoolss_fcpn(POLICY_HND *handle)
4330 {
4331         Printer_entry *Printer= find_printer_index_by_hnd(handle);
4332         
4333         if (!OPEN_HANDLE(Printer)) {
4334                 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4335                 return ERROR_INVALID_HANDLE;
4336         }
4337
4338         if (Printer->notify.client_connected==True)
4339                 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4340                         return ERROR_INVALID_HANDLE;
4341
4342         Printer->notify.flags=0;
4343         Printer->notify.options=0;
4344         Printer->notify.localmachine[0]='\0';
4345         Printer->notify.printerlocal=0;
4346         if (Printer->notify.option)
4347                 safe_free(Printer->notify.option->ctr.type);
4348         safe_free(Printer->notify.option);
4349         Printer->notify.option=NULL;
4350         Printer->notify.client_connected=False;
4351
4352         return NT_STATUS_NO_PROBLEMO;
4353 }
4354
4355 /****************************************************************************
4356 ****************************************************************************/
4357 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4358                        NEW_BUFFER *buffer, uint32 offered,
4359                        uint32 *needed)
4360 {
4361         *needed = 0;
4362         return ERROR_INVALID_PARAMETER; /* this is what a NT server
4363                                            returns for AddJob. AddJob
4364                                            must fail on non-local
4365                                            printers */
4366 }
4367
4368 /****************************************************************************
4369 ****************************************************************************/
4370 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4371                             int position, int snum)
4372 {
4373         pstring temp_name;
4374         
4375         struct tm *t;
4376         
4377         t=gmtime(&queue->time);
4378         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4379
4380         job_info->jobid=queue->job;     
4381         init_unistr(&job_info->printername, lp_servicename(snum));
4382         init_unistr(&job_info->machinename, temp_name);
4383         init_unistr(&job_info->username, queue->user);
4384         init_unistr(&job_info->document, queue->file);
4385         init_unistr(&job_info->datatype, "RAW");
4386         init_unistr(&job_info->text_status, "");
4387         job_info->status=nt_printj_status(queue->status);
4388         job_info->priority=queue->priority;
4389         job_info->position=position;
4390         job_info->totalpages=0;
4391         job_info->pagesprinted=0;
4392
4393         make_systemtime(&job_info->submitted, t);
4394 }
4395
4396 /****************************************************************************
4397 ****************************************************************************/
4398 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4399                             int position, int snum, 
4400                             NT_PRINTER_INFO_LEVEL *ntprinter)
4401 {
4402         pstring temp_name;
4403         pstring chaine;
4404         struct tm *t;
4405
4406         t=gmtime(&queue->time);
4407         snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4408
4409         job_info->jobid=queue->job;
4410         
4411         snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4412
4413         init_unistr(&job_info->printername, chaine);
4414         
4415         init_unistr(&job_info->machinename, temp_name);
4416         init_unistr(&job_info->username, queue->user);
4417         init_unistr(&job_info->document, queue->file);
4418         init_unistr(&job_info->notifyname, queue->user);
4419         init_unistr(&job_info->datatype, "RAW");
4420         init_unistr(&job_info->printprocessor, "winprint");
4421         init_unistr(&job_info->parameters, "");
4422         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4423         init_unistr(&job_info->text_status, "");
4424         
4425 /* and here the security descriptor */
4426
4427         job_info->status=nt_printj_status(queue->status);
4428         job_info->priority=queue->priority;
4429         job_info->position=position;
4430         job_info->starttime=0;
4431         job_info->untiltime=0;
4432         job_info->totalpages=0;
4433         job_info->size=queue->size;
4434         make_systemtime(&(job_info->submitted), t);
4435         job_info->timeelapsed=0;
4436         job_info->pagesprinted=0;
4437
4438         if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4439                 return False;
4440         }
4441
4442         return (True);
4443 }
4444
4445 /****************************************************************************
4446  Enumjobs at level 1.
4447 ****************************************************************************/
4448 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4449                               NEW_BUFFER *buffer, uint32 offered,
4450                               uint32 *needed, uint32 *returned)
4451 {
4452         JOB_INFO_1 *info;
4453         int i;
4454         
4455         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4456         if (info==NULL) {
4457                 safe_free(queue);
4458                 *returned=0;
4459                 return ERROR_NOT_ENOUGH_MEMORY;
4460         }
4461         
4462         for (i=0; i<*returned; i++)
4463                 fill_job_info_1(&info[i], &queue[i], i, snum);
4464
4465         safe_free(queue);
4466
4467         /* check the required size. */  
4468         for (i=0; i<*returned; i++)
4469                 (*needed) += spoolss_size_job_info_1(&info[i]);
4470
4471         if (!alloc_buffer_size(buffer, *needed)) {
4472                 safe_free(info);
4473                 return ERROR_INSUFFICIENT_BUFFER;
4474         }
4475
4476         /* fill the buffer with the structures */
4477         for (i=0; i<*returned; i++)
4478                 new_smb_io_job_info_1("", buffer, &info[i], 0); 
4479
4480         /* clear memory */
4481         safe_free(info);
4482
4483         if (*needed > offered) {
4484                 *returned=0;
4485                 return ERROR_INSUFFICIENT_BUFFER;
4486         }
4487         else
4488                 return NT_STATUS_NO_PROBLEMO;
4489 }
4490
4491 /****************************************************************************
4492  Enumjobs at level 2.
4493 ****************************************************************************/
4494 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4495                               NEW_BUFFER *buffer, uint32 offered,
4496                               uint32 *needed, uint32 *returned)
4497 {
4498         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4499         JOB_INFO_2 *info;
4500         int i;
4501         
4502         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4503         if (info==NULL) {
4504                 *returned=0;
4505                 return ERROR_NOT_ENOUGH_MEMORY;
4506         }
4507
4508         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4509                 *returned = 0;
4510                 return ERROR_NOT_ENOUGH_MEMORY;
4511         }
4512                 
4513         for (i=0; i<*returned; i++)
4514                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4515
4516         free_a_printer(&ntprinter, 2);
4517         safe_free(queue);
4518
4519         /* check the required size. */  
4520         for (i=0; i<*returned; i++)
4521                 (*needed) += spoolss_size_job_info_2(&info[i]);
4522
4523         if (!alloc_buffer_size(buffer, *needed)) {
4524                 safe_free(info);
4525                 return ERROR_INSUFFICIENT_BUFFER;
4526         }
4527
4528         /* fill the buffer with the structures */
4529         for (i=0; i<*returned; i++)
4530                 new_smb_io_job_info_2("", buffer, &info[i], 0); 
4531
4532         /* clear memory */
4533         for (i = 0; i < *returned; i++)
4534                 free_job_info_2(&info[i]);
4535
4536         free(info);
4537
4538         if (*needed > offered) {
4539                 *returned=0;
4540                 return ERROR_INSUFFICIENT_BUFFER;
4541         }
4542         else
4543                 return NT_STATUS_NO_PROBLEMO;
4544 }
4545
4546 /****************************************************************************
4547  Enumjobs.
4548 ****************************************************************************/
4549 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,                  
4550                           NEW_BUFFER *buffer, uint32 offered,
4551                           uint32 *needed, uint32 *returned)
4552 {       
4553         int snum;
4554         print_queue_struct *queue=NULL;
4555         print_status_struct prt_status;
4556
4557         DEBUG(4,("_spoolss_enumjobs\n"));
4558
4559         ZERO_STRUCT(prt_status);
4560
4561         *needed=0;
4562         *returned=0;
4563
4564         if (!get_printer_snum(handle, &snum))
4565                 return ERROR_INVALID_HANDLE;
4566
4567         *returned = print_queue_status(snum, &queue, &prt_status);
4568         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4569
4570         if (*returned == 0) {
4571                 safe_free(queue);
4572                 return NT_STATUS_NO_PROBLEMO;
4573         }
4574
4575         switch (level) {
4576         case 1:
4577                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4578         case 2:
4579                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4580         default:
4581                 safe_free(queue);
4582                 *returned=0;
4583                 return ERROR_INVALID_LEVEL;
4584         }
4585 }
4586
4587
4588 /****************************************************************************
4589 ****************************************************************************/
4590 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4591 {
4592         return 0x0;
4593 }
4594
4595 /****************************************************************************
4596 ****************************************************************************/
4597 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4598                        pipes_struct *p, JOB_INFO *ctr, uint32 command)
4599 {
4600         struct current_user user;
4601         print_status_struct prt_status;
4602         int snum, errcode = ERROR_INVALID_FUNCTION;
4603                 
4604         memset(&prt_status, 0, sizeof(prt_status));
4605
4606         if (!get_printer_snum(handle, &snum)) {
4607                 return ERROR_INVALID_HANDLE;
4608         }
4609
4610         if (!print_job_exists(jobid)) {
4611                 return ERROR_INVALID_PRINTER_NAME;
4612         }
4613
4614         get_current_user(&user, p);     
4615
4616         switch (command) {
4617         case JOB_CONTROL_CANCEL:
4618         case JOB_CONTROL_DELETE:
4619                 if (print_job_delete(&user, jobid, &errcode)) {
4620                         errcode = 0;
4621                 }
4622                 break;
4623         case JOB_CONTROL_PAUSE:
4624                 if (print_job_pause(&user, jobid, &errcode)) {
4625                         errcode = 0;
4626                 }               
4627                 break;
4628         case JOB_CONTROL_RESTART:
4629         case JOB_CONTROL_RESUME:
4630                 if (print_job_resume(&user, jobid, &errcode)) {
4631                         errcode = 0;
4632                 }
4633                 break;
4634         default:
4635                 return ERROR_INVALID_LEVEL;
4636         }
4637
4638         return errcode;
4639 }
4640
4641 /****************************************************************************
4642  Enumerates all printer drivers at level 1.
4643 ****************************************************************************/
4644 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4645 {
4646         int i;
4647         int ndrivers;
4648         uint32 version;
4649         fstring *list = NULL;
4650
4651         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4652         DRIVER_INFO_1 *driver_info_1=NULL;
4653
4654         *returned=0;
4655
4656 #define MAX_VERSION 4
4657
4658         for (version=0; version<MAX_VERSION; version++) {
4659                 list=NULL;
4660                 ndrivers=get_ntdrivers(&list, architecture, version);
4661                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4662
4663                 if(ndrivers == -1)
4664                         return ERROR_NOT_ENOUGH_MEMORY;
4665
4666                 if(ndrivers != 0) {
4667                         if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4668                                 safe_free(list);
4669                                 return ERROR_NOT_ENOUGH_MEMORY;
4670                         }
4671                 }
4672
4673                 for (i=0; i<ndrivers; i++) {
4674                         uint32 status;
4675                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4676                         ZERO_STRUCT(driver);
4677                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4678                                 safe_free(list);
4679                                 return status;
4680                         }
4681                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
4682                         free_a_printer_driver(driver, 3);
4683                 }       
4684
4685                 *returned+=ndrivers;
4686                 safe_free(list);
4687         }
4688         
4689         /* check the required size. */
4690         for (i=0; i<*returned; i++) {
4691                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4692                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4693         }
4694
4695         if (!alloc_buffer_size(buffer, *needed)) {
4696                 safe_free(driver_info_1);
4697                 return ERROR_INSUFFICIENT_BUFFER;
4698         }
4699
4700         /* fill the buffer with the form structures */
4701         for (i=0; i<*returned; i++) {
4702                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4703                 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4704         }
4705
4706         safe_free(driver_info_1);
4707
4708         if (*needed > offered) {
4709                 *returned=0;
4710                 return ERROR_INSUFFICIENT_BUFFER;
4711         }
4712         else
4713                 return NT_STATUS_NO_PROBLEMO;
4714 }
4715
4716 /****************************************************************************
4717  Enumerates all printer drivers at level 2.
4718 ****************************************************************************/
4719 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4720 {
4721         int i;
4722         int ndrivers;
4723         uint32 version;
4724         fstring *list = NULL;
4725
4726         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4727         DRIVER_INFO_2 *driver_info_2=NULL;
4728
4729         *returned=0;
4730
4731 #define MAX_VERSION 4
4732
4733         for (version=0; version<MAX_VERSION; version++) {
4734                 list=NULL;
4735                 ndrivers=get_ntdrivers(&list, architecture, version);
4736                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4737
4738                 if(ndrivers == -1)
4739                         return ERROR_NOT_ENOUGH_MEMORY;
4740
4741                 if(ndrivers != 0) {
4742                         if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4743                                 safe_free(list);
4744                                 return ERROR_NOT_ENOUGH_MEMORY;
4745                         }
4746                 }
4747                 
4748                 for (i=0; i<ndrivers; i++) {
4749                         uint32 status;
4750
4751                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4752                         ZERO_STRUCT(driver);
4753                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4754                                 safe_free(list);
4755                                 return status;
4756                         }
4757                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
4758                         free_a_printer_driver(driver, 3);
4759                 }       
4760
4761                 *returned+=ndrivers;
4762                 safe_free(list);
4763         }
4764         
4765         /* check the required size. */
4766         for (i=0; i<*returned; i++) {
4767                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4768                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4769         }
4770
4771         if (!alloc_buffer_size(buffer, *needed)) {
4772                 safe_free(driver_info_2);
4773                 return ERROR_INSUFFICIENT_BUFFER;
4774         }
4775
4776         /* fill the buffer with the form structures */
4777         for (i=0; i<*returned; i++) {
4778                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4779                 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4780         }
4781
4782         safe_free(driver_info_2);
4783
4784         if (*needed > offered) {
4785                 *returned=0;
4786                 return ERROR_INSUFFICIENT_BUFFER;
4787         }
4788         else
4789                 return NT_STATUS_NO_PROBLEMO;
4790 }
4791
4792 /****************************************************************************
4793  Enumerates all printer drivers at level 3.
4794 ****************************************************************************/
4795 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4796 {
4797         int i;
4798         int ndrivers;
4799         uint32 version;
4800         fstring *list = NULL;
4801
4802         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4803         DRIVER_INFO_3 *driver_info_3=NULL;
4804
4805         *returned=0;
4806
4807 #define MAX_VERSION 4
4808
4809         for (version=0; version<MAX_VERSION; version++) {
4810                 list=NULL;
4811                 ndrivers=get_ntdrivers(&list, architecture, version);
4812                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4813
4814                 if(ndrivers == -1)
4815                         return ERROR_NOT_ENOUGH_MEMORY;
4816
4817                 if(ndrivers != 0) {
4818                         if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4819                                 safe_free(list);
4820                                 return ERROR_NOT_ENOUGH_MEMORY;
4821                         }
4822                 }
4823
4824                 for (i=0; i<ndrivers; i++) {
4825                         uint32 status;
4826
4827                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4828                         ZERO_STRUCT(driver);
4829                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4830                                 safe_free(list);
4831                                 return status;
4832                         }
4833                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
4834                         free_a_printer_driver(driver, 3);
4835                 }       
4836
4837                 *returned+=ndrivers;
4838                 safe_free(list);
4839         }
4840
4841         /* check the required size. */
4842         for (i=0; i<*returned; i++) {
4843                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4844                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4845         }
4846
4847         if (!alloc_buffer_size(buffer, *needed)) {
4848                 safe_free(driver_info_3);
4849                 return ERROR_INSUFFICIENT_BUFFER;
4850         }
4851         
4852         /* fill the buffer with the driver structures */
4853         for (i=0; i<*returned; i++) {
4854                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4855                 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4856         }
4857
4858         for (i=0; i<*returned; i++)
4859                 safe_free(driver_info_3[i].dependentfiles);
4860         
4861         safe_free(driver_info_3);
4862         
4863         if (*needed > offered) {
4864                 *returned=0;
4865                 return ERROR_INSUFFICIENT_BUFFER;
4866         }
4867         else
4868                 return NT_STATUS_NO_PROBLEMO;
4869 }
4870
4871 /****************************************************************************
4872  Enumerates all printer drivers.
4873 ****************************************************************************/
4874 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4875                                     NEW_BUFFER *buffer, uint32 offered,
4876                                     uint32 *needed, uint32 *returned)
4877 {
4878         fstring *list = NULL;
4879         fstring servername;
4880         fstring architecture;
4881
4882         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4883         fstrcpy(servername, global_myname);
4884         *needed=0;
4885         *returned=0;
4886
4887         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4888
4889         switch (level) {
4890         case 1:
4891                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4892         case 2:
4893                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4894         case 3:
4895                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4896         default:
4897                 *returned=0;
4898                 safe_free(list);
4899                 return ERROR_INVALID_LEVEL;
4900         }
4901 }
4902
4903 /****************************************************************************
4904 ****************************************************************************/
4905 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4906 {
4907         form->flag=list->flag;
4908         init_unistr(&form->name, list->name);
4909         form->width=list->width;
4910         form->length=list->length;
4911         form->left=list->left;
4912         form->top=list->top;
4913         form->right=list->right;
4914         form->bottom=list->bottom;      
4915 }
4916         
4917 /****************************************************************************
4918 ****************************************************************************/
4919 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4920                                NEW_BUFFER *buffer, uint32 offered,
4921                                uint32 *needed, uint32 *numofforms)
4922 {
4923         nt_forms_struct *list=NULL;
4924         FORM_1 *forms_1;
4925         int buffer_size=0;
4926         int i;
4927
4928         DEBUG(4,("_new_spoolss_enumforms\n"));
4929         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4930         DEBUGADD(5,("Info level [%d]\n",          level));
4931
4932         *numofforms = get_ntforms(&list);
4933         DEBUGADD(5,("Number of forms [%d]\n",     *numofforms));
4934
4935         if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4936
4937         switch (level) {
4938         case 1:
4939                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4940                         *numofforms=0;
4941                         return ERROR_NOT_ENOUGH_MEMORY;
4942                 }
4943
4944                 /* construct the list of form structures */
4945                 for (i=0; i<*numofforms; i++) {
4946                         DEBUGADD(6,("Filling form number [%d]\n",i));
4947                         fill_form_1(&forms_1[i], &list[i]);
4948                 }
4949                 
4950                 safe_free(list);
4951
4952                 /* check the required size. */
4953                 for (i=0; i<*numofforms; i++) {
4954                         DEBUGADD(6,("adding form [%d]'s size\n",i));
4955                         buffer_size += spoolss_size_form_1(&forms_1[i]);
4956                 }
4957
4958                 *needed=buffer_size;            
4959                 
4960                 if (!alloc_buffer_size(buffer, buffer_size)){
4961                         safe_free(forms_1);
4962                         return ERROR_INSUFFICIENT_BUFFER;
4963                 }
4964
4965                 /* fill the buffer with the form structures */
4966                 for (i=0; i<*numofforms; i++) {
4967                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
4968                         new_smb_io_form_1("", buffer, &forms_1[i], 0);
4969                 }
4970
4971                 safe_free(forms_1);
4972
4973                 if (*needed > offered) {
4974                         *numofforms=0;
4975                         return ERROR_INSUFFICIENT_BUFFER;
4976                 }
4977                 else
4978                         return NT_STATUS_NO_PROBLEMO;
4979                         
4980         default:
4981                 safe_free(list);
4982                 return ERROR_INVALID_LEVEL;
4983         }
4984
4985 }
4986
4987 /****************************************************************************
4988 ****************************************************************************/
4989 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4990 {
4991         nt_forms_struct *list=NULL;
4992         FORM_1 form_1;
4993         fstring form_name;
4994         int buffer_size=0;
4995         int numofforms, i;
4996
4997         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4998
4999         DEBUG(4,("_spoolss_getform\n"));
5000         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5001         DEBUGADD(5,("Info level [%d]\n",          level));
5002
5003         numofforms = get_ntforms(&list);
5004         DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
5005
5006         if (numofforms == 0)
5007                 return ERROR_NO_MORE_ITEMS;
5008
5009         switch (level) {
5010         case 1:
5011
5012                 /* Check if the requested name is in the list of form structures */
5013                 for (i=0; i<numofforms; i++) {
5014
5015                         DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5016
5017                         if (strequal(form_name, list[i].name)) {
5018                                 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5019                                 fill_form_1(&form_1, &list[i]);
5020                                 break;
5021                         }
5022                 }
5023                 
5024                 safe_free(list);
5025
5026                 /* check the required size. */
5027
5028                 *needed=spoolss_size_form_1(&form_1);
5029                 
5030                 if (!alloc_buffer_size(buffer, buffer_size)){
5031                         return ERROR_INSUFFICIENT_BUFFER;
5032                 }
5033
5034                 if (*needed > offered) {
5035                         return ERROR_INSUFFICIENT_BUFFER;
5036                 }
5037
5038                 /* fill the buffer with the form structures */
5039                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5040                 new_smb_io_form_1("", buffer, &form_1, 0);
5041
5042                 return NT_STATUS_NO_PROBLEMO;
5043                         
5044         default:
5045                 safe_free(list);
5046                 return ERROR_INVALID_LEVEL;
5047         }
5048 }
5049
5050 /****************************************************************************
5051 ****************************************************************************/
5052 static void fill_port_1(PORT_INFO_1 *port, char *name)
5053 {
5054         init_unistr(&port->port_name, name);
5055 }
5056
5057 /****************************************************************************
5058 ****************************************************************************/
5059 static void fill_port_2(PORT_INFO_2 *port, char *name)
5060 {
5061         init_unistr(&port->port_name, name);
5062         init_unistr(&port->monitor_name, "Local Monitor");
5063         init_unistr(&port->description, "Local Port");
5064 #define PORT_TYPE_WRITE 1
5065         port->port_type=PORT_TYPE_WRITE;
5066         port->reserved=0x0;     
5067 }
5068
5069 /****************************************************************************
5070  enumports level 1.
5071 ****************************************************************************/
5072 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5073 {
5074         PORT_INFO_1 *ports=NULL;
5075         int i=0;
5076
5077         if (*lp_enumports_cmd()) {
5078                 pid_t local_pid = sys_getpid();
5079                 char *cmd = lp_enumports_cmd();
5080                 char *path;
5081                 char **qlines;
5082                 pstring tmp_file;
5083                 pstring command;
5084                 int numlines;
5085                 int ret;
5086
5087                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5088                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5089                 else
5090                         path = tmpdir();
5091
5092                 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5093                 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
5094
5095                 unlink(tmp_file);
5096                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5097                 ret = smbrun(command, tmp_file, False);
5098                 DEBUG(10,("Returned [%d]\n", ret));
5099                 if (ret != 0) {
5100                         unlink(tmp_file);
5101                         /* Is this the best error to return here? */
5102                         return ERROR_ACCESS_DENIED;
5103                 }
5104
5105                 numlines = 0;
5106                 qlines = file_lines_load(tmp_file, &numlines,True);
5107                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5108                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5109                 unlink(tmp_file);
5110
5111                 if(numlines) {
5112                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5113                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5114                                 file_lines_free(qlines);
5115                                 return ERROR_NOT_ENOUGH_MEMORY;
5116                         }
5117
5118                         for (i=0; i<numlines; i++) {
5119                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5120                                 fill_port_1(&ports[i], qlines[i]);
5121                         }
5122
5123                         file_lines_free(qlines);
5124                 }
5125
5126                 *returned = numlines;
5127
5128         } else {
5129                 *returned = 1; /* Sole Samba port returned. */
5130
5131                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5132                         return ERROR_NOT_ENOUGH_MEMORY;
5133         
5134                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5135
5136                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5137         }
5138
5139         /* check the required size. */
5140         for (i=0; i<*returned; i++) {
5141                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5142                 *needed += spoolss_size_port_info_1(&ports[i]);
5143         }
5144                 
5145         if (!alloc_buffer_size(buffer, *needed)) {
5146                 safe_free(ports);
5147                 return ERROR_INSUFFICIENT_BUFFER;
5148         }
5149
5150         /* fill the buffer with the ports structures */
5151         for (i=0; i<*returned; i++) {
5152                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5153                 new_smb_io_port_1("", buffer, &ports[i], 0);
5154         }
5155
5156         safe_free(ports);
5157
5158         if (*needed > offered) {
5159                 *returned=0;
5160                 return ERROR_INSUFFICIENT_BUFFER;
5161         }
5162         else
5163                 return NT_STATUS_NO_PROBLEMO;
5164 }
5165
5166 /****************************************************************************
5167  enumports level 2.
5168 ****************************************************************************/
5169
5170 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5171 {
5172         PORT_INFO_2 *ports=NULL;
5173         int i=0;
5174
5175         if (*lp_enumports_cmd()) {
5176                 pid_t local_pid = sys_getpid();
5177                 char *cmd = lp_enumports_cmd();
5178                 char *path;
5179                 char **qlines;
5180                 pstring tmp_file;
5181                 pstring command;
5182                 int numlines;
5183                 int ret;
5184
5185                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5186                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5187                 else
5188                         path = tmpdir();
5189
5190                 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5191                 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
5192
5193                 unlink(tmp_file);
5194                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5195                 ret = smbrun(command, tmp_file, False);
5196                 DEBUGADD(10,("returned [%d]\n", ret));
5197                 if (ret != 0) {
5198                         unlink(tmp_file);
5199                         /* Is this the best error to return here? */
5200                         return ERROR_ACCESS_DENIED;
5201                 }
5202
5203                 numlines = 0;
5204                 qlines = file_lines_load(tmp_file, &numlines,True);
5205                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5206                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5207                 unlink(tmp_file);
5208
5209                 if(numlines) {
5210                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5211                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5212                                 file_lines_free(qlines);
5213                                 return ERROR_NOT_ENOUGH_MEMORY;
5214                         }
5215
5216                         for (i=0; i<numlines; i++) {
5217                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5218                                 fill_port_2(&(ports[i]), qlines[i]);
5219                         }
5220
5221                         file_lines_free(qlines);
5222                 }
5223
5224                 *returned = numlines;
5225
5226         } else {
5227
5228                 *returned = 1;
5229
5230                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5231                         return ERROR_NOT_ENOUGH_MEMORY;
5232         
5233                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5234
5235                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5236         }
5237
5238         /* check the required size. */
5239         for (i=0; i<*returned; i++) {
5240                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5241                 *needed += spoolss_size_port_info_2(&ports[i]);
5242         }
5243                 
5244         if (!alloc_buffer_size(buffer, *needed)) {
5245                 safe_free(ports);
5246                 return ERROR_INSUFFICIENT_BUFFER;
5247         }
5248
5249         /* fill the buffer with the ports structures */
5250         for (i=0; i<*returned; i++) {
5251                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5252                 new_smb_io_port_2("", buffer, &ports[i], 0);
5253         }
5254
5255         safe_free(ports);
5256
5257         if (*needed > offered) {
5258                 *returned=0;
5259                 return ERROR_INSUFFICIENT_BUFFER;
5260         }
5261         else
5262                 return NT_STATUS_NO_PROBLEMO;
5263 }
5264
5265 /****************************************************************************
5266  enumports.
5267 ****************************************************************************/
5268 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5269                            NEW_BUFFER *buffer, uint32 offered,
5270                            uint32 *needed, uint32 *returned)
5271 {
5272         DEBUG(4,("_spoolss_enumports\n"));
5273         
5274         *returned=0;
5275         *needed=0;
5276         
5277         switch (level) {
5278         case 1:
5279                 return enumports_level_1(buffer, offered, needed, returned);
5280         case 2:
5281                 return enumports_level_2(buffer, offered, needed, returned);
5282         default:
5283                 return ERROR_INVALID_LEVEL;
5284         }
5285 }
5286
5287 /****************************************************************************
5288 ****************************************************************************/
5289 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5290                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5291                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5292                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5293                                 POLICY_HND *handle)
5294 {
5295         NT_PRINTER_INFO_LEVEL *printer = NULL;
5296         fstring name;
5297         int snum;
5298
5299         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5300                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5301                 return ERROR_NOT_ENOUGH_MEMORY;
5302         }
5303
5304         ZERO_STRUCTP(printer);
5305
5306         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5307         convert_printer_info(info, printer, 2);
5308
5309         if (*lp_addprinter_cmd() )
5310                 if ( !add_printer_hook(printer) ) {
5311                         free_a_printer(&printer,2);
5312                         return ERROR_ACCESS_DENIED;
5313         }
5314
5315         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5316              printer->info_2->sharename);
5317
5318         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5319                 free_a_printer(&printer,2);
5320                 return ERROR_ACCESS_DENIED;
5321         }
5322
5323         /* you must be a printer admin to add a new printer */
5324         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5325                 free_a_printer(&printer,2);
5326                 return ERROR_ACCESS_DENIED;             
5327         }
5328         
5329         /*
5330          * Do sanity check on the requested changes for Samba.
5331          */
5332
5333         if (!check_printer_ok(printer->info_2, snum)) {
5334                 free_a_printer(&printer,2);
5335                 return ERROR_INVALID_PARAMETER;
5336         }
5337
5338         /* write the ASCII on disk */
5339         if (add_a_printer(*printer, 2) != 0) {
5340                 free_a_printer(&printer,2);
5341                 return ERROR_ACCESS_DENIED;
5342         }
5343
5344         if (!open_printer_hnd(handle, name)) {
5345                 /* Handle open failed - remove addition. */
5346                 del_a_printer(printer->info_2->sharename);
5347                 free_a_printer(&printer,2);
5348                 return ERROR_ACCESS_DENIED;
5349         }
5350
5351         free_a_printer(&printer,2);
5352
5353         srv_spoolss_sendnotify(handle);
5354
5355         return NT_STATUS_NO_PROBLEMO;
5356 }
5357
5358 /****************************************************************************
5359 ****************************************************************************/
5360 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5361                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5362                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5363                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5364                                 POLICY_HND *handle)
5365 {
5366         switch (level) {
5367                 case 1:
5368                         /* we don't handle yet */
5369                         /* but I know what to do ... */
5370                         return ERROR_INVALID_LEVEL;
5371                 case 2:
5372                         return spoolss_addprinterex_level_2(uni_srv_name, info,
5373                                                             unk0, unk1, unk2, unk3,
5374                                                             user_switch, user, handle);
5375                 default:
5376                         return ERROR_INVALID_LEVEL;
5377         }
5378 }
5379
5380 /****************************************************************************
5381 ****************************************************************************/
5382 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5383                                  uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5384 {
5385         uint32 err = NT_STATUS_NO_PROBLEMO;
5386         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5387         struct current_user user;
5388         
5389         ZERO_STRUCT(driver);
5390
5391         get_current_user(&user, p);     
5392         
5393         convert_printer_driver_info(info, &driver, level);
5394
5395         DEBUG(5,("Cleaning driver's information\n"));
5396         if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5397                 goto done;
5398
5399         DEBUG(5,("Moving driver to final destination\n"));
5400         if(!move_driver_to_download_area(driver, level, &user, &err)) {
5401                 if (err == 0)
5402                         err = ERROR_ACCESS_DENIED;
5403                 goto done;
5404         }
5405
5406         if (add_a_printer_driver(driver, level)!=0) {
5407                 err = ERROR_ACCESS_DENIED;
5408                 goto done;
5409         }
5410
5411  done:
5412         free_a_printer_driver(driver, level);
5413         return err;
5414 }
5415
5416 /****************************************************************************
5417 ****************************************************************************/
5418 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5419 {
5420         init_unistr(&info->name, name);
5421 }
5422
5423 /****************************************************************************
5424 ****************************************************************************/
5425 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5426 {
5427         pstring path;
5428         pstring long_archi;
5429         pstring short_archi;
5430         DRIVER_DIRECTORY_1 *info=NULL;
5431
5432         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5433
5434         if (get_short_archi(short_archi, long_archi)==FALSE)
5435                 return ERROR_INVALID_ENVIRONMENT;
5436
5437         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5438                 return ERROR_NOT_ENOUGH_MEMORY;
5439
5440         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5441
5442         DEBUG(4,("printer driver directory: [%s]\n", path));
5443
5444         fill_driverdir_1(info, path);
5445         
5446         *needed += spoolss_size_driverdir_info_1(info);
5447
5448         if (!alloc_buffer_size(buffer, *needed)) {
5449                 safe_free(info);
5450                 return ERROR_INSUFFICIENT_BUFFER;
5451         }
5452
5453         new_smb_io_driverdir_1("", buffer, info, 0);
5454
5455         safe_free(info);
5456         
5457         if (*needed > offered)
5458                 return ERROR_INSUFFICIENT_BUFFER;
5459         else
5460                 return NT_STATUS_NO_PROBLEMO;
5461 }
5462
5463 /****************************************************************************
5464 ****************************************************************************/
5465 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5466                                         NEW_BUFFER *buffer, uint32 offered,
5467                                         uint32 *needed)
5468 {
5469         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5470
5471         *needed=0;
5472
5473         switch(level) {
5474         case 1:
5475                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5476         default:
5477                 return ERROR_INVALID_LEVEL;
5478         }
5479 }
5480         
5481 /****************************************************************************
5482 ****************************************************************************/
5483 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5484                                 uint32 in_value_len, uint32 in_data_len,
5485                                 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5486                                 uint32 *out_type,
5487                                 uint32 *out_max_data_len, uint8  **data_out, uint32 *out_data_len)
5488 {
5489         NT_PRINTER_INFO_LEVEL *printer = NULL;
5490         
5491         fstring value;
5492         
5493         uint32 param_index;
5494         uint32 biggest_valuesize;
5495         uint32 biggest_datasize;
5496         uint32 data_len;
5497         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5498         int snum;
5499         uint8 *data=NULL;
5500         uint32 type;
5501
5502         ZERO_STRUCT(printer);
5503         
5504         *out_max_value_len=0;
5505         *out_value=NULL;
5506         *out_value_len=0;
5507
5508         *out_type=0;
5509
5510         *out_max_data_len=0;
5511         *data_out=NULL;
5512         *out_data_len=0;
5513
5514         DEBUG(5,("spoolss_enumprinterdata\n"));
5515
5516         if (!OPEN_HANDLE(Printer)) {
5517                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5518                 return ERROR_INVALID_HANDLE;
5519         }
5520
5521         if (!get_printer_snum(handle, &snum))
5522                 return ERROR_INVALID_HANDLE;
5523         
5524         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5525                 return ERROR_INVALID_HANDLE;
5526
5527         /*
5528          * The NT machine wants to know the biggest size of value and data
5529          *
5530          * cf: MSDN EnumPrinterData remark section
5531          */
5532         if ( (in_value_len==0) && (in_data_len==0) ) {
5533                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5534
5535 #if 0
5536                 /*
5537                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5538                  * if this parameter size doesn't exist.
5539                  * Ok - my opinion here is that the client is not asking for the greatest
5540                  * possible size of all the parameters, but is asking specifically for the size needed
5541                  * for this specific parameter. In that case we can remove the loop below and
5542                  * simplify this lookup code considerably. JF - comments welcome. JRA.
5543                  */
5544
5545                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5546                         safe_free(data);
5547                         free_a_printer(&printer, 2);
5548                         return ERROR_NO_MORE_ITEMS;
5549                 }
5550 #endif
5551
5552                 safe_free(data);
5553                 data = NULL;
5554
5555                 param_index=0;
5556                 biggest_valuesize=0;
5557                 biggest_datasize=0;
5558                 
5559                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5560                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5561                         if (data_len > biggest_datasize) biggest_datasize=data_len;
5562
5563                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5564
5565                         safe_free(data);
5566                         data = NULL;
5567                         param_index++;
5568                 }
5569
5570                 /*
5571                  * I think this is correct, it doesn't break APW and
5572                  * allows Gerald's Win32 test programs to work correctly,
5573                  * but may need altering.... JRA.
5574                  */
5575
5576                 if (param_index == 0) {
5577                         /* No parameters found. */
5578                         free_a_printer(&printer, 2);
5579                         return ERROR_NO_MORE_ITEMS;
5580                 }
5581
5582                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5583                 *out_value_len=2*(1+biggest_valuesize);
5584                 *out_data_len=biggest_datasize;
5585
5586                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5587
5588                 free_a_printer(&printer, 2);
5589                 return NT_STATUS_NO_PROBLEMO;
5590         }
5591         
5592         /*
5593          * the value len is wrong in NT sp3
5594          * that's the number of bytes not the number of unicode chars
5595          */
5596
5597         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5598                 safe_free(data);
5599                 free_a_printer(&printer, 2);
5600                 return ERROR_NO_MORE_ITEMS;
5601         }
5602
5603         free_a_printer(&printer, 2);
5604
5605         /*
5606          * the value is:
5607          * - counted in bytes in the request
5608          * - counted in UNICODE chars in the max reply
5609          * - counted in bytes in the real size
5610          *
5611          * take a pause *before* coding not *during* coding
5612          */
5613         
5614         *out_max_value_len=(in_value_len/sizeof(uint16));
5615         if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5616                 safe_free(data);
5617                 return ERROR_NOT_ENOUGH_MEMORY;
5618         }
5619         
5620         ZERO_STRUCTP(*out_value);
5621         *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5622
5623         *out_type=type;
5624
5625         /* the data is counted in bytes */
5626         *out_max_data_len=in_data_len;
5627         if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5628                 safe_free(data);
5629                 return ERROR_NOT_ENOUGH_MEMORY;
5630         }
5631         
5632         memset(*data_out,'\0',in_data_len);
5633         memcpy(*data_out, data, (size_t)data_len);
5634         *out_data_len=data_len;
5635
5636         safe_free(data);
5637         
5638         return NT_STATUS_NO_PROBLEMO;
5639 }
5640
5641 /****************************************************************************
5642 ****************************************************************************/
5643 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5644                                 const UNISTR2 *value,
5645                                 uint32 type,
5646                                 uint32 max_len,
5647                                 const uint8 *data,
5648                                 uint32 real_len,
5649                                 uint32 numeric_data)
5650 {
5651         NT_PRINTER_INFO_LEVEL *printer = NULL;
5652         NT_PRINTER_PARAM *param = NULL, old_param;
5653         int snum=0;
5654         uint32 status = 0x0;
5655         Printer_entry *Printer=find_printer_index_by_hnd(handle);
5656         
5657         DEBUG(5,("spoolss_setprinterdata\n"));
5658
5659         if (!OPEN_HANDLE(Printer)) {
5660                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5661                 return ERROR_INVALID_HANDLE;
5662         }
5663
5664         if (!get_printer_snum(handle, &snum))
5665                 return ERROR_INVALID_HANDLE;
5666
5667         status = get_a_printer(&printer, 2, lp_servicename(snum));
5668         if (status != 0x0)
5669                 return ERROR_INVALID_NAME;
5670
5671         convert_specific_param(&param, value , type, data, real_len);
5672
5673         /* Check if we are making any changes or not.  Return true if
5674            nothing is actually changing. */
5675
5676         ZERO_STRUCT(old_param);
5677
5678         if (get_specific_param(*printer, 2, param->value, &old_param.data,
5679                                &old_param.type, (unsigned int *)&old_param.data_len)) {
5680
5681                 if (param->type == old_param.type &&
5682                     param->data_len == old_param.data_len &&
5683                     memcmp(param->data, old_param.data,
5684                            old_param.data_len) == 0) {
5685
5686                         DEBUG(3, ("setprinterdata hasn't changed\n"));
5687                         status = NT_STATUS_NO_PROBLEMO;
5688                         goto done;
5689                 }
5690         }
5691
5692         /* Access check */
5693
5694         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5695                 DEBUG(3, ("security descriptor change denied by existing "
5696                           "security descriptor\n"));
5697                 status = ERROR_ACCESS_DENIED;
5698                 goto done;
5699         }
5700
5701         unlink_specific_param_if_exist(printer->info_2, param);
5702         
5703         add_a_specific_param(printer->info_2, &param);
5704         status = mod_a_printer(*printer, 2);
5705
5706  done:
5707         free_a_printer(&printer, 2);
5708         if (param)
5709                 free_nt_printer_param(&param);
5710         safe_free(old_param.data);
5711
5712         return status;
5713 }
5714
5715 /****************************************************************************
5716 ****************************************************************************/
5717 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5718 {
5719         NT_PRINTER_INFO_LEVEL *printer = NULL;
5720         NT_PRINTER_PARAM param;
5721         int snum=0;
5722         uint32 status = 0x0;
5723         Printer_entry *Printer=find_printer_index_by_hnd(handle);
5724         
5725         DEBUG(5,("spoolss_deleteprinterdata\n"));
5726         
5727         if (!OPEN_HANDLE(Printer)) {
5728                 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5729                 return ERROR_INVALID_HANDLE;
5730         }
5731
5732         if (!get_printer_snum(handle, &snum))
5733                 return ERROR_INVALID_HANDLE;
5734
5735         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5736                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5737                           "change denied by existing security descriptor\n"));
5738                 return ERROR_ACCESS_DENIED;
5739         }
5740
5741         status = get_a_printer(&printer, 2, lp_servicename(snum));
5742         if (status != 0x0)
5743                 return ERROR_INVALID_NAME;
5744
5745         ZERO_STRUCTP(&param);
5746         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5747
5748         if(!unlink_specific_param_if_exist(printer->info_2, &param))
5749                 status = ERROR_INVALID_PARAMETER;
5750         else
5751                 status = mod_a_printer(*printer, 2);
5752
5753         free_a_printer(&printer, 2);
5754         return status;
5755 }
5756
5757 /****************************************************************************
5758 ****************************************************************************/
5759 uint32 _spoolss_addform( POLICY_HND *handle,
5760                                 uint32 level,
5761                                 const FORM *form)
5762 {
5763         int count=0;
5764         nt_forms_struct *list=NULL;
5765         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5766
5767         DEBUG(5,("spoolss_addform\n"));
5768
5769         if (!OPEN_HANDLE(Printer)) {
5770                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5771                 return ERROR_INVALID_HANDLE;
5772         }
5773
5774         count=get_ntforms(&list);
5775         if(!add_a_form(&list, form, &count))
5776                 return ERROR_NOT_ENOUGH_MEMORY;
5777         write_ntforms(&list, count);
5778
5779         safe_free(list);
5780
5781         return 0x0;
5782 }
5783
5784 /****************************************************************************
5785 ****************************************************************************/
5786 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5787 {
5788         int count=0;
5789         uint32 ret = 0;
5790         nt_forms_struct *list=NULL;
5791         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5792
5793         DEBUG(5,("spoolss_deleteform\n"));
5794
5795         if (!OPEN_HANDLE(Printer)) {
5796                 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5797                 return ERROR_INVALID_HANDLE;
5798         }
5799
5800         count = get_ntforms(&list);
5801         if(!delete_a_form(&list, form_name, &count, &ret))
5802                 return ERROR_INVALID_PARAMETER;
5803
5804         safe_free(list);
5805
5806         return ret;
5807 }
5808
5809 /****************************************************************************
5810 ****************************************************************************/
5811 uint32 _spoolss_setform( POLICY_HND *handle,
5812                                 const UNISTR2 *uni_name,
5813                                 uint32 level,
5814                                 const FORM *form)
5815 {
5816         int count=0;
5817         nt_forms_struct *list=NULL;
5818         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5819
5820         DEBUG(5,("spoolss_setform\n"));
5821
5822         if (!OPEN_HANDLE(Printer)) {
5823                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5824                 return ERROR_INVALID_HANDLE;
5825         }
5826         count=get_ntforms(&list);
5827         update_a_form(&list, form, count);
5828         write_ntforms(&list, count);
5829
5830         safe_free(list);
5831
5832         return 0x0;
5833 }
5834
5835 /****************************************************************************
5836  enumprintprocessors level 1.
5837 ****************************************************************************/
5838 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5839 {
5840         PRINTPROCESSOR_1 *info_1=NULL;
5841         
5842         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5843                 return ERROR_NOT_ENOUGH_MEMORY;
5844
5845         (*returned) = 0x1;
5846         
5847         init_unistr(&info_1->name, "winprint");
5848
5849         *needed += spoolss_size_printprocessor_info_1(info_1);
5850
5851         if (!alloc_buffer_size(buffer, *needed))
5852                 return ERROR_INSUFFICIENT_BUFFER;
5853
5854         smb_io_printprocessor_info_1("", buffer, info_1, 0);
5855
5856         safe_free(info_1);
5857
5858         if (*needed > offered) {
5859                 *returned=0;
5860                 return ERROR_INSUFFICIENT_BUFFER;
5861         }
5862         else
5863                 return NT_STATUS_NO_PROBLEMO;
5864 }
5865
5866 /****************************************************************************
5867 ****************************************************************************/
5868 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5869                                     NEW_BUFFER *buffer, uint32 offered,
5870                                     uint32 *needed, uint32 *returned)
5871 {
5872         DEBUG(5,("spoolss_enumprintprocessors\n"));
5873
5874         /*
5875          * Enumerate the print processors ...
5876          *
5877          * Just reply with "winprint", to keep NT happy
5878          * and I can use my nice printer checker.
5879          */
5880         
5881         *returned=0;
5882         *needed=0;
5883         
5884         switch (level) {
5885         case 1:
5886                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5887         default:
5888                 return ERROR_INVALID_LEVEL;
5889         }
5890 }
5891
5892 /****************************************************************************
5893  enumprintprocdatatypes level 1.
5894 ****************************************************************************/
5895 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5896 {
5897         PRINTPROCDATATYPE_1 *info_1=NULL;
5898         
5899         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5900                 return ERROR_NOT_ENOUGH_MEMORY;
5901
5902         (*returned) = 0x1;
5903         
5904         init_unistr(&info_1->name, "RAW");
5905
5906         *needed += spoolss_size_printprocdatatype_info_1(info_1);
5907
5908         if (!alloc_buffer_size(buffer, *needed))
5909                 return ERROR_INSUFFICIENT_BUFFER;
5910
5911         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5912
5913         safe_free(info_1);
5914
5915         if (*needed > offered) {
5916                 *returned=0;
5917                 return ERROR_INSUFFICIENT_BUFFER;
5918         }
5919         else
5920                 return NT_STATUS_NO_PROBLEMO;
5921 }
5922
5923 /****************************************************************************
5924 ****************************************************************************/
5925 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5926                                         NEW_BUFFER *buffer, uint32 offered,
5927                                         uint32 *needed, uint32 *returned)
5928 {
5929         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5930         
5931         *returned=0;
5932         *needed=0;
5933         
5934         switch (level) {
5935         case 1:
5936                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5937         default:
5938                 return ERROR_INVALID_LEVEL;
5939         }
5940 }
5941
5942 /****************************************************************************
5943  enumprintmonitors level 1.
5944 ****************************************************************************/
5945 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5946 {
5947         PRINTMONITOR_1 *info_1=NULL;
5948         
5949         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5950                 return ERROR_NOT_ENOUGH_MEMORY;
5951
5952         (*returned) = 0x1;
5953         
5954         init_unistr(&info_1->name, "Local Port");
5955
5956         *needed += spoolss_size_printmonitor_info_1(info_1);
5957
5958         if (!alloc_buffer_size(buffer, *needed))
5959                 return ERROR_INSUFFICIENT_BUFFER;
5960
5961         smb_io_printmonitor_info_1("", buffer, info_1, 0);
5962
5963         safe_free(info_1);
5964
5965         if (*needed > offered) {
5966                 *returned=0;
5967                 return ERROR_INSUFFICIENT_BUFFER;
5968         }
5969         else
5970                 return NT_STATUS_NO_PROBLEMO;
5971 }
5972
5973 /****************************************************************************
5974  enumprintmonitors level 2.
5975 ****************************************************************************/
5976 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5977 {
5978         PRINTMONITOR_2 *info_2=NULL;
5979         
5980         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5981                 return ERROR_NOT_ENOUGH_MEMORY;
5982
5983         (*returned) = 0x1;
5984         
5985         init_unistr(&info_2->name, "Local Port");
5986         init_unistr(&info_2->environment, "Windows NT X86");
5987         init_unistr(&info_2->dll_name, "localmon.dll");
5988
5989         *needed += spoolss_size_printmonitor_info_2(info_2);
5990
5991         if (!alloc_buffer_size(buffer, *needed))
5992                 return ERROR_INSUFFICIENT_BUFFER;
5993
5994         smb_io_printmonitor_info_2("", buffer, info_2, 0);
5995
5996         safe_free(info_2);
5997
5998         if (*needed > offered) {
5999                 *returned=0;
6000                 return ERROR_INSUFFICIENT_BUFFER;
6001         }
6002         else
6003                 return NT_STATUS_NO_PROBLEMO;
6004 }
6005
6006 /****************************************************************************
6007 ****************************************************************************/
6008 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6009                                     NEW_BUFFER *buffer, uint32 offered,
6010                                     uint32 *needed, uint32 *returned)
6011 {
6012         DEBUG(5,("spoolss_enumprintmonitors\n"));
6013
6014         /*
6015          * Enumerate the print monitors ...
6016          *
6017          * Just reply with "Local Port", to keep NT happy
6018          * and I can use my nice printer checker.
6019          */
6020         
6021         *returned=0;
6022         *needed=0;
6023         
6024         switch (level) {
6025         case 1:
6026                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6027         case 2:
6028                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6029         default:
6030                 return ERROR_INVALID_LEVEL;
6031         }
6032 }
6033
6034 /****************************************************************************
6035 ****************************************************************************/
6036 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6037 {
6038         int i=0;
6039         BOOL found=False;
6040         JOB_INFO_1 *info_1=NULL;
6041
6042         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6043
6044         if (info_1 == NULL) {
6045                 safe_free(queue);
6046                 return ERROR_NOT_ENOUGH_MEMORY;
6047         }
6048                 
6049         for (i=0; i<count && found==False; i++) {
6050                 if (queue[i].job==(int)jobid)
6051                         found=True;
6052         }
6053         
6054         if (found==False) {
6055                 safe_free(queue);
6056                 safe_free(info_1);
6057                 /* I shoud reply something else ... I can't find the good one */
6058                 return NT_STATUS_NO_PROBLEMO;
6059         }
6060         
6061         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6062         
6063         safe_free(queue);
6064         
6065         *needed += spoolss_size_job_info_1(info_1);
6066
6067         if (!alloc_buffer_size(buffer, *needed)) {
6068                 safe_free(info_1);
6069                 return ERROR_INSUFFICIENT_BUFFER;
6070         }
6071
6072         new_smb_io_job_info_1("", buffer, info_1, 0);
6073
6074         safe_free(info_1);
6075
6076         if (*needed > offered)
6077                 return ERROR_INSUFFICIENT_BUFFER;
6078         else
6079                 return NT_STATUS_NO_PROBLEMO;
6080 }
6081
6082
6083 /****************************************************************************
6084 ****************************************************************************/
6085 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6086 {
6087         int i=0;
6088         BOOL found=False;
6089         JOB_INFO_2 *info_2;
6090         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6091
6092         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6093
6094         ZERO_STRUCTP(info_2);
6095
6096         if (info_2 == NULL) {
6097                 safe_free(queue);
6098                 return ERROR_NOT_ENOUGH_MEMORY;
6099         }
6100
6101         for (i=0; i<count && found==False; i++) {
6102                 if (queue[i].job==(int)jobid)
6103                         found=True;
6104         }
6105         
6106         if (found==False) {
6107                 safe_free(queue);
6108                 safe_free(info_2);
6109                 /* I shoud reply something else ... I can't find the good one */
6110                 return NT_STATUS_NO_PROBLEMO;
6111         }
6112         
6113         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6114                 safe_free(queue);
6115                 return ERROR_NOT_ENOUGH_MEMORY;
6116         }
6117
6118         fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6119         
6120         free_a_printer(&ntprinter, 2);
6121         safe_free(queue);
6122         
6123         *needed += spoolss_size_job_info_2(info_2);
6124
6125         if (!alloc_buffer_size(buffer, *needed)) {
6126                 safe_free(info_2);
6127                 return ERROR_INSUFFICIENT_BUFFER;
6128         }
6129
6130         new_smb_io_job_info_2("", buffer, info_2, 0);
6131
6132         free_job_info_2(info_2);
6133         free(info_2);
6134
6135         if (*needed > offered)
6136                 return ERROR_INSUFFICIENT_BUFFER;
6137         else
6138                 return NT_STATUS_NO_PROBLEMO;
6139 }
6140
6141 /****************************************************************************
6142 ****************************************************************************/
6143 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6144                         NEW_BUFFER *buffer, uint32 offered,
6145                         uint32 *needed)
6146 {
6147         int snum;
6148         int count;
6149         print_queue_struct *queue=NULL;
6150         print_status_struct prt_status;
6151
6152         DEBUG(5,("spoolss_getjob\n"));
6153         
6154         memset(&prt_status, 0, sizeof(prt_status));
6155
6156         *needed=0;
6157         
6158         if (!get_printer_snum(handle, &snum))
6159                 return ERROR_INVALID_HANDLE;
6160         
6161         count = print_queue_status(snum, &queue, &prt_status);
6162         
6163         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6164                      count, prt_status.status, prt_status.message));
6165                 
6166         switch (level) {
6167         case 1:
6168                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6169         case 2:
6170                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6171         default:
6172                 safe_free(queue);
6173                 return ERROR_INVALID_LEVEL;
6174         }
6175 }
6176 #undef OLD_NTDOMAIN