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