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