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