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