This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison                    2001,
8  *  Copyright (C) Gerald Carter                2000-2001,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30
31 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
33 #endif
34
35 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
36 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
37 #define PRINTER_HANDLE_IS_PRINTER       0
38 #define PRINTER_HANDLE_IS_PRINTSERVER   1
39
40 struct table_node {
41         char    *long_archi;
42         char    *short_archi;
43         int     version;
44 };
45
46
47 /* structure to store the printer handles */
48 /* and a reference to what it's pointing to */
49 /* and the notify info asked about */
50 /* that's the central struct */
51 typedef struct _Printer{
52         struct _Printer *prev, *next;
53         BOOL document_started;
54         BOOL page_started;
55         int jobid; /* jobid in printing backend */
56         BOOL printer_type;
57         union {
58                 fstring handlename;
59                 fstring printerservername;
60         } dev;
61         uint32 type;
62         uint32 access_granted;
63         struct {
64                 uint32 flags;
65                 uint32 options;
66                 fstring localmachine;
67                 uint32 printerlocal;
68                 SPOOL_NOTIFY_OPTION *option;
69                 POLICY_HND client_hnd;
70                 uint32 client_connected;
71         } notify;
72         struct {
73                 fstring machine;
74                 fstring user;
75         } client;
76 } Printer_entry;
77
78 static Printer_entry *printers_list;
79
80 typedef struct _counter_printer_0 {
81         ubi_dlNode Next;
82         ubi_dlNode Prev;
83         
84         int snum;
85         uint32 counter;
86 } counter_printer_0;
87
88 static ubi_dlList counter_list;
89
90 static struct cli_state cli;
91 static uint32 smb_connections=0;
92
93
94 /* in printing/nt_printing.c */
95
96 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
97
98 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
99 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
100
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v)
103 {
104         switch (v) {
105         case LPQ_QUEUED:
106                 return 0;
107         case LPQ_PAUSED:
108                 return JOB_STATUS_PAUSED;
109         case LPQ_SPOOLING:
110                 return JOB_STATUS_SPOOLING;
111         case LPQ_PRINTING:
112                 return JOB_STATUS_PRINTING;
113         case LPQ_ERROR:
114                 return JOB_STATUS_ERROR;
115         case LPQ_DELETING:
116                 return JOB_STATUS_DELETING;
117         case LPQ_OFFLINE:
118                 return JOB_STATUS_OFFLINE;
119         case LPQ_PAPEROUT:
120                 return JOB_STATUS_PAPEROUT;
121         case LPQ_PRINTED:
122                 return JOB_STATUS_PRINTED;
123         case LPQ_DELETED:
124                 return JOB_STATUS_DELETED;
125         case LPQ_BLOCKED:
126                 return JOB_STATUS_BLOCKED;
127         case LPQ_USER_INTERVENTION:
128                 return JOB_STATUS_USER_INTERVENTION;
129         }
130         return 0;
131 }
132
133 static int nt_printq_status(int v)
134 {
135         switch (v) {
136         case LPQ_PAUSED:
137                 return PRINTER_STATUS_PAUSED;
138         case LPQ_QUEUED:
139         case LPQ_SPOOLING:
140         case LPQ_PRINTING:
141                 return 0;
142         }
143         return 0;
144 }
145
146 /****************************************************************************
147  Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
148 ****************************************************************************/
149
150 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
151 {
152         if (*pp == NULL)
153                 return;
154
155         SAFE_FREE((*pp)->ctr.type);
156         SAFE_FREE(*pp);
157 }
158
159 /***************************************************************************
160  Disconnect from the client
161 ****************************************************************************/
162
163 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
164 {
165         WERROR result;
166
167         /* weird if the test succeds !!! */
168         if (smb_connections==0) {
169                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
170                 return;
171         }
172
173         result = cli_spoolss_reply_close_printer(&cli, cli.mem_ctx, handle);
174         
175         if (!W_ERROR_IS_OK(result))
176                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
177                         dos_errstr(result)));
178
179         /* if it's the last connection, deconnect the IPC$ share */
180         if (smb_connections==1) {
181                 if(!spoolss_disconnect_from_client(&cli))
182                         return;
183
184                 message_deregister(MSG_PRINTER_NOTIFY);
185         }
186
187         smb_connections--;
188 }
189
190 /****************************************************************************
191  Functions to free a printer entry datastruct.
192 ****************************************************************************/
193
194 static void free_printer_entry(void *ptr)
195 {
196         Printer_entry *Printer = (Printer_entry *)ptr;
197
198         if (Printer->notify.client_connected==True)
199                 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
200
201         Printer->notify.flags=0;
202         Printer->notify.options=0;
203         Printer->notify.localmachine[0]='\0';
204         Printer->notify.printerlocal=0;
205         free_spool_notify_option(&Printer->notify.option);
206         Printer->notify.option=NULL;
207         Printer->notify.client_connected=False;
208
209         /* Remove from the internal list. */
210         DLIST_REMOVE(printers_list, Printer);
211
212         SAFE_FREE(Printer);
213 }
214
215 /****************************************************************************
216  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
217 ****************************************************************************/
218
219 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
220 {
221         SPOOL_NOTIFY_OPTION *new_sp = NULL;
222
223         if (!sp)
224                 return NULL;
225
226         new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
227         if (!new_sp)
228                 return NULL;
229
230         *new_sp = *sp;
231
232         if (sp->ctr.count) {
233                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
234
235                 if (!new_sp->ctr.type) {
236                         SAFE_FREE(new_sp);
237                         return NULL;
238                 }
239         }
240
241         return new_sp;
242 }
243
244 /****************************************************************************
245   find printer index by handle
246 ****************************************************************************/
247
248 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
249 {
250         Printer_entry *find_printer = NULL;
251
252         if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
253                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
254                 return NULL;
255         }
256
257         return find_printer;
258 }
259
260 /****************************************************************************
261  Close printer index by handle.
262 ****************************************************************************/
263
264 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
265 {
266         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
267
268         if (!Printer) {
269                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
270                 return False;
271         }
272
273         close_policy_hnd(p, hnd);
274
275         return True;
276 }       
277
278 /****************************************************************************
279  Delete a printer given a handle.
280 ****************************************************************************/
281
282 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
283 {
284         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
285
286         if (!Printer) {
287                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
288                 return WERR_BADFID;
289         }
290
291         if (del_a_printer(Printer->dev.handlename) != 0) {
292                 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
293                 return WERR_BADFID;
294         }
295
296         /* Check calling user has permission to delete printer.  Note that
297            since we set the snum parameter to -1 only administrators can
298            delete the printer.  This stops people with the Full Control
299            permission from deleting the printer. */
300
301         if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
302                 DEBUG(3, ("printer delete denied by security descriptor\n"));
303                 return WERR_ACCESS_DENIED;
304         }
305
306         if (*lp_deleteprinter_cmd()) {
307
308                 char *cmd = lp_deleteprinter_cmd();
309                 pstring command;
310                 int ret;
311                 int i;
312
313                 /* Printer->dev.handlename equals portname equals sharename */
314                 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
315                                         Printer->dev.handlename);
316
317                 DEBUG(10,("Running [%s]\n", command));
318                 ret = smbrun(command, NULL);
319                 if (ret != 0) {
320                         return WERR_BADFID; /* What to return here? */
321                 }
322                 DEBUGADD(10,("returned [%d]\n", ret));
323
324                 /* Send SIGHUP to process group... is there a better way? */
325                 kill(0, SIGHUP);
326
327                 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
328                         lp_killservice( i );
329                         return WERR_OK;
330                 } else
331                         return WERR_ACCESS_DENIED;
332         }
333
334         return WERR_OK;
335 }
336
337 /****************************************************************************
338  Return the snum of a printer corresponding to an handle.
339 ****************************************************************************/
340
341 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
342 {
343         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
344                 
345         if (!Printer) {
346                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
347                 return False;
348         }
349         
350         switch (Printer->printer_type) {
351         case PRINTER_HANDLE_IS_PRINTER:         
352                 DEBUG(4,("short name:%s\n", Printer->dev.handlename));                  
353                 *number = print_queue_snum(Printer->dev.handlename);
354                 return (*number != -1);
355         case PRINTER_HANDLE_IS_PRINTSERVER:
356                 return False;
357         default:
358                 return False;
359         }
360 }
361
362 /****************************************************************************
363  Set printer handle type.
364  Check if it's \\server or \\server\printer
365 ****************************************************************************/
366
367 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
368 {
369         DEBUG(3,("Setting printer type=%s\n", handlename));
370
371         if ( strlen(handlename) < 3 ) {
372                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
373                 return False;
374         }
375
376         /* it's a print server */
377         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
378                 DEBUGADD(4,("Printer is a print server\n"));
379                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;          
380         }
381         /* it's a printer */
382         else {
383                 DEBUGADD(4,("Printer is a printer\n"));
384                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
385         }
386
387         return True;
388 }
389
390 /****************************************************************************
391  Set printer handle name.
392 ****************************************************************************/
393
394 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
395 {
396         int snum;
397         int n_services=lp_numservices();
398         char *aprinter;
399         fstring sname;
400         BOOL found=False;
401         
402         DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
403
404         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
405                 ZERO_STRUCT(Printer->dev.printerservername);
406                 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
407                 return True;
408         }
409
410         if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
411                 return False;
412         
413         if (*handlename=='\\') {
414                 aprinter=strchr_m(handlename+2, '\\');
415                 aprinter++;
416         }
417         else {
418                 aprinter=handlename;
419         }
420
421         DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
422
423         /*
424          * The original code allowed smbd to store a printer name that
425          * was different from the share name.  This is not possible 
426          * anymore, so I've simplified this loop greatly.  Here
427          * we are just verifying that the printer name is a valid
428          * printer service defined in smb.conf
429          *                          --jerry [Fri Feb 15 11:17:46 CST 2002] 
430          */
431
432         for (snum=0; snum<n_services; snum++) {
433
434                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
435                         continue;
436                 
437                 fstrcpy(sname, lp_servicename(snum));
438
439                 DEBUGADD(5,("share:%s\n",sname));
440                 
441                 if (! StrCaseCmp(sname, aprinter)) {
442                         found = True;
443                         break;
444                 }
445
446         }
447
448                 
449         if (!found) {
450                 DEBUGADD(4,("Printer not found\n"));
451                 return False;
452         }
453         
454         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
455
456         ZERO_STRUCT(Printer->dev.handlename);
457         fstrcpy(Printer->dev.handlename, sname);
458
459         return True;
460 }
461
462 /****************************************************************************
463  Find first available printer slot. creates a printer handle for you.
464  ****************************************************************************/
465
466 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
467 {
468         Printer_entry *new_printer;
469
470         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
471
472         if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
473                 return False;
474
475         ZERO_STRUCTP(new_printer);
476         
477         new_printer->notify.option=NULL;
478                                 
479         /* Add to the internal list. */
480         DLIST_ADD(printers_list, new_printer);
481
482         if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
483                 SAFE_FREE(new_printer);
484                 return False;
485         }
486
487         if (!set_printer_hnd_printertype(new_printer, name)) {
488                 close_printer_handle(p, hnd);
489                 return False;
490         }
491         
492         if (!set_printer_hnd_name(new_printer, name)) {
493                 close_printer_handle(p, hnd);
494                 return False;
495         }
496
497         new_printer->access_granted = access_granted;
498
499         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
500
501         return True;
502 }
503
504 /****************************************************************************
505  Allocate more memory for a BUFFER.
506 ****************************************************************************/
507
508 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
509 {
510         prs_struct *ps;
511         uint32 extra_space;
512         uint32 old_offset;
513         
514         ps= &buffer->prs;
515
516         /* damn, I'm doing the reverse operation of prs_grow() :) */
517         if (buffer_size < prs_data_size(ps))
518                 extra_space=0;
519         else    
520                 extra_space = buffer_size - prs_data_size(ps);
521
522         /*
523          * save the offset and move to the end of the buffer
524          * prs_grow() checks the extra_space against the offset
525          */
526         old_offset=prs_offset(ps);      
527         prs_set_offset(ps, prs_data_size(ps));
528         
529         if (!prs_grow(ps, extra_space))
530                 return False;
531
532         prs_set_offset(ps, old_offset);
533
534         buffer->string_at_end=prs_data_size(ps);
535
536         return True;
537 }
538 /***************************************************************************
539  Always give preference Printer_entry.notify.option over 
540  Printer_entry.notify.flags.  Return True if we should send notification 
541  events using SPOOLSS_RRPCN.  False means that we should use 
542  SPOOLSS_ROUTERREPLYPRINTER.
543  **************************************************************************/
544 static BOOL valid_notify_options(Printer_entry *printer)
545 {
546         if (printer->notify.option == NULL)
547                 return False;
548                 
549         return True;
550 }
551
552 /***************************************************************************
553  Simple check to see if the client motify handle is set to watch for events
554  represented by 'flags'
555  
556  FIXME!!!! only a stub right now     --jerry
557  **************************************************************************/
558  
559 static BOOL is_client_monitoring_event(Printer_entry *p, uint32 flags)
560 {
561
562         return True;
563 }
564
565 /***************************************************************************
566  Server wrapper for cli_spoolss_routerreplyprinter() since the client 
567  function can only send a single change notification at a time.
568  
569  FIXME!!!  only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
570  --jerry
571  **************************************************************************/
572  
573 static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
574                                         POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
575                                         NT_PRINTER_INFO_LEVEL *printer)                         
576 {
577         WERROR result;
578         uint32 condition = 0x0;
579         
580         if (info->flags & PRINTER_MESSAGE_DRIVER)
581                 condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
582         
583         result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition, 
584                         printer->info_2->changeid);
585
586         return result;
587 }
588
589 /***********************************************************************
590  Wrapper around the decision of which RPC use to in the change 
591  notification
592  **********************************************************************/
593  
594 static WERROR srv_spoolss_send_event_to_client(Printer_entry* Printer, 
595         struct cli_state *send_cli,     PRINTER_MESSAGE_INFO *msg, 
596         NT_PRINTER_INFO_LEVEL *info)
597 {
598         WERROR result;
599         
600         if (valid_notify_options(Printer)) {
601                 /* This is a single call that can send information about multiple changes */
602                 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
603                         msg->flags |= PRINTER_MESSAGE_ATTRIBUTES;
604
605                 result = cli_spoolss_reply_rrpcn(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd, 
606                                 msg, info);
607         }
608         else {
609                 /* This requires that the server send an individual event notification for each change */
610                 result = srv_spoolss_routerreplyprinter(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd, 
611                                 msg, info);
612         }
613         
614         return result;
615 }
616
617
618 /***********************************************************************
619  Send a change notication message on all handles which have a call 
620  back registered
621  **********************************************************************/
622
623 static void send_spoolss_event_notification(PRINTER_MESSAGE_INFO *msg)
624 {
625         Printer_entry *find_printer;
626         WERROR result;
627         NT_PRINTER_INFO_LEVEL *printer = NULL;
628
629         if (!msg) {
630                 DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n"));
631                 return;
632         }
633
634         for(find_printer = printers_list; find_printer; find_printer = find_printer->next) {
635
636                 /*
637                  * If the entry has a connected client we send the message. There should 
638                  * only be one of these normally when dealing with the NT/2k spooler.
639                  * However, iterate over all to make sure we deal with user applications
640                  * in addition to spooler service.
641                  *
642                  * While we are only maintaining a single connection to the client, 
643                  * the FindFirstPrinterChangeNotification() call is made on a printer 
644                  * handle, so "client_connected" represents the whether or not the 
645                  * client asked for change notication on this handle.
646                  * 
647                  * --jerry
648                  */
649
650                 if (find_printer->notify.client_connected==True) {
651                 
652                         /* does the client care about what changed? */
653
654                         if (msg->flags && !is_client_monitoring_event(find_printer, msg->flags)) {
655                                 DEBUG(10,("send_spoolss_event_notification: Client [%s] not monitoring these events\n",
656                                         find_printer->client.machine)); 
657                                 continue;
658                         }
659
660                         if (find_printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
661                                 DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer->dev.printerservername ));
662                         else
663                                 DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer->dev.handlename));
664
665                         /*
666                          * if handle is a printer, only send if the printer_name matches.
667                          * ...else if handle is a printerserver, send to all
668                          */
669
670                         if (*msg->printer_name && (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER) 
671                                 && !strequal(msg->printer_name, find_printer->dev.handlename)) 
672                         {
673                                 DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n",
674                                         msg->printer_name, find_printer->dev.handlename ));
675                                 continue;
676                         }
677
678
679                         /* lookup the printer if we have a name if we don't already have a 
680                            valid NT_PRINTER_INFO_LEVEL structure. And yes I'm assuming we 
681                            will always have a non-empty msg.printer_name */
682                                    
683                         if (!printer || !printer->info_2 || strcmp(msg->printer_name, printer->info_2->printername)) 
684                         {
685                         
686                                 if (printer) {
687                                         free_a_printer(&printer, 2);
688                                         printer = NULL;
689                                 }
690                                         
691                                 result = get_a_printer(&printer, 2, msg->printer_name);
692                                 if (!W_ERROR_IS_OK(result))
693                                         continue;
694                         }
695
696                         /* issue the client call */
697
698                         result = srv_spoolss_send_event_to_client(find_printer, &cli, msg, printer);
699                         
700                         if (!W_ERROR_IS_OK(result)) {
701                                 DEBUG(5,("send_spoolss_event_notification: Event notification failed [%s]\n",
702                                         dos_errstr(result)));
703                 }
704         }
705 }
706
707         return;
708 }
709 /***************************************************************************
710  Receive the notify message and decode the message.  Do not send 
711  notification if we sent this originally as that would result in 
712  duplicates.
713 ****************************************************************************/
714
715 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
716 {
717         PRINTER_MESSAGE_INFO msg;
718         
719         if (len < sizeof(msg)) {
720                 DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len));
721                 return;
722         }
723
724         memcpy(&msg, buf, sizeof(PRINTER_MESSAGE_INFO));
725         
726         DEBUG(10,("srv_spoolss_receive_message: Got message printer change [queue = %s] low=0x%x  high=0x%x flags=0x%x\n",
727                 msg.printer_name, (unsigned int)msg.low, (unsigned int)msg.high, msg.flags ));
728
729         /* Iterate the printer list */
730         
731         send_spoolss_event_notification(&msg);
732         
733 }
734
735 /***************************************************************************
736  Send a notify event.
737 ****************************************************************************/
738
739 static BOOL srv_spoolss_sendnotify(char* printer_name, uint32 high, uint32 low, uint32 flags)
740 {
741         char msg[sizeof(PRINTER_MESSAGE_INFO)];
742         PRINTER_MESSAGE_INFO info;
743         
744         ZERO_STRUCT(info);
745
746         info.low        = low;
747         info.high       = high;
748         info.flags      = flags;
749         fstrcpy(info.printer_name, printer_name);
750         
751         memcpy(msg, &info, sizeof(PRINTER_MESSAGE_INFO));       
752
753         DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x  high=0x%x [%s], flags=0x%x\n", 
754                 low, high, printer_name, flags));
755                 
756         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(PRINTER_MESSAGE_INFO), 
757                 False, NULL);
758
759         return True;
760 }       
761
762 /********************************************************************
763  Copy routines used by convert_to_openprinterex()
764  *******************************************************************/
765
766 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
767 {
768         DEVICEMODE *d;
769         int len;
770
771         if (!devmode)
772                 return NULL;
773                 
774         DEBUG (8,("dup_devmode\n"));
775         
776         /* bulk copy first */
777         
778         d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
779         if (!d)
780                 return NULL;
781                 
782         /* dup the pointer members separately */
783         
784         len = unistrlen(devmode->devicename.buffer);
785         if (len != -1) {
786                 d->devicename.buffer = talloc(ctx, len*2);
787                 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
788                         return NULL;
789         }
790                 
791
792         len = unistrlen(devmode->formname.buffer);
793         if (len != -1) {
794                 d->devicename.buffer = talloc(ctx, len*2);
795                 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
796                         return NULL;
797         }
798
799         d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
800         
801         return d;
802 }
803
804 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
805 {
806         if (!new_ctr || !ctr)
807                 return;
808                 
809         DEBUG(8,("copy_devmode_ctr\n"));
810         
811         new_ctr->size = ctr->size;
812         new_ctr->devmode_ptr = ctr->devmode_ptr;
813         
814         if(ctr->devmode_ptr)
815                 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
816 }
817
818 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
819 {
820         if (!new_def || !def)
821                 return;
822         
823         DEBUG(8,("copy_printer_defaults\n"));
824         
825         new_def->datatype_ptr = def->datatype_ptr;
826         
827         if (def->datatype_ptr)
828                 copy_unistr2(&new_def->datatype, &def->datatype);
829         
830         copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
831         
832         new_def->access_required = def->access_required;
833 }
834
835 /********************************************************************
836  * Convert a SPOOL_Q_OPEN_PRINTER structure to a 
837  * SPOOL_Q_OPEN_PRINTER_EX structure
838  ********************************************************************/
839
840 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
841 {
842         if (!q_u_ex || !q_u)
843                 return;
844
845         DEBUG(8,("convert_to_openprinterex\n"));
846                                 
847         q_u_ex->printername_ptr = q_u->printername_ptr;
848         
849         if (q_u->printername_ptr)
850                 copy_unistr2(&q_u_ex->printername, &q_u->printername);
851         
852         copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
853 }
854
855 /********************************************************************
856  * spoolss_open_printer
857  *
858  * called from the spoolss dispatcher
859  ********************************************************************/
860
861 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
862 {
863         SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
864         SPOOL_R_OPEN_PRINTER_EX r_u_ex;
865         
866         if (!q_u || !r_u)
867                 return WERR_NOMEM;
868         
869         ZERO_STRUCT(q_u_ex);
870         ZERO_STRUCT(r_u_ex);
871         
872         /* convert the OpenPrinter() call to OpenPrinterEx() */
873         
874         convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
875         
876         r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
877         
878         /* convert back to OpenPrinter() */
879         
880         memcpy(r_u, &r_u_ex, sizeof(*r_u));
881         
882         return r_u->status;
883 }
884
885 /********************************************************************
886  * spoolss_open_printer
887  *
888  * called from the spoolss dispatcher
889  ********************************************************************/
890
891 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
892 {
893         UNISTR2 *printername = NULL;
894         PRINTER_DEFAULT *printer_default = &q_u->printer_default;
895 /*      uint32 user_switch = q_u->user_switch; - notused */
896 /*      SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
897         POLICY_HND *handle = &r_u->handle;
898
899         fstring name;
900         int snum;
901         struct current_user user;
902         Printer_entry *Printer=NULL;
903
904         if (q_u->printername_ptr != 0)
905                 printername = &q_u->printername;
906
907         if (printername == NULL)
908                 return WERR_INVALID_PRINTER_NAME;
909
910         /* some sanity check because you can open a printer or a print server */
911         /* aka: \\server\printer or \\server */
912         unistr2_to_ascii(name, printername, sizeof(name)-1);
913
914         DEBUGADD(3,("checking name: %s\n",name));
915
916         if (!open_printer_hnd(p, handle, name, 0))
917                 return WERR_INVALID_PRINTER_NAME;
918         
919         Printer=find_printer_index_by_hnd(p, handle);
920         if (!Printer) {
921                 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
922 Can't find printer handle we created for printer %s\n", name ));
923                 close_printer_handle(p,handle);
924                 return WERR_INVALID_PRINTER_NAME;
925         }
926
927 /*
928         if (printer_default->datatype_ptr != NULL)
929         {
930                 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
931                 set_printer_hnd_datatype(handle, datatype);
932         }
933         else
934                 set_printer_hnd_datatype(handle, "");
935 */
936         
937         /*
938            First case: the user is opening the print server:
939
940            Disallow MS AddPrinterWizard if parameter disables it. A Win2k
941            client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
942
943            Then both Win2k and WinNT clients try an OpenPrinterEx with
944            SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
945            or if the user is listed in the smb.conf printer admin parameter.
946
947            Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
948            client view printer folder, but does not show the MSAPW.
949
950            Note: this test needs code to check access rights here too. Jeremy
951            could you look at this?
952            
953            
954            Second case: the user is opening a printer:
955            NT doesn't let us connect to a printer if the connecting user
956            doesn't have print permission.
957
958         */
959
960         get_current_user(&user, p);
961
962         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
963
964                 /* Printserver handles use global struct... */
965
966                 snum = -1;
967
968                 /* Map standard access rights to object specific access
969                    rights */
970                 
971                 se_map_standard(&printer_default->access_required, 
972                                 &printserver_std_mapping);
973         
974                 /* Deny any object specific bits that don't apply to print
975                    servers (i.e printer and job specific bits) */
976
977                 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
978
979                 if (printer_default->access_required &
980                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
981                         DEBUG(3, ("access DENIED for non-printserver bits"));
982                         close_printer_handle(p, handle);
983                         return WERR_ACCESS_DENIED;
984                 }
985
986                 /* Allow admin access */
987
988                 if (printer_default->access_required & 
989                     SERVER_ACCESS_ADMINISTER) {
990
991                         if (!lp_ms_add_printer_wizard()) {
992                                 close_printer_handle(p, handle);
993                                 return WERR_ACCESS_DENIED;
994                         }
995
996                         if (user.uid == 0 || 
997                             user_in_list(uidtoname(user.uid),
998                                          lp_printer_admin(snum)))
999                                 return WERR_OK;
1000
1001                         close_printer_handle(p, handle);
1002                         return WERR_ACCESS_DENIED;
1003                 }
1004
1005                 /* We fall through to return WERR_OK */
1006                 
1007         }
1008         else
1009         {
1010                 /* NT doesn't let us connect to a printer if the connecting user
1011                    doesn't have print permission.  */
1012
1013                 if (!get_printer_snum(p, handle, &snum))
1014                         return WERR_BADFID;
1015
1016                 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1017                 
1018                 /* map an empty access mask to the minimum access mask */
1019                 if (printer_default->access_required == 0x0)
1020                         printer_default->access_required = PRINTER_ACCESS_USE;
1021
1022                 /*
1023                  * If we are not serving the printer driver for this printer,
1024                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1025                  * will keep NT clients happy  --jerry  
1026                  */
1027                  
1028                 if (lp_use_client_driver(snum) 
1029                         && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1030                 {
1031                         printer_default->access_required = PRINTER_ACCESS_USE;
1032                 }
1033
1034                 if (!print_access_check(&user, snum, printer_default->access_required)) {
1035                         DEBUG(3, ("access DENIED for printer open\n"));
1036                         close_printer_handle(p, handle);
1037                         return WERR_ACCESS_DENIED;
1038                 }
1039
1040                 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1041                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1042                         close_printer_handle(p, handle);
1043                         return WERR_ACCESS_DENIED;
1044                 }
1045
1046                 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1047                         printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1048                 else
1049                         printer_default->access_required = PRINTER_ACCESS_USE;
1050
1051                 DEBUG(4,("Setting printer access=%x\n", printer_default->access_required));
1052                 Printer->access_granted = printer_default->access_required;
1053
1054                 /*
1055                  * If we have a default device pointer in the
1056                  * printer_default struct, then we need to get
1057                  * the printer info from the tdb and if there is
1058                  * no default devicemode there then we do a *SET*
1059                  * here ! This is insanity.... JRA.
1060                  */
1061
1062                 /*
1063                  * If the openprinterex rpc call contains a devmode,
1064                  * it's a per-user one. This per-user devmode is derivated
1065                  * from the global devmode. Openprinterex() contains a per-user 
1066                  * devmode for when you do EMF printing and spooling.
1067                  * In the EMF case, the NT workstation is only doing half the job
1068                  * of rendering the page. The other half is done by running the printer
1069                  * driver on the server.
1070                  * The EMF file doesn't contain the page description (paper size, orientation, ...).
1071                  * The EMF file only contains what is to be printed on the page.
1072                  * So in order for the server to know how to print, the NT client sends
1073                  * a devicemode attached to the openprinterex call.
1074                  * But this devicemode is short lived, it's only valid for the current print job.
1075                  *
1076                  * If Samba would have supported EMF spooling, this devicemode would
1077                  * have been attached to the handle, to sent it to the driver to correctly
1078                  * rasterize the EMF file.
1079                  *
1080                  * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1081                  * we just act as a pass-thru between windows and the printer.
1082                  *
1083                  * In order to know that Samba supports only RAW spooling, NT has to call
1084                  * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1085                  * and until NT sends a RAW job, we refuse it.
1086                  *
1087                  * But to call getprinter() or startdoc(), you first need a valid handle,
1088                  * and to get an handle you have to call openprintex(). Hence why you have
1089                  * a devicemode in the openprinterex() call.
1090                  *
1091                  *
1092                  * Differences between NT4 and NT 2000.
1093                  * NT4:
1094                  * ---
1095                  * On NT4, you only have a global devicemode. This global devicemode can be changed
1096                  * by the administrator (or by a user with enough privs). Everytime a user
1097                  * wants to print, the devicemode is resetted to the default. In Word, everytime
1098                  * you print, the printer's characteristics are always reset to the global devicemode.
1099                  *
1100                  * NT 2000:
1101                  * -------
1102                  * In W2K, there is the notion of per-user devicemode. The first time you use
1103                  * a printer, a per-user devicemode is build from the global devicemode.
1104                  * If you change your per-user devicemode, it is saved in the registry, under the
1105                  * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1106                  * printer preferences available.
1107                  *
1108                  * To change the per-user devicemode: it's the "Printing Preferences ..." button
1109                  * on the General Tab of the printer properties windows.
1110                  *
1111                  * To change the global devicemode: it's the "Printing Defaults..." button
1112                  * on the Advanced Tab of the printer properties window.
1113                  *
1114                  * JFM.
1115                  */
1116
1117
1118
1119 #if 0
1120                 if (printer_default->devmode_cont.devmode != NULL) {
1121                         result = printer_write_default_dev( snum, printer_default);
1122                         if (result != 0) {
1123                                 close_printer_handle(p, handle);
1124                                 return result;
1125                         }
1126                 }
1127 #endif
1128         }
1129
1130         return WERR_OK;
1131 }
1132
1133 /****************************************************************************
1134 ****************************************************************************/
1135
1136 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1137                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1138 {
1139         BOOL ret = True;
1140
1141         switch (level) {
1142                 case 2:
1143                         ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1144                         break;
1145                 default:
1146                         break;
1147         }
1148
1149         return ret;
1150 }
1151
1152 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1153                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1154 {
1155         BOOL result = True;
1156
1157         switch (level) {
1158                 case 3:
1159                         printer->info_3=NULL;
1160                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1161                                 result = False;
1162                         break;
1163                 case 6:
1164                         printer->info_6=NULL;
1165                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1166                                 result = False;
1167                         break;
1168                 default:
1169                         break;
1170         }
1171
1172         return result;
1173 }
1174
1175 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1176                                 NT_DEVICEMODE **pp_nt_devmode)
1177 {
1178         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1179
1180         /*
1181          * Ensure nt_devmode is a valid pointer
1182          * as we will be overwriting it.
1183          */
1184                 
1185         if (nt_devmode == NULL) {
1186                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1187                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1188                         return False;
1189         }
1190
1191         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1192         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1193
1194         nt_devmode->specversion=devmode->specversion;
1195         nt_devmode->driverversion=devmode->driverversion;
1196         nt_devmode->size=devmode->size;
1197         nt_devmode->fields=devmode->fields;
1198         nt_devmode->orientation=devmode->orientation;
1199         nt_devmode->papersize=devmode->papersize;
1200         nt_devmode->paperlength=devmode->paperlength;
1201         nt_devmode->paperwidth=devmode->paperwidth;
1202         nt_devmode->scale=devmode->scale;
1203         nt_devmode->copies=devmode->copies;
1204         nt_devmode->defaultsource=devmode->defaultsource;
1205         nt_devmode->printquality=devmode->printquality;
1206         nt_devmode->color=devmode->color;
1207         nt_devmode->duplex=devmode->duplex;
1208         nt_devmode->yresolution=devmode->yresolution;
1209         nt_devmode->ttoption=devmode->ttoption;
1210         nt_devmode->collate=devmode->collate;
1211
1212         nt_devmode->logpixels=devmode->logpixels;
1213         nt_devmode->bitsperpel=devmode->bitsperpel;
1214         nt_devmode->pelswidth=devmode->pelswidth;
1215         nt_devmode->pelsheight=devmode->pelsheight;
1216         nt_devmode->displayflags=devmode->displayflags;
1217         nt_devmode->displayfrequency=devmode->displayfrequency;
1218         nt_devmode->icmmethod=devmode->icmmethod;
1219         nt_devmode->icmintent=devmode->icmintent;
1220         nt_devmode->mediatype=devmode->mediatype;
1221         nt_devmode->dithertype=devmode->dithertype;
1222         nt_devmode->reserved1=devmode->reserved1;
1223         nt_devmode->reserved2=devmode->reserved2;
1224         nt_devmode->panningwidth=devmode->panningwidth;
1225         nt_devmode->panningheight=devmode->panningheight;
1226
1227         /*
1228          * Only change private and driverextra if the incoming devmode
1229          * has a new one. JRA.
1230          */
1231
1232         if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1233                 SAFE_FREE(nt_devmode->private);
1234                 nt_devmode->driverextra=devmode->driverextra;
1235                 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1236                         return False;
1237                 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1238         }
1239
1240         *pp_nt_devmode = nt_devmode;
1241
1242         return True;
1243 }
1244
1245 /********************************************************************
1246  * _spoolss_enddocprinter_internal.
1247  ********************************************************************/
1248
1249 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1250 {
1251         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1252         
1253         if (!Printer) {
1254                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1255                 return WERR_BADFID;
1256         }
1257         
1258         Printer->document_started=False;
1259         print_job_end(Printer->jobid,True);
1260         /* error codes unhandled so far ... */
1261
1262         return WERR_OK;
1263 }
1264
1265 /********************************************************************
1266  * api_spoolss_closeprinter
1267  ********************************************************************/
1268
1269 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1270 {
1271         POLICY_HND *handle = &q_u->handle;
1272
1273         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1274
1275         if (Printer && Printer->document_started)
1276                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1277
1278         if (!close_printer_handle(p, handle))
1279                 return WERR_BADFID;     
1280                 
1281         /* clear the returned printer handle.  Observed behavior 
1282            from Win2k server.  Don't think this really matters.
1283            Previous code just copied the value of the closed
1284            handle.    --jerry */
1285
1286         memset(&r_u->handle, '\0', sizeof(r_u->handle));
1287
1288         return WERR_OK;
1289 }
1290
1291 /********************************************************************
1292  * api_spoolss_deleteprinter
1293
1294  ********************************************************************/
1295
1296 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1297 {
1298         POLICY_HND *handle = &q_u->handle;
1299         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1300         WERROR result;
1301
1302         if (Printer && Printer->document_started)
1303                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1304
1305         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1306
1307         result = delete_printer_handle(p, handle);
1308
1309         update_c_setprinter(False);
1310
1311         if (W_ERROR_IS_OK(result)) {
1312                 srv_spoolss_sendnotify(Printer->dev.handlename, 0, PRINTER_CHANGE_DELETE_PRINTER, 0x0);
1313         }
1314                 
1315         return result;
1316 }
1317
1318 /*******************************************************************
1319  * static function to lookup the version id corresponding to an
1320  * long architecture string
1321  ******************************************************************/
1322
1323 static int get_version_id (char * arch)
1324 {
1325         int i;
1326         struct table_node archi_table[]= {
1327  
1328                 {"Windows 4.0",          "WIN40",       0 },
1329                 {"Windows NT x86",       "W32X86",      2 },
1330                 {"Windows NT R4000",     "W32MIPS",     2 },    
1331                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
1332                 {"Windows NT PowerPC",   "W32PPC",      2 },
1333                 {NULL,                   "",            -1 }
1334         };
1335  
1336         for (i=0; archi_table[i].long_archi != NULL; i++)
1337         {
1338                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1339                         return (archi_table[i].version);
1340         }
1341         
1342         return -1;
1343 }
1344
1345 /********************************************************************
1346  * _spoolss_deleteprinterdriver
1347  *
1348  * We currently delete the driver for the architecture only.
1349  * This can leave the driver for other archtectures.  However,
1350  * since every printer associates a "Windows NT x86" driver name
1351  * and we cannot delete that one while it is in use, **and** since
1352  * it is impossible to assign a driver to a Samba printer without
1353  * having the "Windows NT x86" driver installed,...
1354  * 
1355  * ....we should not get into trouble here.  
1356  *
1357  *                                                      --jerry
1358  ********************************************************************/
1359
1360 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, 
1361                                     SPOOL_R_DELETEPRINTERDRIVER *r_u)
1362 {
1363         fstring                         driver;
1364         fstring                         arch;
1365         NT_PRINTER_DRIVER_INFO_LEVEL    info;
1366         int                             version;
1367          
1368         unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1369         unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
1370         
1371         /* check that we have a valid driver name first */
1372         if ((version=get_version_id(arch)) == -1) {
1373                 /* this is what NT returns */
1374                 return WERR_INVALID_ENVIRONMENT;
1375         }
1376                 
1377         ZERO_STRUCT(info);
1378         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1379                 return WERR_UNKNOWN_PRINTER_DRIVER;
1380         }
1381         
1382
1383         if (printer_driver_in_use(arch, driver))
1384         {
1385                 return WERR_PRINTER_DRIVER_IN_USE;
1386         }
1387
1388         return delete_printer_driver(info.info_3);       
1389 }
1390
1391 /********************************************************************
1392  GetPrinterData on a printer server Handle.
1393 ********************************************************************/
1394
1395 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1396 {               
1397         int i;
1398         
1399         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1400                 
1401         if (!strcmp(value, "W3SvcInstalled")) {
1402                 *type = 0x4;
1403                 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1404                         return False;
1405                 *needed = 0x4;                  
1406                 return True;
1407         }
1408
1409         if (!strcmp(value, "BeepEnabled")) {
1410                 *type = 0x4;
1411                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1412                         return False;
1413                 SIVAL(*data, 0, 0x00);
1414                 *needed = 0x4;                  
1415                 return True;
1416         }
1417
1418         if (!strcmp(value, "EventLog")) {
1419                 *type = 0x4;
1420                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1421                         return False;
1422                 /* formally was 0x1b */
1423                 SIVAL(*data, 0, 0x0);
1424                 *needed = 0x4;                  
1425                 return True;
1426         }
1427
1428         if (!strcmp(value, "NetPopup")) {
1429                 *type = 0x4;
1430                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1431                         return False;
1432                 SIVAL(*data, 0, 0x00);
1433                 *needed = 0x4;
1434                 return True;
1435         }
1436
1437         if (!strcmp(value, "MajorVersion")) {
1438                 *type = 0x4;
1439                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1440                         return False;
1441                 SIVAL(*data, 0, 2);
1442                 *needed = 0x4;
1443                 return True;
1444         }
1445
1446         if (!strcmp(value, "DefaultSpoolDirectory")) {
1447                 fstring string;
1448
1449                 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1450                 *type = 0x1;                    
1451                 *needed = 2*(strlen(string)+1);         
1452                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1453                         return False;
1454                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1455                 
1456                 /* it's done by hand ready to go on the wire */
1457                 for (i=0; i<strlen(string); i++) {
1458                         (*data)[2*i]=string[i];
1459                         (*data)[2*i+1]='\0';
1460                 }                       
1461                 return True;
1462         }
1463
1464         if (!strcmp(value, "Architecture")) {                   
1465                 pstring string="Windows NT x86";
1466                 *type = 0x1;                    
1467                 *needed = 2*(strlen(string)+1); 
1468                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1469                         return False;
1470                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1471                 for (i=0; i<strlen(string); i++) {
1472                         (*data)[2*i]=string[i];
1473                         (*data)[2*i+1]='\0';
1474                 }                       
1475                 return True;
1476         }
1477         
1478         return False;
1479 }
1480
1481 /********************************************************************
1482  GetPrinterData on a printer Handle.
1483 ********************************************************************/
1484
1485 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1486                                 fstring value, uint32 *type,
1487                                 uint8 **data, uint32 *needed, uint32 in_size )
1488 {
1489         NT_PRINTER_INFO_LEVEL *printer = NULL;
1490         int snum=0;
1491         uint8 *idata=NULL;
1492         uint32 len;
1493         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1494         
1495         DEBUG(5,("getprinterdata_printer\n"));
1496
1497         if (!Printer) {
1498                 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1499                 return False;
1500         }
1501
1502         if(!get_printer_snum(p, handle, &snum))
1503                 return False;
1504
1505         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1506                 return False;
1507
1508         if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1509                 free_a_printer(&printer, 2);
1510                 return False;
1511         }
1512
1513         free_a_printer(&printer, 2);
1514
1515         DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1516
1517         if (in_size) {
1518                 if((*data  = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1519                         return False;
1520                 }
1521
1522                 memset(*data, 0, in_size *sizeof(uint8));
1523                 /* copy the min(in_size, len) */
1524                 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1525         } else {
1526                 *data = NULL;
1527         }
1528
1529         *needed = len;
1530         
1531         DEBUG(5,("getprinterdata_printer:copy done\n"));
1532                         
1533         SAFE_FREE(idata);
1534         
1535         return True;
1536 }       
1537
1538 /********************************************************************
1539  * spoolss_getprinterdata
1540  ********************************************************************/
1541
1542 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1543 {
1544         POLICY_HND *handle = &q_u->handle;
1545         UNISTR2 *valuename = &q_u->valuename;
1546         uint32 in_size = q_u->size;
1547         uint32 *type = &r_u->type;
1548         uint32 *out_size = &r_u->size;
1549         uint8 **data = &r_u->data;
1550         uint32 *needed = &r_u->needed;
1551
1552         fstring value;
1553         BOOL found=False;
1554         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1555         
1556         /*
1557          * Reminder: when it's a string, the length is in BYTES
1558          * even if UNICODE is negociated.
1559          *
1560          * JFM, 4/19/1999
1561          */
1562
1563         *out_size=in_size;
1564
1565         /* in case of problem, return some default values */
1566         *needed=0;
1567         *type=0;
1568         
1569         DEBUG(4,("_spoolss_getprinterdata\n"));
1570         
1571         if (!Printer) {
1572                 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1573                         return WERR_NOMEM;
1574                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1575                 return WERR_BADFID;
1576         }
1577         
1578         unistr2_to_ascii(value, valuename, sizeof(value)-1);
1579         
1580         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1581                 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1582         else
1583                 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1584
1585         if (found==False) {
1586                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1587                 /* reply this param doesn't exist */
1588                 if (*out_size) {
1589                         if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1590                                 return WERR_NOMEM;
1591                 } else {
1592                         *data = NULL;
1593                 }
1594
1595                 /* error depends on handle type */
1596
1597                 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1598                         return WERR_INVALID_PARAM;
1599                 else 
1600                         return WERR_BADFILE;
1601         }
1602         
1603         if (*needed > *out_size)
1604                 return WERR_MORE_DATA;
1605         else 
1606                 return WERR_OK;
1607 }
1608
1609 /***************************************************************************
1610  Connect to the client.
1611 ****************************************************************************/
1612
1613 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1614 {
1615         WERROR result;
1616
1617         /*
1618          * If it's the first connection, contact the client
1619          * and connect to the IPC$ share anonumously
1620          */
1621         if (smb_connections==0) {
1622                 fstring unix_printer;
1623
1624                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1625
1626                 if(!spoolss_connect_to_client(&cli, unix_printer))
1627                         return False;
1628                         
1629                 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1630
1631         }
1632
1633         smb_connections++;
1634
1635         result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter, 
1636                         type, handle);
1637
1638         if (!W_ERROR_IS_OK(result))
1639                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1640                         dos_errstr(result)));
1641
1642         return (W_ERROR_IS_OK(result)); 
1643 }
1644
1645 /********************************************************************
1646  * _spoolss_rffpcnex
1647  * ReplyFindFirstPrinterChangeNotifyEx
1648  *
1649  * jfmxxxx: before replying OK: status=0
1650  * should do a rpc call to the workstation asking ReplyOpenPrinter
1651  * have to code it, later.
1652  *
1653  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1654  * called from api_spoolss_rffpcnex
1655  ********************************************************************/
1656
1657 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1658 {
1659         POLICY_HND *handle = &q_u->handle;
1660         uint32 flags = q_u->flags;
1661         uint32 options = q_u->options;
1662         UNISTR2 *localmachine = &q_u->localmachine;
1663         uint32 printerlocal = q_u->printerlocal;
1664         SPOOL_NOTIFY_OPTION *option = q_u->option;
1665
1666         /* store the notify value in the printer struct */
1667
1668         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1669
1670         if (!Printer) {
1671                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1672                 return WERR_BADFID;
1673         }
1674
1675         Printer->notify.flags=flags;
1676         Printer->notify.options=options;
1677         Printer->notify.printerlocal=printerlocal;
1678
1679         if (Printer->notify.option)
1680                 free_spool_notify_option(&Printer->notify.option);
1681
1682         Printer->notify.option=dup_spool_notify_option(option);
1683
1684         unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1685
1686         /* connect to the client machine and send a ReplyOpenPrinter */
1687         if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1688                                         Printer->notify.printerlocal, 1,
1689                                         &Printer->notify.client_hnd))
1690         {
1691                 Printer->notify.client_connected=True;
1692         }
1693
1694         return WERR_OK;
1695 }
1696
1697 /*******************************************************************
1698  * fill a notify_info_data with the servername
1699  ********************************************************************/
1700
1701 void spoolss_notify_server_name(int snum, 
1702                                        SPOOL_NOTIFY_INFO_DATA *data, 
1703                                        print_queue_struct *queue,
1704                                        NT_PRINTER_INFO_LEVEL *printer,
1705                                        TALLOC_CTX *mem_ctx) 
1706 {
1707         pstring temp_name, temp;
1708         uint32 len;
1709
1710         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1711
1712         len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1713
1714         data->notify_data.data.length = len / 2 - 1;
1715         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1716
1717         if (!data->notify_data.data.string) {
1718                 data->notify_data.data.length = 0;
1719                 return;
1720         }
1721         
1722         memcpy(data->notify_data.data.string, temp, len);
1723 }
1724
1725 /*******************************************************************
1726  * fill a notify_info_data with the printername (not including the servername).
1727  ********************************************************************/
1728
1729 void spoolss_notify_printer_name(int snum, 
1730                                         SPOOL_NOTIFY_INFO_DATA *data, 
1731                                         print_queue_struct *queue,
1732                                         NT_PRINTER_INFO_LEVEL *printer,
1733                                         TALLOC_CTX *mem_ctx)
1734 {
1735         pstring temp;
1736         uint32 len;
1737                 
1738         /* the notify name should not contain the \\server\ part */
1739         char *p = strrchr(printer->info_2->printername, '\\');
1740
1741         if (!p) {
1742                 p = printer->info_2->printername;
1743         } else {
1744                 p++;
1745         }
1746
1747         len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1748
1749         data->notify_data.data.length = len / 2 - 1;
1750         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1751         
1752         if (!data->notify_data.data.string) {
1753                 data->notify_data.data.length = 0;
1754                 return;
1755         }
1756         
1757         memcpy(data->notify_data.data.string, temp, len);
1758 }
1759
1760 /*******************************************************************
1761  * fill a notify_info_data with the servicename
1762  ********************************************************************/
1763
1764 void spoolss_notify_share_name(int snum, 
1765                                       SPOOL_NOTIFY_INFO_DATA *data, 
1766                                       print_queue_struct *queue,
1767                                       NT_PRINTER_INFO_LEVEL *printer,
1768                                       TALLOC_CTX *mem_ctx)
1769 {
1770         pstring temp;
1771         uint32 len;
1772
1773         len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1774
1775         data->notify_data.data.length = len / 2 - 1;
1776         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1777         
1778         if (!data->notify_data.data.string) {
1779                 data->notify_data.data.length = 0;
1780                 return;
1781         }
1782         
1783         memcpy(data->notify_data.data.string, temp, len);
1784 }
1785
1786 /*******************************************************************
1787  * fill a notify_info_data with the port name
1788  ********************************************************************/
1789
1790 void spoolss_notify_port_name(int snum, 
1791                                      SPOOL_NOTIFY_INFO_DATA *data, 
1792                                      print_queue_struct *queue,
1793                                      NT_PRINTER_INFO_LEVEL *printer,
1794                                      TALLOC_CTX *mem_ctx)
1795 {
1796         pstring temp;
1797         uint32 len;
1798
1799         /* even if it's strange, that's consistant in all the code */
1800
1801         len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1802
1803         data->notify_data.data.length = len / 2 - 1;
1804         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1805         
1806         if (!data->notify_data.data.string) {
1807                 data->notify_data.data.length = 0;
1808                 return;
1809         }
1810         
1811         memcpy(data->notify_data.data.string, temp, len);
1812 }
1813
1814 /*******************************************************************
1815  * fill a notify_info_data with the printername
1816  * but it doesn't exist, have to see what to do
1817  ********************************************************************/
1818
1819 void spoolss_notify_driver_name(int snum, 
1820                                        SPOOL_NOTIFY_INFO_DATA *data,
1821                                        print_queue_struct *queue,
1822                                        NT_PRINTER_INFO_LEVEL *printer,
1823                                        TALLOC_CTX *mem_ctx)
1824 {
1825         pstring temp;
1826         uint32 len;
1827
1828         len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1829         data->notify_data.data.length = len / 2 - 1;
1830         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1831         
1832         if (!data->notify_data.data.string) {
1833                 data->notify_data.data.length = 0;
1834                 return;
1835         }
1836         
1837         memcpy(data->notify_data.data.string, temp, len);
1838 }
1839
1840 /*******************************************************************
1841  * fill a notify_info_data with the comment
1842  ********************************************************************/
1843
1844 void spoolss_notify_comment(int snum, 
1845                                    SPOOL_NOTIFY_INFO_DATA *data,
1846                                    print_queue_struct *queue,
1847                                    NT_PRINTER_INFO_LEVEL *printer,
1848                                    TALLOC_CTX *mem_ctx)
1849 {
1850         pstring temp;
1851         uint32 len;
1852
1853         if (*printer->info_2->comment == '\0')
1854                 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1855         else
1856                 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1857
1858         data->notify_data.data.length = len / 2 - 1;
1859         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1860         
1861         if (!data->notify_data.data.string) {
1862                 data->notify_data.data.length = 0;
1863                 return;
1864         }
1865         
1866         memcpy(data->notify_data.data.string, temp, len);
1867 }
1868
1869 /*******************************************************************
1870  * fill a notify_info_data with the comment
1871  * location = "Room 1, floor 2, building 3"
1872  ********************************************************************/
1873
1874 void spoolss_notify_location(int snum, 
1875                                     SPOOL_NOTIFY_INFO_DATA *data,
1876                                     print_queue_struct *queue,
1877                                     NT_PRINTER_INFO_LEVEL *printer,
1878                                     TALLOC_CTX *mem_ctx)
1879 {
1880         pstring temp;
1881         uint32 len;
1882
1883         len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1884
1885         data->notify_data.data.length = len / 2 - 1;
1886         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1887         
1888         if (!data->notify_data.data.string) {
1889                 data->notify_data.data.length = 0;
1890                 return;
1891         }
1892         
1893         memcpy(data->notify_data.data.string, temp, len);
1894 }
1895
1896 /*******************************************************************
1897  * fill a notify_info_data with the device mode
1898  * jfm:xxxx don't to it for know but that's a real problem !!!
1899  ********************************************************************/
1900
1901 static void spoolss_notify_devmode(int snum, 
1902                                    SPOOL_NOTIFY_INFO_DATA *data,
1903                                    print_queue_struct *queue,
1904                                    NT_PRINTER_INFO_LEVEL *printer,
1905                                    TALLOC_CTX *mem_ctx)
1906 {
1907 }
1908
1909 /*******************************************************************
1910  * fill a notify_info_data with the separator file name
1911  ********************************************************************/
1912
1913 void spoolss_notify_sepfile(int snum, 
1914                                    SPOOL_NOTIFY_INFO_DATA *data, 
1915                                    print_queue_struct *queue,
1916                                    NT_PRINTER_INFO_LEVEL *printer,
1917                                    TALLOC_CTX *mem_ctx)
1918 {
1919         pstring temp;
1920         uint32 len;
1921
1922         len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1923
1924         data->notify_data.data.length = len / 2 - 1;
1925         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1926         
1927         if (!data->notify_data.data.string) {
1928                 data->notify_data.data.length = 0;
1929                 return;
1930         }
1931         
1932         memcpy(data->notify_data.data.string, temp, len);
1933 }
1934
1935 /*******************************************************************
1936  * fill a notify_info_data with the print processor
1937  * jfm:xxxx return always winprint to indicate we don't do anything to it
1938  ********************************************************************/
1939
1940 void spoolss_notify_print_processor(int snum, 
1941                                            SPOOL_NOTIFY_INFO_DATA *data,
1942                                            print_queue_struct *queue,
1943                                            NT_PRINTER_INFO_LEVEL *printer,
1944                                            TALLOC_CTX *mem_ctx)
1945 {
1946         pstring temp;
1947         uint32 len;
1948
1949         len = rpcstr_push(temp,  printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1950
1951         data->notify_data.data.length = len / 2 - 1;
1952         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1953         
1954         if (!data->notify_data.data.string) {
1955                 data->notify_data.data.length = 0;
1956                 return;
1957         }
1958         
1959         memcpy(data->notify_data.data.string, temp, len);
1960 }
1961
1962 /*******************************************************************
1963  * fill a notify_info_data with the print processor options
1964  * jfm:xxxx send an empty string
1965  ********************************************************************/
1966
1967 void spoolss_notify_parameters(int snum, 
1968                                       SPOOL_NOTIFY_INFO_DATA *data,
1969                                       print_queue_struct *queue,
1970                                       NT_PRINTER_INFO_LEVEL *printer,
1971                                       TALLOC_CTX *mem_ctx)
1972 {
1973         pstring temp;
1974         uint32 len;
1975
1976         len = rpcstr_push(temp,  printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1977
1978         data->notify_data.data.length = len / 2 - 1;
1979         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1980         
1981         if (!data->notify_data.data.string) {
1982                 data->notify_data.data.length = 0;
1983                 return;
1984         }
1985         
1986         memcpy(data->notify_data.data.string, temp, len);
1987 }
1988
1989 /*******************************************************************
1990  * fill a notify_info_data with the data type
1991  * jfm:xxxx always send RAW as data type
1992  ********************************************************************/
1993
1994 void spoolss_notify_datatype(int snum, 
1995                                     SPOOL_NOTIFY_INFO_DATA *data,
1996                                     print_queue_struct *queue,
1997                                     NT_PRINTER_INFO_LEVEL *printer,
1998                                     TALLOC_CTX *mem_ctx)
1999 {
2000         pstring temp;
2001         uint32 len;
2002
2003         len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2004
2005         data->notify_data.data.length = len / 2 - 1;
2006         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2007         
2008         if (!data->notify_data.data.string) {
2009                 data->notify_data.data.length = 0;
2010                 return;
2011         }
2012         
2013         memcpy(data->notify_data.data.string, temp, len);
2014 }
2015
2016 /*******************************************************************
2017  * fill a notify_info_data with the security descriptor
2018  * jfm:xxxx send an null pointer to say no security desc
2019  * have to implement security before !
2020  ********************************************************************/
2021
2022 static void spoolss_notify_security_desc(int snum, 
2023                                          SPOOL_NOTIFY_INFO_DATA *data,
2024                                          print_queue_struct *queue,
2025                                          NT_PRINTER_INFO_LEVEL *printer,
2026                                          TALLOC_CTX *mem_ctx)
2027 {
2028         data->notify_data.data.length=0;
2029         data->notify_data.data.string = NULL;
2030 }
2031
2032 /*******************************************************************
2033  * fill a notify_info_data with the attributes
2034  * jfm:xxxx a samba printer is always shared
2035  ********************************************************************/
2036
2037 void spoolss_notify_attributes(int snum, 
2038                                       SPOOL_NOTIFY_INFO_DATA *data,
2039                                       print_queue_struct *queue,
2040                                       NT_PRINTER_INFO_LEVEL *printer,
2041                                       TALLOC_CTX *mem_ctx)
2042 {
2043         data->notify_data.value[0] = printer->info_2->attributes;
2044         data->notify_data.value[1] = 0;
2045 }
2046
2047 /*******************************************************************
2048  * fill a notify_info_data with the priority
2049  ********************************************************************/
2050
2051 static void spoolss_notify_priority(int snum, 
2052                                     SPOOL_NOTIFY_INFO_DATA *data,
2053                                     print_queue_struct *queue,
2054                                     NT_PRINTER_INFO_LEVEL *printer,
2055                                     TALLOC_CTX *mem_ctx)
2056 {
2057         data->notify_data.value[0] = printer->info_2->priority;
2058         data->notify_data.value[1] = 0;
2059 }
2060
2061 /*******************************************************************
2062  * fill a notify_info_data with the default priority
2063  ********************************************************************/
2064
2065 static void spoolss_notify_default_priority(int snum, 
2066                                             SPOOL_NOTIFY_INFO_DATA *data,
2067                                             print_queue_struct *queue,
2068                                             NT_PRINTER_INFO_LEVEL *printer,
2069                                             TALLOC_CTX *mem_ctx)
2070 {
2071         data->notify_data.value[0] = printer->info_2->default_priority;
2072         data->notify_data.value[1] = 0;
2073 }
2074
2075 /*******************************************************************
2076  * fill a notify_info_data with the start time
2077  ********************************************************************/
2078
2079 static void spoolss_notify_start_time(int snum, 
2080                                       SPOOL_NOTIFY_INFO_DATA *data,
2081                                       print_queue_struct *queue,
2082                                       NT_PRINTER_INFO_LEVEL *printer,
2083                                       TALLOC_CTX *mem_ctx)
2084 {
2085         data->notify_data.value[0] = printer->info_2->starttime;
2086         data->notify_data.value[1] = 0;
2087 }
2088
2089 /*******************************************************************
2090  * fill a notify_info_data with the until time
2091  ********************************************************************/
2092
2093 static void spoolss_notify_until_time(int snum, 
2094                                       SPOOL_NOTIFY_INFO_DATA *data,
2095                                       print_queue_struct *queue,
2096                                       NT_PRINTER_INFO_LEVEL *printer,
2097                                       TALLOC_CTX *mem_ctx)
2098 {
2099         data->notify_data.value[0] = printer->info_2->untiltime;
2100         data->notify_data.value[1] = 0;
2101 }
2102
2103 /*******************************************************************
2104  * fill a notify_info_data with the status
2105  ********************************************************************/
2106
2107 static void spoolss_notify_status(int snum, 
2108                                   SPOOL_NOTIFY_INFO_DATA *data,
2109                                   print_queue_struct *queue,
2110                                   NT_PRINTER_INFO_LEVEL *printer,
2111                                   TALLOC_CTX *mem_ctx)
2112 {
2113         print_status_struct status;
2114
2115         print_queue_length(snum, &status);
2116         data->notify_data.value[0]=(uint32) status.status;
2117         data->notify_data.value[1] = 0;
2118 }
2119
2120 /*******************************************************************
2121  * fill a notify_info_data with the number of jobs queued
2122  ********************************************************************/
2123
2124 void spoolss_notify_cjobs(int snum, 
2125                                  SPOOL_NOTIFY_INFO_DATA *data,
2126                                  print_queue_struct *queue,
2127                                  NT_PRINTER_INFO_LEVEL *printer, 
2128                                  TALLOC_CTX *mem_ctx)
2129 {
2130         data->notify_data.value[0] = print_queue_length(snum, NULL);
2131         data->notify_data.value[1] = 0;
2132 }
2133
2134 /*******************************************************************
2135  * fill a notify_info_data with the average ppm
2136  ********************************************************************/
2137
2138 static void spoolss_notify_average_ppm(int snum, 
2139                                        SPOOL_NOTIFY_INFO_DATA *data,
2140                                        print_queue_struct *queue,
2141                                        NT_PRINTER_INFO_LEVEL *printer,
2142                                        TALLOC_CTX *mem_ctx)
2143 {
2144         /* always respond 8 pages per minutes */
2145         /* a little hard ! */
2146         data->notify_data.value[0] = printer->info_2->averageppm;
2147         data->notify_data.value[1] = 0;
2148 }
2149
2150 /*******************************************************************
2151  * fill a notify_info_data with username
2152  ********************************************************************/
2153
2154 static void spoolss_notify_username(int snum, 
2155                                     SPOOL_NOTIFY_INFO_DATA *data,
2156                                     print_queue_struct *queue,
2157                                     NT_PRINTER_INFO_LEVEL *printer,
2158                                     TALLOC_CTX *mem_ctx)
2159 {
2160         pstring temp;
2161         uint32 len;
2162
2163         len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2164
2165         data->notify_data.data.length = len / 2 - 1;
2166         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2167         
2168         if (!data->notify_data.data.string) {
2169                 data->notify_data.data.length = 0;
2170                 return;
2171         }
2172         
2173         memcpy(data->notify_data.data.string, temp, len);
2174 }
2175
2176 /*******************************************************************
2177  * fill a notify_info_data with job status
2178  ********************************************************************/
2179
2180 static void spoolss_notify_job_status(int snum, 
2181                                       SPOOL_NOTIFY_INFO_DATA *data,
2182                                       print_queue_struct *queue,
2183                                       NT_PRINTER_INFO_LEVEL *printer,
2184                                       TALLOC_CTX *mem_ctx)
2185 {
2186         data->notify_data.value[0]=nt_printj_status(queue->status);
2187         data->notify_data.value[1] = 0;
2188 }
2189
2190 /*******************************************************************
2191  * fill a notify_info_data with job name
2192  ********************************************************************/
2193
2194 static void spoolss_notify_job_name(int snum, 
2195                                     SPOOL_NOTIFY_INFO_DATA *data,
2196                                     print_queue_struct *queue,
2197                                     NT_PRINTER_INFO_LEVEL *printer,
2198                                     TALLOC_CTX *mem_ctx)
2199 {
2200         pstring temp;
2201         uint32 len;
2202
2203         len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2204
2205         data->notify_data.data.length = len / 2 - 1;
2206         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2207         
2208         if (!data->notify_data.data.string) {
2209                 data->notify_data.data.length = 0;
2210                 return;
2211         }
2212         
2213         memcpy(data->notify_data.data.string, temp, len);
2214 }
2215
2216 /*******************************************************************
2217  * fill a notify_info_data with job status
2218  ********************************************************************/
2219
2220 static void spoolss_notify_job_status_string(int snum, 
2221                                              SPOOL_NOTIFY_INFO_DATA *data,
2222                                              print_queue_struct *queue,
2223                                              NT_PRINTER_INFO_LEVEL *printer, 
2224                                              TALLOC_CTX *mem_ctx)
2225 {
2226         /*
2227          * Now we're returning job status codes we just return a "" here. JRA.
2228          */
2229
2230         char *p = "";
2231         pstring temp;
2232         uint32 len;
2233
2234 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2235         p = "unknown";
2236
2237         switch (queue->status) {
2238         case LPQ_QUEUED:
2239                 p = "Queued";
2240                 break;
2241         case LPQ_PAUSED:
2242                 p = "";    /* NT provides the paused string */
2243                 break;
2244         case LPQ_SPOOLING:
2245                 p = "Spooling";
2246                 break;
2247         case LPQ_PRINTING:
2248                 p = "Printing";
2249                 break;
2250         }
2251 #endif /* NO LONGER NEEDED. */
2252
2253         len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2254
2255         data->notify_data.data.length = len / 2 - 1;
2256         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2257         
2258         if (!data->notify_data.data.string) {
2259                 data->notify_data.data.length = 0;
2260                 return;
2261         }
2262         
2263         memcpy(data->notify_data.data.string, temp, len);
2264 }
2265
2266 /*******************************************************************
2267  * fill a notify_info_data with job time
2268  ********************************************************************/
2269
2270 static void spoolss_notify_job_time(int snum, 
2271                                     SPOOL_NOTIFY_INFO_DATA *data,
2272                                     print_queue_struct *queue,
2273                                     NT_PRINTER_INFO_LEVEL *printer,
2274                                     TALLOC_CTX *mem_ctx)
2275 {
2276         data->notify_data.value[0]=0x0;
2277         data->notify_data.value[1]=0;
2278 }
2279
2280 /*******************************************************************
2281  * fill a notify_info_data with job size
2282  ********************************************************************/
2283
2284 static void spoolss_notify_job_size(int snum, 
2285                                     SPOOL_NOTIFY_INFO_DATA *data,
2286                                     print_queue_struct *queue,
2287                                     NT_PRINTER_INFO_LEVEL *printer,
2288                                     TALLOC_CTX *mem_ctx)
2289 {
2290         data->notify_data.value[0]=queue->size;
2291         data->notify_data.value[1]=0;
2292 }
2293
2294 /*******************************************************************
2295  * fill a notify_info_data with page info
2296  ********************************************************************/
2297 static void spoolss_notify_total_pages(int snum,
2298                                 SPOOL_NOTIFY_INFO_DATA *data,
2299                                 print_queue_struct *queue,
2300                                 NT_PRINTER_INFO_LEVEL *printer,
2301                                 TALLOC_CTX *mem_ctx)
2302 {
2303         data->notify_data.value[0]=queue->page_count;
2304         data->notify_data.value[1]=0;
2305 }
2306
2307 /*******************************************************************
2308  * fill a notify_info_data with pages printed info.
2309  ********************************************************************/
2310 static void spoolss_notify_pages_printed(int snum,
2311                                 SPOOL_NOTIFY_INFO_DATA *data,
2312                                 print_queue_struct *queue,
2313                                 NT_PRINTER_INFO_LEVEL *printer,
2314                                 TALLOC_CTX *mem_ctx)
2315 {
2316         data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
2317         data->notify_data.value[1]=0;
2318 }
2319
2320 /*******************************************************************
2321  Fill a notify_info_data with job position.
2322  ********************************************************************/
2323
2324 static void spoolss_notify_job_position(int snum, 
2325                                         SPOOL_NOTIFY_INFO_DATA *data,
2326                                         print_queue_struct *queue,
2327                                         NT_PRINTER_INFO_LEVEL *printer,
2328                                         TALLOC_CTX *mem_ctx)
2329 {
2330         data->notify_data.value[0]=queue->job;
2331         data->notify_data.value[1]=0;
2332 }
2333
2334 /*******************************************************************
2335  Fill a notify_info_data with submitted time.
2336  ********************************************************************/
2337
2338 static void spoolss_notify_submitted_time(int snum, 
2339                                           SPOOL_NOTIFY_INFO_DATA *data,
2340                                           print_queue_struct *queue,
2341                                           NT_PRINTER_INFO_LEVEL *printer,
2342                                           TALLOC_CTX *mem_ctx)
2343 {
2344         struct tm *t;
2345         uint32 len;
2346         SYSTEMTIME st;
2347         char *p;
2348
2349         t=gmtime(&queue->time);
2350
2351         len = sizeof(SYSTEMTIME);
2352
2353         data->notify_data.data.length = len;
2354         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2355
2356         if (!data->notify_data.data.string) {
2357                 data->notify_data.data.length = 0;
2358                 return;
2359         }
2360         
2361         make_systemtime(&st, t);
2362
2363         /*
2364          * Systemtime must be linearized as a set of UINT16's. 
2365          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2366          */
2367
2368         p = (char *)data->notify_data.data.string;
2369         SSVAL(p, 0, st.year);
2370         SSVAL(p, 2, st.month);
2371         SSVAL(p, 4, st.dayofweek);
2372         SSVAL(p, 6, st.day);
2373         SSVAL(p, 8, st.hour);
2374         SSVAL(p, 10, st.minute);
2375         SSVAL(p, 12, st.second);
2376         SSVAL(p, 14, st.milliseconds);
2377 }
2378
2379 #define END 65535
2380
2381 struct s_notify_info_data_table
2382 {
2383         uint16 type;
2384         uint16 field;
2385         char *name;
2386         uint32 size;
2387         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2388                     print_queue_struct *queue,
2389                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2390 };
2391
2392 struct s_notify_info_data_table notify_info_data_table[] =
2393 {
2394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         POINTER,   spoolss_notify_server_name },
2395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        POINTER,   spoolss_notify_printer_name },
2396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          POINTER,   spoolss_notify_share_name },
2397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           POINTER,   spoolss_notify_port_name },
2398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         POINTER,   spoolss_notify_driver_name },
2399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             POINTER,   spoolss_notify_comment },
2400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            POINTER,   spoolss_notify_location },
2401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             POINTER,   spoolss_notify_devmode },
2402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             POINTER,   spoolss_notify_sepfile },
2403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     POINTER,   spoolss_notify_print_processor },
2404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          POINTER,   spoolss_notify_parameters },
2405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            POINTER,   spoolss_notify_datatype },
2406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER,   spoolss_notify_security_desc },
2407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          ONE_VALUE, spoolss_notify_attributes },
2408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            ONE_VALUE, spoolss_notify_priority },
2409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    ONE_VALUE, spoolss_notify_default_priority },
2410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          ONE_VALUE, spoolss_notify_start_time },
2411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          ONE_VALUE, spoolss_notify_until_time },
2412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              ONE_VALUE, spoolss_notify_status },
2413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       POINTER,   NULL },
2414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               ONE_VALUE, spoolss_notify_cjobs },
2415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         ONE_VALUE, spoolss_notify_average_ppm },
2416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         POINTER,   NULL },
2417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       POINTER,   NULL },
2418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         POINTER,   NULL },
2419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       POINTER,   NULL },
2420 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            POINTER,   spoolss_notify_printer_name },
2421 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            POINTER,   spoolss_notify_server_name },
2422 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               POINTER,   spoolss_notify_port_name },
2423 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               POINTER,   spoolss_notify_username },
2424 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             POINTER,   spoolss_notify_username },
2425 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                POINTER,   spoolss_notify_datatype },
2426 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         POINTER,   spoolss_notify_print_processor },
2427 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              POINTER,   spoolss_notify_parameters },
2428 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             POINTER,   spoolss_notify_driver_name },
2429 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 POINTER,   spoolss_notify_devmode },
2430 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  ONE_VALUE, spoolss_notify_job_status },
2431 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           POINTER,   spoolss_notify_job_status_string },
2432 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     POINTER,   NULL },
2433 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                POINTER,   spoolss_notify_job_name },
2434 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                ONE_VALUE, spoolss_notify_priority },
2435 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                ONE_VALUE, spoolss_notify_job_position },
2436 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               POINTER,   spoolss_notify_submitted_time },
2437 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              ONE_VALUE, spoolss_notify_start_time },
2438 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              ONE_VALUE, spoolss_notify_until_time },
2439 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    ONE_VALUE, spoolss_notify_job_time },
2440 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             ONE_VALUE, spoolss_notify_total_pages },
2441 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           ONE_VALUE, spoolss_notify_pages_printed },
2442 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             ONE_VALUE, spoolss_notify_job_size },
2443 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_BYTES_PRINTED,           "JOB_NOTIFY_BYTES_PRINTED",           ONE_VALUE, NULL },
2444 { END,                 END,                                "",                                   END,       NULL }
2445 };
2446
2447 /*******************************************************************
2448  Return the size of info_data structure.
2449 ********************************************************************/
2450
2451 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2452 {
2453         int i=0;
2454
2455         while (notify_info_data_table[i].type != END)
2456         {
2457                 if ( (notify_info_data_table[i].type == type ) &&
2458                      (notify_info_data_table[i].field == field ) )
2459                 {
2460                         return (notify_info_data_table[i].size);
2461                 }
2462                 i++;
2463         }
2464         return (65535);
2465 }
2466
2467 /*******************************************************************
2468  Return the type of notify_info_data.
2469 ********************************************************************/
2470
2471 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2472 {
2473         int i=0;
2474
2475         while (notify_info_data_table[i].type != END)
2476         {
2477                 if ( (notify_info_data_table[i].type == type ) &&
2478                      (notify_info_data_table[i].field == field ) )
2479                 {
2480                         if (notify_info_data_table[i].size == POINTER)
2481                         {
2482                                 return (False);
2483                         }
2484                         else
2485                         {
2486                                 return (True);
2487                         }
2488                 }
2489                 i++;
2490         }
2491         return (False);
2492 }
2493
2494 /****************************************************************************
2495 ****************************************************************************/
2496
2497 static int search_notify(uint16 type, uint16 field, int *value)
2498 {       
2499         int j;
2500         BOOL found;
2501
2502         for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2503         {
2504                 if ( (notify_info_data_table[j].type  == type  ) &&
2505                      (notify_info_data_table[j].field == field ) )
2506                         found=True;
2507         }
2508         *value=--j;
2509
2510         if ( found && (notify_info_data_table[j].fn != NULL) )
2511                 return True;
2512         else
2513                 return False;   
2514 }
2515
2516 /****************************************************************************
2517 ****************************************************************************/
2518
2519 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2520 {
2521         info_data->type     = type;
2522         info_data->field    = field;
2523         info_data->reserved = 0;
2524         info_data->id       = id;
2525         info_data->size     = size_of_notify_info_data(type, field);
2526         info_data->enc_type = type_of_notify_info_data(type, field);
2527 }
2528
2529
2530 /*******************************************************************
2531  *
2532  * fill a notify_info struct with info asked
2533  *
2534  ********************************************************************/
2535
2536 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2537                                           snum, SPOOL_NOTIFY_OPTION_TYPE
2538                                           *option_type, uint32 id,
2539                                           TALLOC_CTX *mem_ctx) 
2540 {
2541         int field_num,j;
2542         uint16 type;
2543         uint16 field;
2544
2545         SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2546         NT_PRINTER_INFO_LEVEL *printer = NULL;
2547         print_queue_struct *queue=NULL;
2548
2549         type=option_type->type;
2550
2551         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2552                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2553                 option_type->count, lp_servicename(snum)));
2554         
2555         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2556                 return False;
2557
2558         for(field_num=0; field_num<option_type->count; field_num++) {
2559                 field = option_type->fields[field_num];
2560                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2561
2562                 if (!search_notify(type, field, &j) )
2563                         continue;
2564
2565                 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2566                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2567                         return False;
2568                 }
2569                 else info->data = tid;
2570
2571                 current_data=&info->data[info->count];
2572
2573                 construct_info_data(current_data, type, field, id);             
2574
2575                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
2576                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2577
2578                 notify_info_data_table[j].fn(snum, current_data, queue,
2579                                              printer, mem_ctx);
2580
2581                 info->count++;
2582         }
2583
2584         free_a_printer(&printer, 2);
2585         return True;
2586 }
2587
2588 /*******************************************************************
2589  *
2590  * fill a notify_info struct with info asked
2591  *
2592  ********************************************************************/
2593
2594 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2595                                        SPOOL_NOTIFY_INFO *info,
2596                                        NT_PRINTER_INFO_LEVEL *printer,
2597                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
2598                                        *option_type, uint32 id,
2599                                        TALLOC_CTX *mem_ctx) 
2600 {
2601         int field_num,j;
2602         uint16 type;
2603         uint16 field;
2604
2605         SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2606         
2607         DEBUG(4,("construct_notify_jobs_info\n"));
2608         
2609         type = option_type->type;
2610
2611         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2612                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2613                 option_type->count));
2614
2615         for(field_num=0; field_num<option_type->count; field_num++) {
2616                 field = option_type->fields[field_num];
2617
2618                 if (!search_notify(type, field, &j) )
2619                         continue;
2620
2621                 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2622                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2623                         return False;
2624                 }
2625                 else info->data = tid;
2626
2627                 current_data=&(info->data[info->count]);
2628
2629                 construct_info_data(current_data, type, field, id);
2630                 notify_info_data_table[j].fn(snum, current_data, queue,
2631                                              printer, mem_ctx);
2632                 info->count++;
2633         }
2634
2635         return True;
2636 }
2637
2638 /*
2639  * JFM: The enumeration is not that simple, it's even non obvious.
2640  *
2641  * let's take an example: I want to monitor the PRINTER SERVER for
2642  * the printer's name and the number of jobs currently queued.
2643  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2644  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2645  *
2646  * I have 3 printers on the back of my server.
2647  *
2648  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2649  * structures.
2650  *   Number     Data                    Id
2651  *      1       printer 1 name          1
2652  *      2       printer 1 cjob          1
2653  *      3       printer 2 name          2
2654  *      4       printer 2 cjob          2
2655  *      5       printer 3 name          3
2656  *      6       printer 3 name          3
2657  *
2658  * that's the print server case, the printer case is even worse.
2659  */
2660
2661 /*******************************************************************
2662  *
2663  * enumerate all printers on the printserver
2664  * fill a notify_info struct with info asked
2665  *
2666  ********************************************************************/
2667
2668 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, 
2669                                       SPOOL_NOTIFY_INFO *info,
2670                                       TALLOC_CTX *mem_ctx)
2671 {
2672         int snum;
2673         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2674         int n_services=lp_numservices();
2675         int i;
2676         uint32 id;
2677         SPOOL_NOTIFY_OPTION *option;
2678         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2679
2680         DEBUG(4,("printserver_notify_info\n"));
2681         
2682         if (!Printer)
2683                 return WERR_BADFID;
2684
2685         option=Printer->notify.option;
2686         id=1;
2687         info->version=2;
2688         info->data=NULL;
2689         info->count=0;
2690
2691         for (i=0; i<option->count; i++) {
2692                 option_type=&(option->ctr.type[i]);
2693                 
2694                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2695                         continue;
2696                 
2697                 for (snum=0; snum<n_services; snum++)
2698                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2699                                 if (construct_notify_printer_info
2700                                     (info, snum, option_type, id, mem_ctx))
2701                                         id++;
2702         }
2703                         
2704         /*
2705          * Debugging information, don't delete.
2706          */
2707         /*
2708         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2709         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2710         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2711         
2712         for (i=0; i<info->count; i++) {
2713                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2714                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2715                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2716         }
2717         */
2718         
2719         return WERR_OK;
2720 }
2721
2722 /*******************************************************************
2723  *
2724  * fill a notify_info struct with info asked
2725  *
2726  ********************************************************************/
2727
2728 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2729                                   TALLOC_CTX *mem_ctx)
2730 {
2731         int snum;
2732         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2733         int i;
2734         uint32 id;
2735         SPOOL_NOTIFY_OPTION *option;
2736         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2737         int count,j;
2738         print_queue_struct *queue=NULL;
2739         print_status_struct status;
2740         
2741         DEBUG(4,("printer_notify_info\n"));
2742
2743         if (!Printer)
2744                 return WERR_BADFID;
2745
2746         option=Printer->notify.option;
2747         id = 0x0;
2748         info->version=2;
2749         info->data=NULL;
2750         info->count=0;
2751
2752         get_printer_snum(p, hnd, &snum);
2753
2754         for (i=0; i<option->count; i++) {
2755                 option_type=&option->ctr.type[i];
2756                 
2757                 switch ( option_type->type ) {
2758                 case PRINTER_NOTIFY_TYPE:
2759                         if(construct_notify_printer_info(info, snum, 
2760                                                          option_type, id,
2761                                                          mem_ctx))  
2762                                 id--;
2763                         break;
2764                         
2765                 case JOB_NOTIFY_TYPE: {
2766                         NT_PRINTER_INFO_LEVEL *printer = NULL;
2767
2768                         count = print_queue_status(snum, &queue, &status);
2769
2770                         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, 
2771                                                          lp_servicename(snum))))
2772                                 goto done;
2773
2774                         for (j=0; j<count; j++) {
2775                                 construct_notify_jobs_info(&queue[j], info,
2776                                                            printer, snum,
2777                                                            option_type,
2778                                                            queue[j].job,
2779                                                            mem_ctx); 
2780                         }
2781
2782                         free_a_printer(&printer, 2);
2783                         
2784                 done:
2785                         SAFE_FREE(queue);
2786                         break;
2787                 }
2788                 }
2789         }
2790         
2791         /*
2792          * Debugging information, don't delete.
2793          */
2794         /*
2795         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2796         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2797         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2798         
2799         for (i=0; i<info->count; i++) {
2800                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2801                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2802                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2803         }
2804         */
2805         return WERR_OK;
2806 }
2807
2808 /********************************************************************
2809  * spoolss_rfnpcnex
2810  ********************************************************************/
2811
2812 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2813 {
2814         POLICY_HND *handle = &q_u->handle;
2815 /*      uint32 change = q_u->change; - notused. */
2816 /*      SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2817         SPOOL_NOTIFY_INFO *info = &r_u->info;
2818
2819         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2820         WERROR result = WERR_BADFID;
2821
2822         /* we always have a NOTIFY_INFO struct */
2823         r_u->info_ptr=0x1;
2824
2825         if (!Printer) {
2826                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
2827                          OUR_HANDLE(handle)));
2828                 goto done;
2829         }
2830
2831         DEBUG(4,("Printer type %x\n",Printer->printer_type));
2832
2833         /* jfm: the change value isn't used right now.
2834          *      we will honour it when
2835          *      a) we'll be able to send notification to the client
2836          *      b) we'll have a way to communicate between the spoolss process.
2837          *
2838          *      same thing for option->flags
2839          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2840          *      I don't have a global notification system, I'm sending back all the
2841          *      informations even when _NOTHING_ has changed.
2842          */
2843
2844         /* just ignore the SPOOL_NOTIFY_OPTION */
2845         
2846         switch (Printer->printer_type) {
2847                 case PRINTER_HANDLE_IS_PRINTSERVER:
2848                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
2849                         break;
2850                         
2851                 case PRINTER_HANDLE_IS_PRINTER:
2852                         result = printer_notify_info(p, handle, info, p->mem_ctx);
2853                         break;
2854         }
2855         
2856  done:
2857         return result;
2858 }
2859
2860 /********************************************************************
2861  * construct_printer_info_0
2862  * fill a printer_info_0 struct
2863  ********************************************************************/
2864
2865 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2866 {
2867         pstring chaine;
2868         int count;
2869         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2870         counter_printer_0 *session_counter;
2871         uint32 global_counter;
2872         struct tm *t;
2873         time_t setuptime;
2874         print_status_struct status;
2875         
2876         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2877                 return False;
2878
2879         count = print_queue_length(snum, &status);
2880
2881         /* check if we already have a counter for this printer */       
2882         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2883
2884         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2885                 if (session_counter->snum == snum)
2886                         break;
2887         }
2888
2889         /* it's the first time, add it to the list */
2890         if (session_counter==NULL) {
2891                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2892                         free_a_printer(&ntprinter, 2);
2893                         return False;
2894                 }
2895                 ZERO_STRUCTP(session_counter);
2896                 session_counter->snum=snum;
2897                 session_counter->counter=0;
2898                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2899         }
2900         
2901         /* increment it */
2902         session_counter->counter++;
2903         
2904         /* JFM:
2905          * the global_counter should be stored in a TDB as it's common to all the clients
2906          * and should be zeroed on samba startup
2907          */
2908         global_counter=session_counter->counter;
2909         
2910         pstrcpy(chaine,ntprinter->info_2->printername);
2911
2912         init_unistr(&printer->printername, chaine);
2913         
2914         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2915         init_unistr(&printer->servername, chaine);
2916         
2917         printer->cjobs = count;
2918         printer->total_jobs = 0;
2919         printer->total_bytes = 0;
2920
2921         setuptime = (time_t)ntprinter->info_2->setuptime;
2922         t=gmtime(&setuptime);
2923
2924         printer->year = t->tm_year+1900;
2925         printer->month = t->tm_mon+1;
2926         printer->dayofweek = t->tm_wday;
2927         printer->day = t->tm_mday;
2928         printer->hour = t->tm_hour;
2929         printer->minute = t->tm_min;
2930         printer->second = t->tm_sec;
2931         printer->milliseconds = 0;
2932
2933         printer->global_counter = global_counter;
2934         printer->total_pages = 0;
2935 #if 0   /* JERRY */
2936         printer->major_version = 0x0004;        /* NT 4 */
2937         printer->build_version = 0x0565;        /* build 1381 */
2938 #else
2939         printer->major_version = 0x0005;        /* NT 5 */
2940         printer->build_version = 0x0893;        /* build 2195 */
2941 #endif
2942         printer->unknown7 = 0x1;
2943         printer->unknown8 = 0x0;
2944         printer->unknown9 = 0x0;
2945         printer->session_counter = session_counter->counter;
2946         printer->unknown11 = 0x0;
2947         printer->printer_errors = 0x0;          /* number of print failure */
2948         printer->unknown13 = 0x0;
2949         printer->unknown14 = 0x1;
2950         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
2951         printer->unknown16 =  0x0;
2952         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2953         printer->unknown18 =  0x0;
2954         printer->status = nt_printq_status(status.status);
2955         printer->unknown20 =  0x0;
2956         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
2957         printer->unknown22 = 0x0;
2958         printer->unknown23 = 0x6;               /* 6  ???*/
2959         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
2960         printer->unknown25 = 0;
2961         printer->unknown26 = 0;
2962         printer->unknown27 = 0;
2963         printer->unknown28 = 0;
2964         printer->unknown29 = 0;
2965         
2966         free_a_printer(&ntprinter,2);
2967         return (True);  
2968 }
2969
2970 /********************************************************************
2971  * construct_printer_info_1
2972  * fill a printer_info_1 struct
2973  ********************************************************************/
2974
2975 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2976 {
2977         pstring chaine;
2978         pstring chaine2;
2979         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2980
2981         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2982                 return False;
2983
2984         printer->flags=flags;
2985
2986         if (*ntprinter->info_2->comment == '\0') {
2987                 init_unistr(&printer->comment, lp_comment(snum));
2988                 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
2989                         ntprinter->info_2->drivername, lp_comment(snum));
2990         }
2991         else {
2992                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2993                 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
2994                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
2995         }
2996                 
2997         slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2998
2999         init_unistr(&printer->description, chaine);
3000         init_unistr(&printer->name, chaine2);   
3001         
3002         free_a_printer(&ntprinter,2);
3003
3004         return True;
3005 }
3006
3007 /****************************************************************************
3008  Free a DEVMODE struct.
3009 ****************************************************************************/
3010
3011 static void free_dev_mode(DEVICEMODE *dev)
3012 {
3013         if (dev == NULL)
3014                 return;
3015
3016                 SAFE_FREE(dev->private);
3017         SAFE_FREE(dev); 
3018 }
3019
3020 /****************************************************************************
3021  Create a DEVMODE struct. Returns malloced memory.
3022 ****************************************************************************/
3023
3024 static DEVICEMODE *construct_dev_mode(int snum)
3025 {
3026         char adevice[32];
3027         char aform[32];
3028         NT_PRINTER_INFO_LEVEL *printer = NULL;
3029         NT_DEVICEMODE *ntdevmode = NULL;
3030         DEVICEMODE *devmode = NULL;
3031
3032         DEBUG(7,("construct_dev_mode\n"));
3033         
3034         DEBUGADD(8,("getting printer characteristics\n"));
3035
3036         if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3037                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3038                 return NULL;
3039         }
3040
3041         ZERO_STRUCTP(devmode);  
3042
3043         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3044                 goto fail;
3045
3046         if (printer->info_2->devmode)
3047                 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3048
3049         if (ntdevmode == NULL)
3050                 goto fail;
3051
3052         DEBUGADD(8,("loading DEVICEMODE\n"));
3053
3054         slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3055         init_unistr(&devmode->devicename, adevice);
3056
3057         slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3058         init_unistr(&devmode->formname, aform);
3059
3060         devmode->specversion      = ntdevmode->specversion;
3061         devmode->driverversion    = ntdevmode->driverversion;
3062         devmode->size             = ntdevmode->size;
3063         devmode->driverextra      = ntdevmode->driverextra;
3064         devmode->fields           = ntdevmode->fields;
3065                                 
3066         devmode->orientation      = ntdevmode->orientation;     
3067         devmode->papersize        = ntdevmode->papersize;
3068         devmode->paperlength      = ntdevmode->paperlength;
3069         devmode->paperwidth       = ntdevmode->paperwidth;
3070         devmode->scale            = ntdevmode->scale;
3071         devmode->copies           = ntdevmode->copies;
3072         devmode->defaultsource    = ntdevmode->defaultsource;
3073         devmode->printquality     = ntdevmode->printquality;
3074         devmode->color            = ntdevmode->color;
3075         devmode->duplex           = ntdevmode->duplex;
3076         devmode->yresolution      = ntdevmode->yresolution;
3077         devmode->ttoption         = ntdevmode->ttoption;
3078         devmode->collate          = ntdevmode->collate;
3079         devmode->icmmethod        = ntdevmode->icmmethod;
3080         devmode->icmintent        = ntdevmode->icmintent;
3081         devmode->mediatype        = ntdevmode->mediatype;
3082         devmode->dithertype       = ntdevmode->dithertype;
3083
3084         if (ntdevmode->private != NULL) {
3085                 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3086                         goto fail;
3087         }
3088
3089         free_nt_devicemode(&ntdevmode);
3090         free_a_printer(&printer,2);
3091
3092         return devmode;
3093
3094   fail:
3095
3096         if (ntdevmode)
3097                 free_nt_devicemode(&ntdevmode);
3098         if (printer)
3099                 free_a_printer(&printer,2);
3100         free_dev_mode(devmode);
3101
3102         return NULL;
3103 }
3104
3105 /********************************************************************
3106  * construct_printer_info_2
3107  * fill a printer_info_2 struct
3108  ********************************************************************/
3109
3110 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3111 {
3112         int count;
3113         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3114
3115         print_status_struct status;
3116
3117         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3118                 return False;
3119                 
3120         count = print_queue_length(snum, &status);
3121
3122         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3123         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
3124         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
3125         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
3126         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
3127
3128         if (*ntprinter->info_2->comment == '\0')
3129                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
3130         else
3131                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3132
3133         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
3134         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
3135         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3136         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
3137         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
3138
3139         printer->attributes = ntprinter->info_2->attributes;
3140
3141         printer->priority = ntprinter->info_2->priority;                                /* priority */  
3142         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
3143         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
3144         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
3145         printer->status = nt_printq_status(status.status);                      /* status */
3146         printer->cjobs = count;                                                 /* jobs */
3147         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
3148                         
3149         if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3150                 DEBUG(8, ("Returning NULL Devicemode!\n"));
3151         }
3152
3153         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3154                 /* steal the printer info sec_desc structure.  [badly done]. */
3155                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3156                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3157                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3158                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3159         }
3160         else {
3161                 printer->secdesc = NULL;
3162         }
3163
3164         free_a_printer(&ntprinter, 2);
3165         return True;
3166 }
3167
3168 /********************************************************************
3169  * construct_printer_info_3
3170  * fill a printer_info_3 struct
3171  ********************************************************************/
3172
3173 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3174 {
3175         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3176         PRINTER_INFO_3 *printer = NULL;
3177
3178         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3179                 return False;
3180
3181         *pp_printer = NULL;
3182         if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3183                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3184                 return False;
3185         }
3186
3187         ZERO_STRUCTP(printer);
3188         
3189         printer->flags = 4; /* These are the components of the SD we are returning. */
3190         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3191                 /* steal the printer info sec_desc structure.  [badly done]. */
3192                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3193
3194 #if 0
3195                 /*
3196                  * Set the flags for the components we are returning.
3197                  */
3198
3199                 if (printer->secdesc->owner_sid)
3200                         printer->flags |= OWNER_SECURITY_INFORMATION;
3201
3202                 if (printer->secdesc->grp_sid)
3203                         printer->flags |= GROUP_SECURITY_INFORMATION;
3204
3205                 if (printer->secdesc->dacl)
3206                         printer->flags |= DACL_SECURITY_INFORMATION;
3207
3208                 if (printer->secdesc->sacl)
3209                         printer->flags |= SACL_SECURITY_INFORMATION;
3210 #endif
3211
3212                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3213                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3214                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3215         }
3216
3217         free_a_printer(&ntprinter, 2);
3218
3219         *pp_printer = printer;
3220         return True;
3221 }
3222
3223 /********************************************************************
3224  * construct_printer_info_4
3225  * fill a printer_info_4 struct
3226  ********************************************************************/
3227
3228 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3229 {
3230         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3231
3232         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3233                 return False;
3234                 
3235         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
3236         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3237         printer->attributes = ntprinter->info_2->attributes;
3238
3239         free_a_printer(&ntprinter, 2);
3240         return True;
3241 }
3242
3243 /********************************************************************
3244  * construct_printer_info_5
3245  * fill a printer_info_5 struct
3246  ********************************************************************/
3247
3248 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3249 {
3250         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3251
3252         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3253                 return False;
3254                 
3255         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
3256         init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3257         printer->attributes = ntprinter->info_2->attributes;
3258         printer->device_not_selected_timeout = 0x3a98;
3259         printer->transmission_retry_timeout = 0xafc8;
3260
3261         free_a_printer(&ntprinter, 2);
3262         return True;
3263 }
3264
3265 /********************************************************************
3266  Spoolss_enumprinters.
3267 ********************************************************************/
3268
3269 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3270 {
3271         int snum;
3272         int i;
3273         int n_services=lp_numservices();
3274         PRINTER_INFO_1 *tp, *printers=NULL;
3275         PRINTER_INFO_1 current_prt;
3276         
3277         DEBUG(4,("enum_all_printers_info_1\n"));        
3278
3279         for (snum=0; snum<n_services; snum++) {
3280                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3281                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3282
3283                         if (construct_printer_info_1(flags, &current_prt, snum)) {
3284                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3285                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3286                                         SAFE_FREE(printers);
3287                                         *returned=0;
3288                                         return WERR_NOMEM;
3289                                 }
3290                                 else printers = tp;
3291                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
3292
3293                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
3294                                 (*returned)++;
3295                         }
3296                 }
3297         }
3298                 
3299         /* check the required size. */  
3300         for (i=0; i<*returned; i++)
3301                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3302
3303         if (!alloc_buffer_size(buffer, *needed))
3304                 return WERR_INSUFFICIENT_BUFFER;
3305
3306         /* fill the buffer with the structures */
3307         for (i=0; i<*returned; i++)
3308                 smb_io_printer_info_1("", buffer, &printers[i], 0);     
3309
3310         /* clear memory */
3311         SAFE_FREE(printers);
3312
3313         if (*needed > offered) {
3314                 *returned=0;
3315                 return WERR_INSUFFICIENT_BUFFER;
3316         }
3317         else
3318                 return WERR_OK;
3319 }
3320
3321 /********************************************************************
3322  enum_all_printers_info_1_local.
3323 *********************************************************************/
3324
3325 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3326 {
3327         DEBUG(4,("enum_all_printers_info_1_local\n"));  
3328         
3329         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3330 }
3331
3332 /********************************************************************
3333  enum_all_printers_info_1_name.
3334 *********************************************************************/
3335
3336 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3337 {
3338         char *s = name;
3339         
3340         DEBUG(4,("enum_all_printers_info_1_name\n"));   
3341         
3342         if ((name[0] == '\\') && (name[1] == '\\'))
3343                 s = name + 2;
3344                 
3345         if (is_myname_or_ipaddr(s)) {
3346                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3347         }
3348         else
3349                 return WERR_INVALID_NAME;
3350 }
3351
3352 /********************************************************************
3353  enum_all_printers_info_1_remote.
3354 *********************************************************************/
3355
3356 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3357 {
3358         PRINTER_INFO_1 *printer;
3359         fstring printername;
3360         fstring desc;
3361         fstring comment;
3362         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
3363
3364         /* JFM: currently it's more a place holder than anything else.
3365          * In the spooler world there is a notion of server registration.
3366          * the print servers are registring (sp ?) on the PDC (in the same domain)
3367          *
3368          * We should have a TDB here. The registration is done thru an undocumented RPC call.
3369          */
3370         
3371         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3372                 return WERR_NOMEM;
3373
3374         *returned=1;
3375         
3376         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());           
3377         slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3378         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3379
3380         init_unistr(&printer->description, desc);
3381         init_unistr(&printer->name, printername);       
3382         init_unistr(&printer->comment, comment);
3383         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3384                 
3385         /* check the required size. */  
3386         *needed += spoolss_size_printer_info_1(printer);
3387
3388         if (!alloc_buffer_size(buffer, *needed)) {
3389                 SAFE_FREE(printer);
3390                 return WERR_INSUFFICIENT_BUFFER;
3391         }
3392
3393         /* fill the buffer with the structures */
3394         smb_io_printer_info_1("", buffer, printer, 0);  
3395
3396         /* clear memory */
3397         SAFE_FREE(printer);
3398
3399         if (*needed > offered) {
3400                 *returned=0;
3401                 return WERR_INSUFFICIENT_BUFFER;
3402         }
3403         else
3404                 return WERR_OK;
3405 }
3406
3407 /********************************************************************
3408  enum_all_printers_info_1_network.
3409 *********************************************************************/
3410
3411 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3412 {
3413         DEBUG(4,("enum_all_printers_info_1_network\n"));        
3414         
3415         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3416 }
3417
3418 /********************************************************************
3419  * api_spoolss_enumprinters
3420  *
3421  * called from api_spoolss_enumprinters (see this to understand)
3422  ********************************************************************/
3423
3424 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3425 {
3426         int snum;
3427         int i;
3428         int n_services=lp_numservices();
3429         PRINTER_INFO_2 *tp, *printers=NULL;
3430         PRINTER_INFO_2 current_prt;
3431
3432         for (snum=0; snum<n_services; snum++) {
3433                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3434                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3435                                 
3436                         if (construct_printer_info_2(&current_prt, snum)) {
3437                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3438                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3439                                         SAFE_FREE(printers);
3440                                         *returned = 0;
3441                                         return WERR_NOMEM;
3442                                 }
3443                                 else printers = tp;
3444                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
3445                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3446                                 (*returned)++;
3447                         }
3448                 }
3449         }
3450         
3451         /* check the required size. */  
3452         for (i=0; i<*returned; i++)
3453                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3454
3455         if (!alloc_buffer_size(buffer, *needed)) {
3456                 for (i=0; i<*returned; i++) {
3457                         free_devmode(printers[i].devmode);
3458                 }
3459                 SAFE_FREE(printers);
3460                 return WERR_INSUFFICIENT_BUFFER;
3461         }
3462
3463         /* fill the buffer with the structures */
3464         for (i=0; i<*returned; i++)
3465                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);   
3466         
3467         /* clear memory */
3468         for (i=0; i<*returned; i++) {
3469                 free_devmode(printers[i].devmode);
3470         }
3471         SAFE_FREE(printers);
3472
3473         if (*needed > offered) {
3474                 *returned=0;
3475                 return WERR_INSUFFICIENT_BUFFER;
3476         }
3477         else
3478                 return WERR_OK;
3479 }
3480
3481 /********************************************************************
3482  * handle enumeration of printers at level 1
3483  ********************************************************************/
3484
3485 static WERROR enumprinters_level1( uint32 flags, fstring name,
3486                                  NEW_BUFFER *buffer, uint32 offered,
3487                                  uint32 *needed, uint32 *returned)
3488 {
3489         /* Not all the flags are equals */
3490
3491         if (flags & PRINTER_ENUM_LOCAL)
3492                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3493
3494         if (flags & PRINTER_ENUM_NAME)
3495                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3496
3497         if (flags & PRINTER_ENUM_REMOTE)
3498                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3499
3500         if (flags & PRINTER_ENUM_NETWORK)
3501                 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3502
3503         return WERR_OK; /* NT4sp5 does that */
3504 }
3505
3506 /********************************************************************
3507  * handle enumeration of printers at level 2
3508  ********************************************************************/
3509
3510 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3511                                  NEW_BUFFER *buffer, uint32 offered,
3512                                  uint32 *needed, uint32 *returned)
3513 {
3514         char *s = servername;
3515
3516         if (flags & PRINTER_ENUM_LOCAL) {
3517                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3518         }
3519
3520         if (flags & PRINTER_ENUM_NAME) {
3521                 if ((servername[0] == '\\') && (servername[1] == '\\'))
3522                         s = servername + 2;
3523                 if (is_myname_or_ipaddr(s))
3524                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3525                 else
3526                         return WERR_INVALID_NAME;
3527         }
3528
3529         if (flags & PRINTER_ENUM_REMOTE)
3530                 return WERR_UNKNOWN_LEVEL;
3531
3532         return WERR_OK;
3533 }
3534
3535 /********************************************************************
3536  * handle enumeration of printers at level 5
3537  ********************************************************************/
3538
3539 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3540                                  NEW_BUFFER *buffer, uint32 offered,
3541                                  uint32 *needed, uint32 *returned)
3542 {
3543 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3544         return WERR_OK;
3545 }
3546
3547 /********************************************************************
3548  * api_spoolss_enumprinters
3549  *
3550  * called from api_spoolss_enumprinters (see this to understand)
3551  ********************************************************************/
3552
3553 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3554 {
3555         uint32 flags = q_u->flags;
3556         UNISTR2 *servername = &q_u->servername;
3557         uint32 level = q_u->level;
3558         NEW_BUFFER *buffer = NULL;
3559         uint32 offered = q_u->offered;
3560         uint32 *needed = &r_u->needed;
3561         uint32 *returned = &r_u->returned;
3562
3563         fstring name;
3564         
3565         /* that's an [in out] buffer */
3566         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3567         buffer = r_u->buffer;
3568
3569         DEBUG(4,("_spoolss_enumprinters\n"));
3570
3571         *needed=0;
3572         *returned=0;
3573         
3574         /*
3575          * Level 1:
3576          *          flags==PRINTER_ENUM_NAME
3577          *           if name=="" then enumerates all printers
3578          *           if name!="" then enumerate the printer
3579          *          flags==PRINTER_ENUM_REMOTE
3580          *          name is NULL, enumerate printers
3581          * Level 2: name!="" enumerates printers, name can't be NULL
3582          * Level 3: doesn't exist
3583          * Level 4: does a local registry lookup
3584          * Level 5: same as Level 2
3585          */
3586
3587         unistr2_to_ascii(name, servername, sizeof(name)-1);
3588         strupper(name);
3589
3590         switch (level) {
3591         case 1:
3592                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3593         case 2:
3594                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3595         case 5:
3596                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3597         case 3:
3598         case 4:
3599                 break;
3600         }
3601         return WERR_UNKNOWN_LEVEL;
3602 }
3603
3604 /****************************************************************************
3605 ****************************************************************************/
3606
3607 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3608 {
3609         PRINTER_INFO_0 *printer=NULL;
3610
3611         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3612                 return WERR_NOMEM;
3613
3614         construct_printer_info_0(printer, snum);
3615         
3616         /* check the required size. */  
3617         *needed += spoolss_size_printer_info_0(printer);
3618
3619         if (!alloc_buffer_size(buffer, *needed)) {
3620                 SAFE_FREE(printer);
3621                 return WERR_INSUFFICIENT_BUFFER;
3622         }
3623
3624         /* fill the buffer with the structures */
3625         smb_io_printer_info_0("", buffer, printer, 0);  
3626         
3627         /* clear memory */
3628         SAFE_FREE(printer);
3629
3630         if (*needed > offered) {
3631                 return WERR_INSUFFICIENT_BUFFER;
3632         }
3633
3634         return WERR_OK;
3635 }
3636
3637 /****************************************************************************
3638 ****************************************************************************/
3639
3640 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3641 {
3642         PRINTER_INFO_1 *printer=NULL;
3643
3644         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3645                 return WERR_NOMEM;
3646
3647         construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3648         
3649         /* check the required size. */  
3650         *needed += spoolss_size_printer_info_1(printer);
3651
3652         if (!alloc_buffer_size(buffer, *needed)) {
3653                 SAFE_FREE(printer);
3654                 return WERR_INSUFFICIENT_BUFFER;
3655         }
3656
3657         /* fill the buffer with the structures */
3658         smb_io_printer_info_1("", buffer, printer, 0);  
3659         
3660         /* clear memory */
3661         SAFE_FREE(printer);
3662
3663         if (*needed > offered) {
3664                 return WERR_INSUFFICIENT_BUFFER;
3665         }
3666
3667         return WERR_OK; 
3668 }
3669
3670 /****************************************************************************
3671 ****************************************************************************/
3672
3673 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3674 {
3675         PRINTER_INFO_2 *printer=NULL;
3676
3677         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3678                 return WERR_NOMEM;
3679         
3680         construct_printer_info_2(printer, snum);
3681         
3682         /* check the required size. */  
3683         *needed += spoolss_size_printer_info_2(printer);
3684
3685         if (!alloc_buffer_size(buffer, *needed)) {
3686                 free_printer_info_2(printer);
3687                 return WERR_INSUFFICIENT_BUFFER;
3688         }
3689
3690         /* fill the buffer with the structures */
3691         if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3692                 free_printer_info_2(printer);
3693                 return WERR_NOMEM;
3694         }
3695         
3696         /* clear memory */
3697         free_printer_info_2(printer);
3698
3699         if (*needed > offered) {
3700                 return WERR_INSUFFICIENT_BUFFER;
3701         }
3702
3703         return WERR_OK; 
3704 }
3705
3706 /****************************************************************************
3707 ****************************************************************************/
3708
3709 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3710 {
3711         PRINTER_INFO_3 *printer=NULL;
3712
3713         if (!construct_printer_info_3(&printer, snum))
3714                 return WERR_NOMEM;
3715         
3716         /* check the required size. */  
3717         *needed += spoolss_size_printer_info_3(printer);
3718
3719         if (!alloc_buffer_size(buffer, *needed)) {
3720                 free_printer_info_3(printer);
3721                 return WERR_INSUFFICIENT_BUFFER;
3722         }
3723
3724         /* fill the buffer with the structures */
3725         smb_io_printer_info_3("", buffer, printer, 0);  
3726         
3727         /* clear memory */
3728         free_printer_info_3(printer);
3729         
3730         if (*needed > offered) {
3731                 return WERR_INSUFFICIENT_BUFFER;
3732         }
3733
3734         return WERR_OK; 
3735 }
3736
3737 /****************************************************************************
3738 ****************************************************************************/
3739
3740 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3741 {
3742         PRINTER_INFO_4 *printer=NULL;
3743
3744         if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3745                 return WERR_NOMEM;
3746
3747         if (!construct_printer_info_4(printer, snum))
3748                 return WERR_NOMEM;
3749         
3750         /* check the required size. */  
3751         *needed += spoolss_size_printer_info_4(printer);
3752
3753         if (!alloc_buffer_size(buffer, *needed)) {
3754                 free_printer_info_4(printer);
3755                 return WERR_INSUFFICIENT_BUFFER;
3756         }
3757
3758         /* fill the buffer with the structures */
3759         smb_io_printer_info_4("", buffer, printer, 0);  
3760         
3761         /* clear memory */
3762         free_printer_info_4(printer);
3763         
3764         if (*needed > offered) {
3765                 return WERR_INSUFFICIENT_BUFFER;
3766         }
3767
3768         return WERR_OK; 
3769 }
3770
3771 /****************************************************************************
3772 ****************************************************************************/
3773
3774 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3775 {
3776         PRINTER_INFO_5 *printer=NULL;
3777
3778         if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3779                 return WERR_NOMEM;
3780
3781         if (!construct_printer_info_5(printer, snum))
3782                 return WERR_NOMEM;
3783         
3784         /* check the required size. */  
3785         *needed += spoolss_size_printer_info_5(printer);
3786
3787         if (!alloc_buffer_size(buffer, *needed)) {
3788                 free_printer_info_5(printer);
3789                 return WERR_INSUFFICIENT_BUFFER;
3790         }
3791
3792         /* fill the buffer with the structures */
3793         smb_io_printer_info_5("", buffer, printer, 0);  
3794         
3795         /* clear memory */
3796         free_printer_info_5(printer);
3797         
3798         if (*needed > offered) {
3799                 return WERR_INSUFFICIENT_BUFFER;
3800         }
3801
3802         return WERR_OK; 
3803 }
3804
3805 /****************************************************************************
3806 ****************************************************************************/
3807
3808 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3809 {
3810         POLICY_HND *handle = &q_u->handle;
3811         uint32 level = q_u->level;
3812         NEW_BUFFER *buffer = NULL;
3813         uint32 offered = q_u->offered;
3814         uint32 *needed = &r_u->needed;
3815
3816         int snum;
3817
3818         /* that's an [in out] buffer */
3819         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3820         buffer = r_u->buffer;
3821
3822         *needed=0;
3823
3824         if (!get_printer_snum(p, handle, &snum))
3825                 return WERR_BADFID;
3826
3827         switch (level) {
3828         case 0:
3829                 return getprinter_level_0(snum, buffer, offered, needed);
3830         case 1:
3831                 return getprinter_level_1(snum, buffer, offered, needed);
3832         case 2:         
3833                 return getprinter_level_2(snum, buffer, offered, needed);
3834         case 3:         
3835                 return getprinter_level_3(snum, buffer, offered, needed);
3836         case 4:         
3837                 return getprinter_level_4(snum, buffer, offered, needed);
3838         case 5:         
3839                 return getprinter_level_5(snum, buffer, offered, needed);
3840         }
3841         return WERR_UNKNOWN_LEVEL;
3842 }       
3843                 
3844 /********************************************************************
3845  * fill a DRIVER_INFO_1 struct
3846  ********************************************************************/
3847
3848 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3849 {
3850         init_unistr( &info->name, driver.info_3->name);
3851 }
3852
3853 /********************************************************************
3854  * construct_printer_driver_info_1
3855  ********************************************************************/
3856
3857 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3858 {       
3859         NT_PRINTER_INFO_LEVEL *printer = NULL;
3860         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3861
3862         ZERO_STRUCT(driver);
3863
3864         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3865                 return WERR_INVALID_PRINTER_NAME;
3866
3867         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3868                 return WERR_UNKNOWN_PRINTER_DRIVER;
3869
3870         fill_printer_driver_info_1(info, driver, servername, architecture);
3871
3872         free_a_printer(&printer,2);
3873
3874         return WERR_OK;
3875 }
3876
3877 /********************************************************************
3878  * construct_printer_driver_info_2
3879  * fill a printer_info_2 struct
3880  ********************************************************************/
3881
3882 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3883 {
3884         pstring temp;
3885
3886         info->version=driver.info_3->cversion;
3887
3888         init_unistr( &info->name, driver.info_3->name );
3889         init_unistr( &info->architecture, driver.info_3->environment );
3890
3891
3892     if (strlen(driver.info_3->driverpath)) {
3893                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3894                 init_unistr( &info->driverpath, temp );
3895     } else
3896         init_unistr( &info->driverpath, "" );
3897
3898         if (strlen(driver.info_3->datafile)) {
3899                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3900                 init_unistr( &info->datafile, temp );
3901         } else
3902                 init_unistr( &info->datafile, "" );
3903         
3904         if (strlen(driver.info_3->configfile)) {
3905                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3906                 init_unistr( &info->configfile, temp ); 
3907         } else
3908                 init_unistr( &info->configfile, "" );
3909 }
3910
3911 /********************************************************************
3912  * construct_printer_driver_info_2
3913  * fill a printer_info_2 struct
3914  ********************************************************************/
3915
3916 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3917 {
3918         NT_PRINTER_INFO_LEVEL *printer = NULL;
3919         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3920
3921         ZERO_STRUCT(printer);
3922         ZERO_STRUCT(driver);
3923
3924         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3925                 return WERR_INVALID_PRINTER_NAME;
3926
3927         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3928                 return WERR_UNKNOWN_PRINTER_DRIVER;
3929
3930         fill_printer_driver_info_2(info, driver, servername);
3931
3932         free_a_printer(&printer,2);
3933
3934         return WERR_OK;
3935 }
3936
3937 /********************************************************************
3938  * copy a strings array and convert to UNICODE
3939  *
3940  * convert an array of ascii string to a UNICODE string
3941  ********************************************************************/
3942
3943 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3944 {
3945         int i=0;
3946         int j=0;
3947         char *v;
3948         pstring line;
3949         uint16 *tuary;
3950
3951         DEBUG(6,("init_unistr_array\n"));
3952         *uni_array=NULL;
3953
3954         while (1) {
3955                 if (char_array == NULL)
3956                         v = "";
3957                 else {
3958                         v = char_array[i];
3959                         if (!v) v = ""; /* hack to handle null lists */
3960                 }
3961                 if (strlen(v) == 0) break;
3962                 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3963                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3964                 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3965                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
3966                         return;
3967                 } else
3968                         *uni_array = tuary;
3969                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3970                 i++;
3971         }
3972         
3973         if (*uni_array) {
3974                 (*uni_array)[j]=0x0000;
3975         }
3976         
3977         DEBUGADD(6,("last one:done\n"));
3978 }
3979
3980 /********************************************************************
3981  * construct_printer_info_3
3982  * fill a printer_info_3 struct
3983  ********************************************************************/
3984
3985 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3986 {
3987         pstring temp;
3988
3989         ZERO_STRUCTP(info);
3990
3991         info->version=driver.info_3->cversion;
3992
3993         init_unistr( &info->name, driver.info_3->name );        
3994         init_unistr( &info->architecture, driver.info_3->environment );
3995
3996     if (strlen(driver.info_3->driverpath)) {
3997         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3998         init_unistr( &info->driverpath, temp );
3999     } else
4000         init_unistr( &info->driverpath, "" );
4001     
4002     if (strlen(driver.info_3->datafile)) {
4003         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4004         init_unistr( &info->datafile, temp );
4005     } else
4006         init_unistr( &info->datafile, "" );
4007
4008     if (strlen(driver.info_3->configfile)) {
4009         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4010         init_unistr( &info->configfile, temp ); 
4011     } else
4012         init_unistr( &info->configfile, "" );
4013
4014     if (strlen(driver.info_3->helpfile)) {
4015         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4016         init_unistr( &info->helpfile, temp );
4017     } else
4018         init_unistr( &info->helpfile, "" );
4019
4020         init_unistr( &info->monitorname, driver.info_3->monitorname );
4021         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4022
4023         info->dependentfiles=NULL;
4024         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4025 }
4026
4027 /********************************************************************
4028  * construct_printer_info_3
4029  * fill a printer_info_3 struct
4030  ********************************************************************/
4031
4032 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4033 {       
4034         NT_PRINTER_INFO_LEVEL *printer = NULL;
4035         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4036         WERROR status;
4037         ZERO_STRUCT(driver);
4038
4039         status=get_a_printer(&printer, 2, lp_servicename(snum) );
4040         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4041         if (!W_ERROR_IS_OK(status))
4042                 return WERR_INVALID_PRINTER_NAME;
4043
4044         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
4045         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4046
4047 #if 0   /* JERRY */
4048
4049         /* 
4050          * I put this code in during testing.  Helpful when commenting out the 
4051          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
4052          * as win2k always queries the driver using an infor level of 6.
4053          * I've left it in (but ifdef'd out) because I'll probably
4054          * use it in experimentation again in the future.   --jerry 22/01/2002
4055          */
4056
4057         if (!W_ERROR_IS_OK(status)) {
4058                 /*
4059                  * Is this a W2k client ?
4060                  */
4061                 if (version == 3) {
4062                         /* Yes - try again with a WinNT driver. */
4063                         version = 2;
4064                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
4065                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4066                 }
4067 #endif
4068
4069                 if (!W_ERROR_IS_OK(status)) {
4070                         free_a_printer(&printer,2);
4071                         return WERR_UNKNOWN_PRINTER_DRIVER;
4072                 }
4073                 
4074 #if 0   /* JERRY */
4075         }
4076 #endif
4077         
4078
4079         fill_printer_driver_info_3(info, driver, servername);
4080
4081         free_a_printer(&printer,2);
4082
4083         return WERR_OK;
4084 }
4085
4086 /********************************************************************
4087  * construct_printer_info_6
4088  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4089  ********************************************************************/
4090
4091 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4092 {
4093         pstring temp;
4094         fstring nullstr;
4095
4096         ZERO_STRUCTP(info);
4097         memset(&nullstr, '\0', sizeof(fstring));
4098
4099         info->version=driver.info_3->cversion;
4100
4101         init_unistr( &info->name, driver.info_3->name );        
4102         init_unistr( &info->architecture, driver.info_3->environment );
4103
4104         if (strlen(driver.info_3->driverpath)) {
4105                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
4106                 init_unistr( &info->driverpath, temp );
4107         } else
4108                 init_unistr( &info->driverpath, "" );
4109
4110         if (strlen(driver.info_3->datafile)) {
4111                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4112                 init_unistr( &info->datafile, temp );
4113         } else
4114                 init_unistr( &info->datafile, "" );
4115
4116         if (strlen(driver.info_3->configfile)) {
4117                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4118                 init_unistr( &info->configfile, temp ); 
4119         } else
4120                 init_unistr( &info->configfile, "" );
4121
4122         if (strlen(driver.info_3->helpfile)) {
4123                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4124                 init_unistr( &info->helpfile, temp );
4125         } else
4126                 init_unistr( &info->helpfile, "" );
4127         
4128         init_unistr( &info->monitorname, driver.info_3->monitorname );
4129         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4130
4131         info->dependentfiles=NULL;
4132         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4133
4134         info->previousdrivernames=NULL;
4135         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4136
4137         info->driver_date.low=0;
4138         info->driver_date.high=0;
4139
4140         info->padding=0;
4141         info->driver_version_low=0;
4142         info->driver_version_high=0;
4143
4144         init_unistr( &info->mfgname, "");
4145         init_unistr( &info->oem_url, "");
4146         init_unistr( &info->hardware_id, "");
4147         init_unistr( &info->provider, "");
4148 }
4149
4150 /********************************************************************
4151  * construct_printer_info_6
4152  * fill a printer_info_6 struct
4153  ********************************************************************/
4154
4155 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4156 {       
4157         NT_PRINTER_INFO_LEVEL *printer = NULL;
4158         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4159         WERROR status;
4160         ZERO_STRUCT(driver);
4161
4162         status=get_a_printer(&printer, 2, lp_servicename(snum) );
4163         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4164         if (!W_ERROR_IS_OK(status))
4165                 return WERR_INVALID_PRINTER_NAME;
4166
4167         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
4168         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4169         if (!W_ERROR_IS_OK(status)) {
4170                 /*
4171                  * Is this a W2k client ?
4172                  */
4173
4174                 if (version < 3) {
4175                         free_a_printer(&printer,2);
4176                         return WERR_UNKNOWN_PRINTER_DRIVER;
4177                 }
4178
4179                 /* Yes - try again with a WinNT driver. */
4180                 version = 2;
4181                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
4182                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4183                 if (!W_ERROR_IS_OK(status)) {
4184                         free_a_printer(&printer,2);
4185                         return WERR_UNKNOWN_PRINTER_DRIVER;
4186                 }
4187         }
4188
4189         fill_printer_driver_info_6(info, driver, servername);
4190
4191         free_a_printer(&printer,2);
4192
4193         return WERR_OK;
4194 }
4195
4196 /****************************************************************************
4197 ****************************************************************************/
4198
4199 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4200 {
4201         SAFE_FREE(info->dependentfiles);
4202 }
4203
4204 /****************************************************************************
4205 ****************************************************************************/
4206
4207 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4208 {
4209         SAFE_FREE(info->dependentfiles);
4210         
4211 }
4212
4213 /****************************************************************************
4214 ****************************************************************************/
4215
4216 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4217 {
4218         DRIVER_INFO_1 *info=NULL;
4219         WERROR status;
4220         
4221         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4222                 return WERR_NOMEM;
4223         
4224         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4225         if (!W_ERROR_IS_OK(status)) {
4226                 SAFE_FREE(info);
4227                 return status;
4228         }
4229
4230         /* check the required size. */  
4231         *needed += spoolss_size_printer_driver_info_1(info);
4232
4233         if (!alloc_buffer_size(buffer, *needed)) {
4234                 SAFE_FREE(info);
4235                 return WERR_INSUFFICIENT_BUFFER;
4236         }
4237
4238         /* fill the buffer with the structures */
4239         smb_io_printer_driver_info_1("", buffer, info, 0);      
4240
4241         /* clear memory */
4242         SAFE_FREE(info);
4243
4244         if (*needed > offered)
4245                 return WERR_INSUFFICIENT_BUFFER;
4246
4247         return WERR_OK;
4248 }
4249
4250 /****************************************************************************
4251 ****************************************************************************/
4252
4253 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4254 {
4255         DRIVER_INFO_2 *info=NULL;
4256         WERROR status;
4257         
4258         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4259                 return WERR_NOMEM;
4260         
4261         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4262         if (!W_ERROR_IS_OK(status)) {
4263                 SAFE_FREE(info);
4264                 return status;
4265         }
4266
4267         /* check the required size. */  
4268         *needed += spoolss_size_printer_driver_info_2(info);
4269
4270         if (!alloc_buffer_size(buffer, *needed)) {
4271                 SAFE_FREE(info);
4272                 return WERR_INSUFFICIENT_BUFFER;
4273         }
4274
4275         /* fill the buffer with the structures */
4276         smb_io_printer_driver_info_2("", buffer, info, 0);      
4277
4278         /* clear memory */
4279         SAFE_FREE(info);
4280
4281         if (*needed > offered)
4282                 return WERR_INSUFFICIENT_BUFFER;
4283         
4284         return WERR_OK;
4285 }
4286
4287 /****************************************************************************
4288 ****************************************************************************/
4289
4290 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4291 {
4292         DRIVER_INFO_3 info;
4293         WERROR status;
4294
4295         ZERO_STRUCT(info);
4296
4297         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4298         if (!W_ERROR_IS_OK(status)) {
4299                 return status;
4300         }
4301
4302         /* check the required size. */  
4303         *needed += spoolss_size_printer_driver_info_3(&info);
4304
4305         if (!alloc_buffer_size(buffer, *needed)) {
4306                 free_printer_driver_info_3(&info);
4307                 return WERR_INSUFFICIENT_BUFFER;
4308         }
4309
4310         /* fill the buffer with the structures */
4311         smb_io_printer_driver_info_3("", buffer, &info, 0);
4312
4313         free_printer_driver_info_3(&info);
4314
4315         if (*needed > offered)
4316                 return WERR_INSUFFICIENT_BUFFER;
4317
4318         return WERR_OK;
4319 }
4320
4321 /****************************************************************************
4322 ****************************************************************************/
4323
4324 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4325 {
4326         DRIVER_INFO_6 info;
4327         WERROR status;
4328
4329         ZERO_STRUCT(info);
4330
4331         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4332         if (!W_ERROR_IS_OK(status)) {
4333                 return status;
4334         }
4335
4336         /* check the required size. */  
4337         *needed += spoolss_size_printer_driver_info_6(&info);
4338
4339         if (!alloc_buffer_size(buffer, *needed)) {
4340                 free_printer_driver_info_6(&info);
4341                 return WERR_INSUFFICIENT_BUFFER;
4342         }
4343
4344         /* fill the buffer with the structures */
4345         smb_io_printer_driver_info_6("", buffer, &info, 0);
4346
4347         free_printer_driver_info_6(&info);
4348
4349         if (*needed > offered)
4350                 return WERR_INSUFFICIENT_BUFFER;
4351         
4352         return WERR_OK;
4353 }
4354
4355 /****************************************************************************
4356 ****************************************************************************/
4357
4358 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4359 {
4360         POLICY_HND *handle = &q_u->handle;
4361         UNISTR2 *uni_arch = &q_u->architecture;
4362         uint32 level = q_u->level;
4363         uint32 clientmajorversion = q_u->clientmajorversion;
4364 /*      uint32 clientminorversion = q_u->clientminorversion; - notused. */
4365         NEW_BUFFER *buffer = NULL;
4366         uint32 offered = q_u->offered;
4367         uint32 *needed = &r_u->needed;
4368         uint32 *servermajorversion = &r_u->servermajorversion;
4369         uint32 *serverminorversion = &r_u->serverminorversion;
4370
4371         fstring servername;
4372         fstring architecture;
4373         int snum;
4374
4375         /* that's an [in out] buffer */
4376         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4377         buffer = r_u->buffer;
4378
4379         DEBUG(4,("_spoolss_getprinterdriver2\n"));
4380
4381         *needed=0;
4382         *servermajorversion=0;
4383         *serverminorversion=0;
4384
4385         pstrcpy(servername, get_called_name());
4386         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4387
4388         if (!get_printer_snum(p, handle, &snum))
4389                 return WERR_BADFID;
4390
4391         switch (level) {
4392         case 1:
4393                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4394         case 2:
4395                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4396         case 3:
4397                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4398         case 6:
4399                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4400         }
4401
4402         return WERR_UNKNOWN_LEVEL;
4403 }
4404
4405 /****************************************************************************
4406 ****************************************************************************/
4407
4408 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4409 {
4410         POLICY_HND *handle = &q_u->handle;
4411
4412         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4413
4414         if (!Printer) {
4415                 DEBUG(3,("Error in startpageprinter printer handle\n"));
4416                 return WERR_BADFID;
4417         }
4418
4419         Printer->page_started=True;
4420         return WERR_OK;
4421 }
4422
4423 /****************************************************************************
4424 ****************************************************************************/
4425
4426 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4427 {
4428         POLICY_HND *handle = &q_u->handle;
4429
4430         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4431
4432         if (!Printer) {
4433                 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4434                 return WERR_BADFID;
4435         }
4436         
4437         Printer->page_started=False;
4438         print_job_endpage(Printer->jobid);
4439
4440         return WERR_OK;
4441 }
4442
4443 /********************************************************************
4444  * api_spoolss_getprinter
4445  * called from the spoolss dispatcher
4446  *
4447  ********************************************************************/
4448
4449 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4450 {
4451         POLICY_HND *handle = &q_u->handle;
4452 /*      uint32 level = q_u->doc_info_container.level; - notused. */
4453         DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4454         uint32 *jobid = &r_u->jobid;
4455
4456         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4457         int snum;
4458         pstring jobname;
4459         fstring datatype;
4460         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4461         struct current_user user;
4462
4463         if (!Printer) {
4464                 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4465                 return WERR_BADFID;
4466         }
4467
4468         get_current_user(&user, p);
4469
4470         /*
4471          * a nice thing with NT is it doesn't listen to what you tell it.
4472          * when asked to send _only_ RAW datas, it tries to send datas
4473          * in EMF format.
4474          *
4475          * So I add checks like in NT Server ...
4476          *
4477          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
4478          * there's a bug in NT client-side code, so we'll fix it in the
4479          * server-side code. *nnnnnggggh!*
4480          */
4481         
4482         if (info_1->p_datatype != 0) {
4483                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4484                 if (strcmp(datatype, "RAW") != 0) {
4485                         (*jobid)=0;
4486                         return WERR_INVALID_DATATYPE;
4487                 }               
4488         }               
4489         
4490         /* get the share number of the printer */
4491         if (!get_printer_snum(p, handle, &snum)) {
4492                 return WERR_BADFID;
4493         }
4494
4495         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4496         
4497         Printer->jobid = print_job_start(&user, snum, jobname);
4498
4499         /* An error occured in print_job_start() so return an appropriate
4500            NT error code. */
4501
4502         if (Printer->jobid == -1) {
4503                 return map_werror_from_unix(errno);
4504         }
4505         
4506         Printer->document_started=True;
4507         (*jobid) = Printer->jobid;
4508
4509         return WERR_OK;
4510 }
4511
4512 /********************************************************************
4513  * api_spoolss_getprinter
4514  * called from the spoolss dispatcher
4515  *
4516  ********************************************************************/
4517
4518 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4519 {
4520         POLICY_HND *handle = &q_u->handle;
4521
4522         return _spoolss_enddocprinter_internal(p, handle);
4523 }
4524
4525 /****************************************************************************
4526 ****************************************************************************/
4527
4528 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4529 {
4530         POLICY_HND *handle = &q_u->handle;
4531         uint32 buffer_size = q_u->buffer_size;
4532         uint8 *buffer = q_u->buffer;
4533         uint32 *buffer_written = &q_u->buffer_size2;
4534
4535         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4536         
4537         if (!Printer) {
4538                 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4539                 r_u->buffer_written = q_u->buffer_size2;
4540                 return WERR_BADFID;
4541         }
4542
4543         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4544
4545
4546         r_u->buffer_written = q_u->buffer_size2;
4547
4548         return WERR_OK;
4549 }
4550
4551 /********************************************************************
4552  * api_spoolss_getprinter
4553  * called from the spoolss dispatcher
4554  *
4555  ********************************************************************/
4556
4557 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4558                               pipes_struct *p)
4559 {
4560         struct current_user user;
4561         int snum;
4562         WERROR errcode = WERR_BADFUNC;
4563         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4564
4565         get_current_user(&user, p);
4566
4567         if (!Printer) {
4568                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4569                 return WERR_BADFID;
4570         }
4571
4572         if (!get_printer_snum(p, handle, &snum))
4573                 return WERR_BADFID;
4574
4575         switch (command) {
4576         case PRINTER_CONTROL_PAUSE:
4577                 if (print_queue_pause(&user, snum, &errcode)) {
4578                         errcode = WERR_OK;
4579                 }
4580                 break;
4581         case PRINTER_CONTROL_RESUME:
4582         case PRINTER_CONTROL_UNPAUSE:
4583                 if (print_queue_resume(&user, snum, &errcode)) {
4584                         errcode = WERR_OK;
4585                 }
4586                 break;
4587         case PRINTER_CONTROL_PURGE:
4588                 if (print_queue_purge(&user, snum, &errcode)) {
4589                         errcode = WERR_OK;
4590                 }
4591                 break;
4592         default:
4593                 return WERR_UNKNOWN_LEVEL;
4594         }
4595
4596         return errcode;
4597 }
4598
4599 /********************************************************************
4600  * api_spoolss_abortprinter
4601  ********************************************************************/
4602
4603 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4604 {
4605         POLICY_HND *handle = &q_u->handle;
4606
4607         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4608 }
4609
4610 /********************************************************************
4611  * called by spoolss_api_setprinter
4612  * when updating a printer description
4613  ********************************************************************/
4614
4615 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4616                                  const SPOOL_PRINTER_INFO_LEVEL *info,
4617                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4618 {
4619         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4620         struct current_user user;
4621         WERROR result;
4622         int snum;
4623
4624         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4625
4626         if (!Printer || !get_printer_snum(p, handle, &snum)) {
4627                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4628                          OUR_HANDLE(handle)));
4629
4630                 result = WERR_BADFID;
4631                 goto done;
4632         }
4633
4634         /* NT seems to like setting the security descriptor even though
4635            nothing may have actually changed.  This causes annoying
4636            dialog boxes when the user doesn't have permission to change
4637            the security descriptor. */
4638
4639         nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4640
4641         if (DEBUGLEVEL >= 10) {
4642                 SEC_ACL *the_acl;
4643                 int i;
4644
4645                 the_acl = old_secdesc_ctr->sec->dacl;
4646                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
4647                            PRINTERNAME(snum), the_acl->num_aces));
4648
4649                 for (i = 0; i < the_acl->num_aces; i++) {
4650                         fstring sid_str;
4651
4652                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4653
4654                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
4655                                   the_acl->ace[i].info.mask));
4656                 }
4657
4658                 the_acl = secdesc_ctr->sec->dacl;
4659
4660                 if (the_acl) {
4661                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4662                                    PRINTERNAME(snum), the_acl->num_aces));
4663
4664                         for (i = 0; i < the_acl->num_aces; i++) {
4665                                 fstring sid_str;
4666                                 
4667                                 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4668                                 
4669                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
4670                                            the_acl->ace[i].info.mask));
4671                         }
4672                 } else {
4673                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4674                 }
4675         }
4676
4677         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4678
4679         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4680                 result = WERR_OK;
4681                 goto done;
4682         }
4683
4684         /* Work out which user is performing the operation */
4685
4686         get_current_user(&user, p);
4687
4688         /* Check the user has permissions to change the security
4689            descriptor.  By experimentation with two NT machines, the user
4690            requires Full Access to the printer to change security
4691            information. */
4692
4693         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4694                 result = WERR_ACCESS_DENIED;
4695                 goto done;
4696         }
4697
4698         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4699
4700  done:
4701
4702         return result;
4703 }
4704
4705 /********************************************************************
4706  Do Samba sanity checks on a printer info struct.
4707  this has changed purpose: it now "canonicalises" printer
4708  info from a client rather than just checking it is correct
4709  ********************************************************************/
4710
4711 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4712 {
4713         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4714                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4715
4716         /* we force some elements to "correct" values */
4717         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4718         fstrcpy(info->sharename, lp_servicename(snum));
4719         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4720                  get_called_name(), info->sharename);
4721         info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
4722         
4723         return True;
4724 }
4725
4726 /****************************************************************************
4727 ****************************************************************************/
4728
4729 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4730 {
4731         char *cmd = lp_addprinter_cmd();
4732         char **qlines;
4733         pstring command;
4734         pstring driverlocation;
4735         int numlines;
4736         int ret;
4737         int fd;
4738         fstring remote_machine = "%m";
4739
4740         /* build driver path... only 9X architecture is needed for legacy reasons */
4741         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4742                         get_called_name());
4743         /* change \ to \\ for the shell */
4744         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4745
4746         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4747                         cmd, printer->info_2->printername, printer->info_2->sharename,
4748                         printer->info_2->portname, printer->info_2->drivername,
4749                         printer->info_2->location, driverlocation, remote_machine);
4750
4751         /* Convert script args to unix-codepage */
4752         DEBUG(10,("Running [%s]\n", command));
4753         ret = smbrun(command, &fd);
4754         DEBUGADD(10,("returned [%d]\n", ret));
4755
4756         if ( ret != 0 ) {
4757                 if (fd != -1)
4758                         close(fd);
4759                 return False;
4760         }
4761
4762         numlines = 0;
4763         /* Get lines and convert them back to dos-codepage */
4764         qlines = fd_lines_load(fd, &numlines);
4765         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4766         close(fd);
4767
4768         if(numlines) {
4769                 /* Set the portname to what the script says the portname should be. */
4770                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4771                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4772
4773                 /* Send SIGHUP to process group... is there a better way? */
4774                 kill(0, SIGHUP);
4775                 add_all_printers();
4776         }
4777
4778         file_lines_free(qlines);
4779         return True;
4780 }
4781
4782 #if 0   /* JERRY */
4783
4784 /* Return true if two devicemodes are equal */
4785
4786 #define DEVMODE_CHECK_INT(field) \
4787     if (d1->field != d2->field) { \
4788         DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4789             d1->field, d2->field)); \
4790         return False; \
4791     }
4792
4793 /************************************************************************
4794  Handy, but currently unused functions
4795  ***********************************************************************/
4796
4797 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4798 {
4799         if (!d1 && !d2) goto equal;  /* if both are NULL they are equal */
4800
4801         if (!d1 ^ !d2) {
4802                 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4803                 return False; /* if either is exclusively NULL are not equal */
4804         }
4805
4806         if (!strequal(d1->devicename, d2->devicename)) {
4807                 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4808                 return False;
4809         }
4810
4811         if (!strequal(d1->formname, d2->formname)) {
4812                 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4813                 return False;
4814         }
4815
4816         DEVMODE_CHECK_INT(specversion);
4817         DEVMODE_CHECK_INT(driverversion);
4818         DEVMODE_CHECK_INT(driverextra);
4819         DEVMODE_CHECK_INT(orientation);
4820         DEVMODE_CHECK_INT(papersize);
4821         DEVMODE_CHECK_INT(paperlength);
4822         DEVMODE_CHECK_INT(paperwidth);
4823         DEVMODE_CHECK_INT(scale);
4824         DEVMODE_CHECK_INT(copies);
4825         DEVMODE_CHECK_INT(defaultsource);
4826         DEVMODE_CHECK_INT(printquality);
4827         DEVMODE_CHECK_INT(color);
4828         DEVMODE_CHECK_INT(duplex);
4829         DEVMODE_CHECK_INT(yresolution);
4830         DEVMODE_CHECK_INT(ttoption);
4831         DEVMODE_CHECK_INT(collate);
4832         DEVMODE_CHECK_INT(logpixels);
4833
4834         DEVMODE_CHECK_INT(fields);
4835         DEVMODE_CHECK_INT(bitsperpel);
4836         DEVMODE_CHECK_INT(pelswidth);
4837         DEVMODE_CHECK_INT(pelsheight);
4838         DEVMODE_CHECK_INT(displayflags);
4839         DEVMODE_CHECK_INT(displayfrequency);
4840         DEVMODE_CHECK_INT(icmmethod);
4841         DEVMODE_CHECK_INT(icmintent);
4842         DEVMODE_CHECK_INT(mediatype);
4843         DEVMODE_CHECK_INT(dithertype);
4844         DEVMODE_CHECK_INT(reserved1);
4845         DEVMODE_CHECK_INT(reserved2);
4846         DEVMODE_CHECK_INT(panningwidth);
4847         DEVMODE_CHECK_INT(panningheight);
4848
4849         /* compare the private data if it exists */
4850         if (!d1->driverextra && !d2->driverextra) goto equal;
4851
4852
4853         DEVMODE_CHECK_INT(driverextra);
4854
4855         if (memcmp(d1->private, d2->private, d1->driverextra)) {
4856                 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4857                 return False;
4858         }
4859
4860  equal:
4861         DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4862         return True;
4863 }
4864
4865 /* Return true if two NT_PRINTER_PARAM structures are equal */
4866
4867 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4868                                    NT_PRINTER_PARAM *p2)
4869 {
4870         if (!p1 && !p2) goto equal;
4871
4872         if ((!p1 && p2) || (p1 && !p2)) {
4873                 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4874                 return False;
4875         }
4876
4877         /* Compare lists of printer parameters */
4878
4879         while (p1) {
4880                 BOOL found = False;
4881                 NT_PRINTER_PARAM *q = p1;
4882
4883                 /* Find the parameter in the second structure */
4884
4885                 while(q) {
4886
4887                         if (strequal(p1->value, q->value)) {
4888
4889                                 if (p1->type != q->type) {
4890                                         DEBUG(10, ("nt_printer_param_equal():"
4891                                                    "types for %s differ (%d != %d)\n",
4892                                                    p1->value, p1->type,
4893                                                    q->type));
4894                                         break;
4895                                 }
4896
4897                                 if (p1->data_len != q->data_len) {
4898                                         DEBUG(10, ("nt_printer_param_equal():"
4899                                                    "len for %s differs (%d != %d)\n",
4900                                                    p1->value, p1->data_len,
4901                                                    q->data_len));
4902                                         break;
4903                                 }
4904
4905                                 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4906                                         found = True;
4907                                 } else {
4908                                         DEBUG(10, ("nt_printer_param_equal():"
4909                                                    "data for %s differs\n", p1->value));
4910                                 }
4911
4912                                 break;
4913                         }
4914
4915                         q = q->next;
4916                 }
4917
4918                 if (!found) {
4919                         DEBUG(10, ("nt_printer_param_equal(): param %s "
4920                                    "does not exist\n", p1->value));
4921                         return False;
4922                 }
4923
4924                 p1 = p1->next;
4925         }
4926
4927         equal:
4928
4929         DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4930         return True;
4931 }
4932
4933 /********************************************************************
4934  * Called by update_printer when trying to work out whether to
4935  * actually update printer info.
4936  ********************************************************************/
4937
4938 #define PI_CHECK_INT(field) \
4939     if (pi1->field != pi2->field) { \
4940         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4941             pi1->field, pi2->field)); \
4942         return False; \
4943     }
4944
4945 #define PI_CHECK_STR(field) \
4946     if (!strequal(pi1->field, pi2->field)) { \
4947         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4948             pi1->field, pi2->field)); \
4949         return False; \
4950     }
4951
4952 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4953                                         NT_PRINTER_INFO_LEVEL *p2)
4954 {
4955         NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4956
4957         /* Trivial conditions */
4958
4959         if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4960                 goto equal;
4961         }
4962
4963         if ((!p1 && p2) || (p1 && !p2) ||
4964             (!p1->info_2 && p2->info_2) ||
4965             (p1->info_2 && !p2->info_2)) {
4966                 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4967                            "differ\n"));
4968                 return False;
4969         }
4970
4971         /* Compare two nt_printer_info_level structures.  Don't compare
4972            status or cjobs as they seem to have something to do with the
4973            printer queue. */
4974
4975         pi1 = p1->info_2;
4976         pi2 = p2->info_2;
4977
4978         /* Don't check the attributes as we stomp on the value in
4979            check_printer_ok() anyway. */
4980
4981 #if 0
4982         PI_CHECK_INT(attributes);
4983 #endif
4984
4985         PI_CHECK_INT(priority);
4986         PI_CHECK_INT(default_priority);
4987         PI_CHECK_INT(starttime);
4988         PI_CHECK_INT(untiltime);
4989         PI_CHECK_INT(averageppm);
4990
4991         /* Yuck - don't check the printername or servername as the
4992            mod_a_printer() code plays games with them.  You can't
4993            change the printername or the sharename through this interface
4994            in Samba. */
4995
4996         PI_CHECK_STR(sharename);
4997         PI_CHECK_STR(portname);
4998         PI_CHECK_STR(drivername);
4999         PI_CHECK_STR(comment);
5000         PI_CHECK_STR(location);
5001
5002         if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
5003                 return False;
5004         }
5005
5006         PI_CHECK_STR(sepfile);
5007         PI_CHECK_STR(printprocessor);
5008         PI_CHECK_STR(datatype);
5009         PI_CHECK_STR(parameters);
5010
5011         if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
5012                 return False;
5013         }
5014
5015         if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
5016                 return False;
5017         }
5018
5019         PI_CHECK_INT(changeid);
5020         PI_CHECK_INT(c_setprinter);
5021         PI_CHECK_INT(setuptime);
5022
5023  equal:
5024         DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5025         return True;
5026 }
5027
5028 #endif
5029
5030 /********************************************************************
5031  * Called by spoolss_api_setprinter
5032  * when updating a printer description.
5033  ********************************************************************/
5034
5035 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5036                            const SPOOL_PRINTER_INFO_LEVEL *info,
5037                            DEVICEMODE *devmode)
5038 {
5039         int snum;
5040         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5041         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5042         PRINTER_MESSAGE_INFO msg;
5043         WERROR result;
5044
5045         DEBUG(8,("update_printer\n"));
5046         
5047         ZERO_STRUCT(msg);
5048         
5049         result = WERR_OK;
5050
5051         if (level!=2) {
5052                 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5053                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5054                 result = WERR_UNKNOWN_LEVEL;
5055                 goto done;
5056         }
5057
5058         if (!Printer) {
5059                 result = WERR_BADFID;
5060                 goto done;
5061         }
5062
5063         if (!get_printer_snum(p, handle, &snum)) {
5064                 result = WERR_BADFID;
5065                 goto done;
5066         }
5067
5068         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5069             (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5070                 result = WERR_BADFID;
5071                 goto done;
5072         }
5073
5074         DEBUGADD(8,("Converting info_2 struct\n"));
5075
5076         /*
5077          * convert_printer_info converts the incoming
5078          * info from the client and overwrites the info
5079          * just read from the tdb in the pointer 'printer'.
5080          */
5081
5082         if (!convert_printer_info(info, printer, level)) {
5083                 result =  WERR_NOMEM;
5084                 goto done;
5085         }
5086
5087         if (devmode) {
5088                 /* we have a valid devmode
5089                    convert it and link it*/
5090
5091                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5092                 if (!convert_devicemode(printer->info_2->printername, devmode,
5093                                 &printer->info_2->devmode)) {
5094                         result =  WERR_NOMEM;
5095                         goto done;
5096                 }
5097         }
5098
5099         /* Do sanity check on the requested changes for Samba */
5100
5101         if (!check_printer_ok(printer->info_2, snum)) {
5102                 result = WERR_INVALID_PARAM;
5103                 goto done;
5104         }
5105
5106 #if 0   /* JERRY */
5107         
5108         /*
5109          * Another one of those historical misunderstandings...
5110          * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5111          * I'm leaving it here as a reminder.  --jerry
5112          */
5113
5114         if (nt_printer_info_level_equal(printer, old_printer)) {
5115                 DEBUG(3, ("update_printer: printer info has not changed\n"));
5116                 result = WERR_OK;
5117                 goto done;
5118         }
5119
5120 #endif
5121
5122         /* Check calling user has permission to update printer description */
5123
5124         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5125                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5126                 result = WERR_ACCESS_DENIED;
5127                 goto done;
5128         }
5129
5130         /* Call addprinter hook */
5131
5132         if (*lp_addprinter_cmd()) {
5133                 if ( !add_printer_hook(printer) ) {
5134                         result = WERR_ACCESS_DENIED;
5135                         goto done;
5136                 }
5137         }
5138         
5139         /*
5140          * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5141          * DEVMODE.displayfrequency, which is not used for printer drivers. This
5142          * requires Win32 client code (see other notes elsewhere in the code).
5143          */
5144         if (printer->info_2->devmode &&
5145                 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5146  
5147                 DEBUG(10,("update_printer: Save printer driver init data\n"));
5148                 printer->info_2->devmode->displayfrequency = 0;
5149  
5150                 if (update_driver_init(*printer, 2)!=0) {
5151                         DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5152                         result = WERR_ACCESS_DENIED;
5153                         goto done;
5154                 }
5155         } else {
5156                 /*
5157                  * When a *new* driver is bound to a printer, the drivername is used to
5158                  * lookup previously saved driver initialization info, which is then
5159                  * bound to the printer, simulating what happens in the Windows arch.
5160                  */
5161                 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5162                         set_driver_init(printer, 2);
5163                         msg.flags |= PRINTER_MESSAGE_DRIVER;
5164                 }
5165         }
5166
5167         /* Update printer info */
5168         result = mod_a_printer(*printer, 2);
5169
5170         /* flag which changes actually occured.  This is a small subset of
5171            all the possible changes                                         */
5172
5173         if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5174                 msg.flags |= PRINTER_MESSAGE_COMMENT;
5175
5176         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5177                 msg.flags |= PRINTER_MESSAGE_SHARENAME;
5178
5179         if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5180                 msg.flags |= PRINTER_MESSAGE_PORT;
5181
5182         if (!strequal(printer->info_2->location, old_printer->info_2->location))
5183                 msg.flags |= PRINTER_MESSAGE_LOCATION;
5184
5185         ZERO_STRUCT(msg);
5186         
5187         msg.low = PRINTER_CHANGE_ADD_PRINTER;
5188         fstrcpy(msg.printer_name, printer->info_2->printername);
5189
5190         /* only send a notify if something changed */
5191         if (msg.flags) {
5192                 srv_spoolss_sendnotify(msg.printer_name, 0, PRINTER_CHANGE_ADD_PRINTER, msg.flags);
5193         }
5194
5195  done:
5196         free_a_printer(&printer, 2);
5197         free_a_printer(&old_printer, 2);
5198
5199
5200         return result;
5201 }
5202
5203 /****************************************************************************
5204 ****************************************************************************/
5205
5206 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5207 {
5208         POLICY_HND *handle = &q_u->handle;
5209         uint32 level = q_u->level;
5210         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5211         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5212         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5213         uint32 command = q_u->command;
5214
5215         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5216         
5217         if (!Printer) {
5218                 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5219                 return WERR_BADFID;
5220         }
5221
5222         /* check the level */   
5223         switch (level) {
5224                 case 0:
5225                         return control_printer(handle, command, p);
5226                 case 2:
5227                         return update_printer(p, handle, level, info, devmode_ctr.devmode);
5228                 case 3:
5229                         return update_printer_sec(handle, level, info, p,
5230                                                   secdesc_ctr);
5231                 default:
5232                         return WERR_UNKNOWN_LEVEL;
5233         }
5234 }
5235
5236 /****************************************************************************
5237 ****************************************************************************/
5238
5239 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5240 {
5241         POLICY_HND *handle = &q_u->handle;
5242
5243         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5244         
5245         if (!Printer) {
5246                 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5247                 return WERR_BADFID;
5248         }
5249
5250         if (Printer->notify.client_connected==True)
5251                 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5252
5253         Printer->notify.flags=0;
5254         Printer->notify.options=0;
5255         Printer->notify.localmachine[0]='\0';
5256         Printer->notify.printerlocal=0;
5257         if (Printer->notify.option)
5258                 free_spool_notify_option(&Printer->notify.option);
5259         Printer->notify.client_connected=False;
5260
5261         return WERR_OK;
5262 }
5263
5264 /****************************************************************************
5265 ****************************************************************************/
5266
5267 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5268 {
5269         /* that's an [in out] buffer (despite appearences to the contrary) */
5270         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5271
5272         r_u->needed = 0;
5273         return WERR_INVALID_PARAM; /* this is what a NT server
5274                                            returns for AddJob. AddJob
5275                                            must fail on non-local
5276                                            printers */
5277 }
5278
5279 /****************************************************************************
5280 ****************************************************************************/
5281
5282 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5283                             int position, int snum)
5284 {
5285         pstring temp_name;
5286         
5287         struct tm *t;
5288         
5289         t=gmtime(&queue->time);
5290         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5291
5292         job_info->jobid=queue->job;     
5293         init_unistr(&job_info->printername, lp_servicename(snum));
5294         init_unistr(&job_info->machinename, temp_name);
5295         init_unistr(&job_info->username, queue->fs_user);
5296         init_unistr(&job_info->document, queue->fs_file);
5297         init_unistr(&job_info->datatype, "RAW");
5298         init_unistr(&job_info->text_status, "");
5299         job_info->status=nt_printj_status(queue->status);
5300         job_info->priority=queue->priority;
5301         job_info->position=position;
5302         job_info->totalpages=queue->page_count;
5303         job_info->pagesprinted=0;
5304
5305         make_systemtime(&job_info->submitted, t);
5306 }
5307
5308 /****************************************************************************
5309 ****************************************************************************/
5310
5311 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5312                             int position, int snum, 
5313                             NT_PRINTER_INFO_LEVEL *ntprinter, 
5314                             DEVICEMODE *devmode)
5315 {
5316         pstring temp_name;
5317         pstring chaine;
5318         struct tm *t;
5319
5320         t=gmtime(&queue->time);
5321         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5322
5323         job_info->jobid=queue->job;
5324         
5325         slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5326
5327         init_unistr(&job_info->printername, chaine);
5328         
5329         init_unistr(&job_info->machinename, temp_name);
5330         init_unistr(&job_info->username, queue->fs_user);
5331         init_unistr(&job_info->document, queue->fs_file);
5332         init_unistr(&job_info->notifyname, queue->fs_user);
5333         init_unistr(&job_info->datatype, "RAW");
5334         init_unistr(&job_info->printprocessor, "winprint");
5335         init_unistr(&job_info->parameters, "");
5336         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5337         init_unistr(&job_info->text_status, "");
5338         
5339 /* and here the security descriptor */
5340
5341         job_info->status=nt_printj_status(queue->status);
5342         job_info->priority=queue->priority;
5343         job_info->position=position;
5344         job_info->starttime=0;
5345         job_info->untiltime=0;
5346         job_info->totalpages=queue->page_count;
5347         job_info->size=queue->size;
5348         make_systemtime(&(job_info->submitted), t);
5349         job_info->timeelapsed=0;
5350         job_info->pagesprinted=0;
5351
5352         job_info->devmode = devmode;
5353
5354         return (True);
5355 }
5356
5357 /****************************************************************************
5358  Enumjobs at level 1.
5359 ****************************************************************************/
5360
5361 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5362                               NEW_BUFFER *buffer, uint32 offered,
5363                               uint32 *needed, uint32 *returned)
5364 {
5365         JOB_INFO_1 *info;
5366         int i;
5367         
5368         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5369         if (info==NULL) {
5370                 SAFE_FREE(queue);
5371                 *returned=0;
5372                 return WERR_NOMEM;
5373         }
5374         
5375         for (i=0; i<*returned; i++)
5376                 fill_job_info_1(&info[i], &queue[i], i, snum);
5377
5378         SAFE_FREE(queue);
5379
5380         /* check the required size. */  
5381         for (i=0; i<*returned; i++)
5382                 (*needed) += spoolss_size_job_info_1(&info[i]);
5383
5384         if (!alloc_buffer_size(buffer, *needed)) {
5385                 SAFE_FREE(info);
5386                 return WERR_INSUFFICIENT_BUFFER;
5387         }
5388
5389         /* fill the buffer with the structures */
5390         for (i=0; i<*returned; i++)
5391                 smb_io_job_info_1("", buffer, &info[i], 0);     
5392
5393         /* clear memory */
5394         SAFE_FREE(info);
5395
5396         if (*needed > offered) {
5397                 *returned=0;
5398                 return WERR_INSUFFICIENT_BUFFER;
5399         }
5400
5401         return WERR_OK;
5402 }
5403
5404 /****************************************************************************
5405  Enumjobs at level 2.
5406 ****************************************************************************/
5407
5408 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5409                               NEW_BUFFER *buffer, uint32 offered,
5410                               uint32 *needed, uint32 *returned)
5411 {
5412         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5413         JOB_INFO_2 *info = NULL;
5414         int i;
5415         WERROR result;
5416         DEVICEMODE *devmode = NULL;
5417         
5418         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5419         if (info==NULL) {
5420                 *returned=0;
5421                 result = WERR_NOMEM;
5422                 goto done;
5423         }
5424
5425         result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5426         if (!W_ERROR_IS_OK(result)) {
5427                 *returned = 0;
5428                 goto done;
5429         }
5430
5431         if (!(devmode = construct_dev_mode(snum))) {
5432                 *returned = 0;
5433                 result = WERR_NOMEM;
5434                 goto done;
5435         }
5436
5437         for (i=0; i<*returned; i++)
5438                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5439                                 devmode);
5440
5441         free_a_printer(&ntprinter, 2);
5442         SAFE_FREE(queue);
5443
5444         /* check the required size. */  
5445         for (i=0; i<*returned; i++)
5446                 (*needed) += spoolss_size_job_info_2(&info[i]);
5447
5448         if (*needed > offered) {
5449                 *returned=0;
5450                 result = WERR_INSUFFICIENT_BUFFER;
5451                 goto done;
5452         }
5453
5454         if (!alloc_buffer_size(buffer, *needed)) {
5455                 SAFE_FREE(info);
5456                 result = WERR_INSUFFICIENT_BUFFER;
5457                 goto done;
5458         }
5459
5460         /* fill the buffer with the structures */
5461         for (i=0; i<*returned; i++)
5462                 smb_io_job_info_2("", buffer, &info[i], 0);     
5463
5464         result = WERR_OK;
5465
5466  done:
5467         free_a_printer(&ntprinter, 2);
5468         free_devmode(devmode);
5469         SAFE_FREE(queue);
5470         SAFE_FREE(info);
5471
5472         return result;
5473 }
5474
5475 /****************************************************************************
5476  Enumjobs.
5477 ****************************************************************************/
5478
5479 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5480 {       
5481         POLICY_HND *handle = &q_u->handle;
5482 /*      uint32 firstjob = q_u->firstjob; - notused. */
5483 /*      uint32 numofjobs = q_u->numofjobs; - notused. */
5484         uint32 level = q_u->level;
5485         NEW_BUFFER *buffer = NULL;
5486         uint32 offered = q_u->offered;
5487         uint32 *needed = &r_u->needed;
5488         uint32 *returned = &r_u->returned;
5489
5490         int snum;
5491         print_status_struct prt_status;
5492         print_queue_struct *queue=NULL;
5493
5494         /* that's an [in out] buffer */
5495         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5496         buffer = r_u->buffer;
5497
5498         DEBUG(4,("_spoolss_enumjobs\n"));
5499
5500         *needed=0;
5501         *returned=0;
5502
5503         if (!get_printer_snum(p, handle, &snum))
5504                 return WERR_BADFID;
5505
5506         *returned = print_queue_status(snum, &queue, &prt_status);
5507         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5508
5509         if (*returned == 0) {
5510                 SAFE_FREE(queue);
5511                 return WERR_OK;
5512         }
5513
5514         switch (level) {
5515         case 1:
5516                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5517         case 2:
5518                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5519         default:
5520                 SAFE_FREE(queue);
5521                 *returned=0;
5522                 return WERR_UNKNOWN_LEVEL;
5523         }
5524 }
5525
5526 /****************************************************************************
5527 ****************************************************************************/
5528
5529 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5530 {
5531         return WERR_OK;
5532 }
5533
5534 /****************************************************************************
5535 ****************************************************************************/
5536
5537 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5538 {
5539         POLICY_HND *handle = &q_u->handle;
5540         uint32 jobid = q_u->jobid;
5541 /*      uint32 level = q_u->level; - notused. */
5542 /*      JOB_INFO *ctr = &q_u->ctr; - notused. */
5543         uint32 command = q_u->command;
5544
5545         struct current_user user;
5546         int snum;
5547         WERROR errcode = WERR_BADFUNC;
5548                 
5549         if (!get_printer_snum(p, handle, &snum)) {
5550                 return WERR_BADFID;
5551         }
5552
5553         if (!print_job_exists(jobid)) {
5554                 return WERR_INVALID_PRINTER_NAME;
5555         }
5556
5557         get_current_user(&user, p);     
5558
5559         switch (command) {
5560         case JOB_CONTROL_CANCEL:
5561         case JOB_CONTROL_DELETE:
5562                 if (print_job_delete(&user, jobid, &errcode)) {
5563                         errcode = WERR_OK;
5564                 }
5565                 break;
5566         case JOB_CONTROL_PAUSE:
5567                 if (print_job_pause(&user, jobid, &errcode)) {
5568                         errcode = WERR_OK;
5569                 }               
5570                 break;
5571         case JOB_CONTROL_RESTART:
5572         case JOB_CONTROL_RESUME:
5573                 if (print_job_resume(&user, jobid, &errcode)) {
5574                         errcode = WERR_OK;
5575                 }
5576                 break;
5577         default:
5578                 return WERR_UNKNOWN_LEVEL;
5579         }
5580
5581         return errcode;
5582 }
5583
5584 /****************************************************************************
5585  Enumerates all printer drivers at level 1.
5586 ****************************************************************************/
5587
5588 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5589 {
5590         int i;
5591         int ndrivers;
5592         uint32 version;
5593         fstring *list = NULL;
5594
5595         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5596         DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5597
5598         *returned=0;
5599
5600 #define MAX_VERSION 4
5601
5602         for (version=0; version<MAX_VERSION; version++) {
5603                 list=NULL;
5604                 ndrivers=get_ntdrivers(&list, architecture, version);
5605                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5606
5607                 if(ndrivers == -1)
5608                         return WERR_NOMEM;
5609
5610                 if(ndrivers != 0) {
5611                         if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5612                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5613                                 SAFE_FREE(driver_info_1);
5614                                 SAFE_FREE(list);
5615                                 return WERR_NOMEM;
5616                         }
5617                         else driver_info_1 = tdi1;
5618                 }
5619
5620                 for (i=0; i<ndrivers; i++) {
5621                         WERROR status;
5622                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5623                         ZERO_STRUCT(driver);
5624                         status = get_a_printer_driver(&driver, 3, list[i], 
5625                                                       architecture, version);
5626                         if (!W_ERROR_IS_OK(status)) {
5627                                 SAFE_FREE(list);
5628                                 return status;
5629                         }
5630                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
5631                         free_a_printer_driver(driver, 3);
5632                 }       
5633
5634                 *returned+=ndrivers;
5635                 SAFE_FREE(list);
5636         }
5637         
5638         /* check the required size. */
5639         for (i=0; i<*returned; i++) {
5640                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5641                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5642         }
5643
5644         if (!alloc_buffer_size(buffer, *needed)) {
5645                 SAFE_FREE(driver_info_1);
5646                 return WERR_INSUFFICIENT_BUFFER;
5647         }
5648
5649         /* fill the buffer with the driver structures */
5650         for (i=0; i<*returned; i++) {
5651                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5652                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5653         }
5654
5655         SAFE_FREE(driver_info_1);
5656
5657         if (*needed > offered) {
5658                 *returned=0;
5659                 return WERR_INSUFFICIENT_BUFFER;
5660         }
5661
5662         return WERR_OK;
5663 }
5664
5665 /****************************************************************************
5666  Enumerates all printer drivers at level 2.
5667 ****************************************************************************/
5668
5669 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5670 {
5671         int i;
5672         int ndrivers;
5673         uint32 version;
5674         fstring *list = NULL;
5675
5676         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5677         DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5678
5679         *returned=0;
5680
5681 #define MAX_VERSION 4
5682
5683         for (version=0; version<MAX_VERSION; version++) {
5684                 list=NULL;
5685                 ndrivers=get_ntdrivers(&list, architecture, version);
5686                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5687
5688                 if(ndrivers == -1)
5689                         return WERR_NOMEM;
5690
5691                 if(ndrivers != 0) {
5692                         if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5693                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5694                                 SAFE_FREE(driver_info_2);
5695                                 SAFE_FREE(list);
5696                                 return WERR_NOMEM;
5697                         }
5698                         else driver_info_2 = tdi2;
5699                 }
5700                 
5701                 for (i=0; i<ndrivers; i++) {
5702                         WERROR status;
5703
5704                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5705                         ZERO_STRUCT(driver);
5706                         status = get_a_printer_driver(&driver, 3, list[i], 
5707                                                       architecture, version);
5708                         if (!W_ERROR_IS_OK(status)) {
5709                                 SAFE_FREE(list);
5710                                 return status;
5711                         }
5712                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
5713                         free_a_printer_driver(driver, 3);
5714                 }       
5715
5716                 *returned+=ndrivers;
5717                 SAFE_FREE(list);
5718         }
5719         
5720         /* check the required size. */
5721         for (i=0; i<*returned; i++) {
5722                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5723                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5724         }
5725
5726         if (!alloc_buffer_size(buffer, *needed)) {
5727                 SAFE_FREE(driver_info_2);
5728                 return WERR_INSUFFICIENT_BUFFER;
5729         }
5730
5731         /* fill the buffer with the form structures */
5732         for (i=0; i<*returned; i++) {
5733                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5734                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5735         }
5736
5737         SAFE_FREE(driver_info_2);
5738
5739         if (*needed > offered) {
5740                 *returned=0;
5741                 return WERR_INSUFFICIENT_BUFFER;
5742         }
5743
5744         return WERR_OK;
5745 }
5746
5747 /****************************************************************************
5748  Enumerates all printer drivers at level 3.
5749 ****************************************************************************/
5750
5751 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5752 {
5753         int i;
5754         int ndrivers;
5755         uint32 version;
5756         fstring *list = NULL;
5757
5758         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5759         DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5760
5761         *returned=0;
5762
5763 #define MAX_VERSION 4
5764
5765         for (version=0; version<MAX_VERSION; version++) {
5766                 list=NULL;
5767                 ndrivers=get_ntdrivers(&list, architecture, version);
5768                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5769
5770                 if(ndrivers == -1)
5771                         return WERR_NOMEM;
5772
5773                 if(ndrivers != 0) {
5774                         if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5775                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5776                                 SAFE_FREE(driver_info_3);
5777                                 SAFE_FREE(list);
5778                                 return WERR_NOMEM;
5779                         }
5780                         else driver_info_3 = tdi3;
5781                 }
5782
5783                 for (i=0; i<ndrivers; i++) {
5784                         WERROR status;
5785
5786                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5787                         ZERO_STRUCT(driver);
5788                         status = get_a_printer_driver(&driver, 3, list[i], 
5789                                                       architecture, version);
5790                         if (!W_ERROR_IS_OK(status)) {
5791                                 SAFE_FREE(list);
5792                                 return status;
5793                         }
5794                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
5795                         free_a_printer_driver(driver, 3);
5796                 }       
5797
5798                 *returned+=ndrivers;
5799                 SAFE_FREE(list);
5800         }
5801
5802         /* check the required size. */
5803         for (i=0; i<*returned; i++) {
5804                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5805                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5806         }
5807
5808         if (!alloc_buffer_size(buffer, *needed)) {
5809                 SAFE_FREE(driver_info_3);
5810                 return WERR_INSUFFICIENT_BUFFER;
5811         }
5812         
5813         /* fill the buffer with the driver structures */
5814         for (i=0; i<*returned; i++) {
5815                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5816                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5817         }
5818
5819         for (i=0; i<*returned; i++)
5820                 SAFE_FREE(driver_info_3[i].dependentfiles);
5821         
5822         SAFE_FREE(driver_info_3);
5823         
5824         if (*needed > offered) {
5825                 *returned=0;
5826                 return WERR_INSUFFICIENT_BUFFER;
5827         }
5828
5829         return WERR_OK;
5830 }
5831
5832 /****************************************************************************
5833  Enumerates all printer drivers.
5834 ****************************************************************************/
5835
5836 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5837 {
5838 /*      UNISTR2 *name = &q_u->name; - notused. */
5839         UNISTR2 *environment = &q_u->environment;
5840         uint32 level = q_u->level;
5841         NEW_BUFFER *buffer = NULL;
5842         uint32 offered = q_u->offered;
5843         uint32 *needed = &r_u->needed;
5844         uint32 *returned = &r_u->returned;
5845
5846         fstring *list = NULL;
5847         fstring servername;
5848         fstring architecture;
5849
5850         /* that's an [in out] buffer */
5851         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5852         buffer = r_u->buffer;
5853
5854         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5855         fstrcpy(servername, get_called_name());
5856         *needed=0;
5857         *returned=0;
5858
5859         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5860
5861         switch (level) {
5862         case 1:
5863                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5864         case 2:
5865                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5866         case 3:
5867                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5868         default:
5869                 *returned=0;
5870                 SAFE_FREE(list);
5871                 return WERR_UNKNOWN_LEVEL;
5872         }
5873 }
5874
5875 /****************************************************************************
5876 ****************************************************************************/
5877
5878 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5879 {
5880         form->flag=list->flag;
5881         init_unistr(&form->name, list->name);
5882         form->width=list->width;
5883         form->length=list->length;
5884         form->left=list->left;
5885         form->top=list->top;
5886         form->right=list->right;
5887         form->bottom=list->bottom;      
5888 }
5889         
5890 /****************************************************************************
5891 ****************************************************************************/
5892
5893 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5894 {
5895 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5896         uint32 level = q_u->level;
5897         NEW_BUFFER *buffer = NULL;
5898         uint32 offered = q_u->offered;
5899         uint32 *needed = &r_u->needed;
5900         uint32 *numofforms = &r_u->numofforms;
5901         uint32 numbuiltinforms;
5902
5903         nt_forms_struct *list=NULL;
5904         nt_forms_struct *builtinlist=NULL;
5905         FORM_1 *forms_1;
5906         int buffer_size=0;
5907         int i;
5908
5909         /* that's an [in out] buffer */
5910         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5911         buffer = r_u->buffer;
5912
5913         DEBUG(4,("_spoolss_enumforms\n"));
5914         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5915         DEBUGADD(5,("Info level [%d]\n",          level));
5916
5917         numbuiltinforms = get_builtin_ntforms(&builtinlist);
5918         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
5919         *numofforms = get_ntforms(&list);
5920         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
5921         *numofforms += numbuiltinforms;
5922
5923         if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5924
5925         switch (level) {
5926         case 1:
5927                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5928                         *numofforms=0;
5929                         return WERR_NOMEM;
5930                 }
5931
5932                 /* construct the list of form structures */
5933                 for (i=0; i<numbuiltinforms; i++) {
5934                         DEBUGADD(6,("Filling form number [%d]\n",i));
5935                         fill_form_1(&forms_1[i], &builtinlist[i]);
5936                 }
5937                 
5938                 SAFE_FREE(builtinlist);
5939
5940                 for (; i<*numofforms; i++) {
5941                         DEBUGADD(6,("Filling form number [%d]\n",i));
5942                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5943                 }
5944                 
5945                 SAFE_FREE(list);
5946
5947                 /* check the required size. */
5948                 for (i=0; i<numbuiltinforms; i++) {
5949                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5950                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5951                 }
5952                 for (; i<*numofforms; i++) {
5953                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5954                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5955                 }
5956
5957                 *needed=buffer_size;            
5958                 
5959                 if (!alloc_buffer_size(buffer, buffer_size)){
5960                         SAFE_FREE(forms_1);
5961                         return WERR_INSUFFICIENT_BUFFER;
5962                 }
5963
5964                 /* fill the buffer with the form structures */
5965                 for (i=0; i<numbuiltinforms; i++) {
5966                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5967                         smb_io_form_1("", buffer, &forms_1[i], 0);
5968                 }
5969                 for (; i<*numofforms; i++) {
5970                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5971                         smb_io_form_1("", buffer, &forms_1[i], 0);
5972                 }
5973
5974                 SAFE_FREE(forms_1);
5975
5976                 if (*needed > offered) {
5977                         *numofforms=0;
5978                         return WERR_INSUFFICIENT_BUFFER;
5979                 }
5980                 else
5981                         return WERR_OK;
5982                         
5983         default:
5984                 SAFE_FREE(list);
5985                 SAFE_FREE(builtinlist);
5986                 return WERR_UNKNOWN_LEVEL;
5987         }
5988
5989 }
5990
5991 /****************************************************************************
5992 ****************************************************************************/
5993
5994 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5995 {
5996 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5997         uint32 level = q_u->level;
5998         UNISTR2 *uni_formname = &q_u->formname;
5999         NEW_BUFFER *buffer = NULL;
6000         uint32 offered = q_u->offered;
6001         uint32 *needed = &r_u->needed;
6002
6003         nt_forms_struct *list=NULL;
6004         nt_forms_struct builtin_form;
6005         BOOL foundBuiltin;
6006         FORM_1 form_1;
6007         fstring form_name;
6008         int buffer_size=0;
6009         int numofforms=0, i=0;
6010
6011         /* that's an [in out] buffer */
6012         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6013         buffer = r_u->buffer;
6014
6015         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6016
6017         DEBUG(4,("_spoolss_getform\n"));
6018         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6019         DEBUGADD(5,("Info level [%d]\n",          level));
6020
6021         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6022         if (!foundBuiltin) {
6023                 numofforms = get_ntforms(&list);
6024                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
6025
6026                 if (numofforms == 0)
6027                         return WERR_BADFID;
6028         }
6029
6030         switch (level) {
6031         case 1:
6032                 if (foundBuiltin) {
6033                         fill_form_1(&form_1, &builtin_form);
6034                 } else {
6035
6036                         /* Check if the requested name is in the list of form structures */
6037                         for (i=0; i<numofforms; i++) {
6038
6039                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6040
6041                                 if (strequal(form_name, list[i].name)) {
6042                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6043                                         fill_form_1(&form_1, &list[i]);
6044                                         break;
6045                                 }
6046                         }
6047                         
6048                         SAFE_FREE(list);
6049                         if (i == numofforms) {
6050                                 return WERR_BADFID;
6051                         }
6052                 }
6053                 /* check the required size. */
6054
6055                 *needed=spoolss_size_form_1(&form_1);
6056                 
6057                 if (!alloc_buffer_size(buffer, buffer_size)){
6058                         return WERR_INSUFFICIENT_BUFFER;
6059                 }
6060
6061                 if (*needed > offered) {
6062                         return WERR_INSUFFICIENT_BUFFER;
6063                 }
6064
6065                 /* fill the buffer with the form structures */
6066                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6067                 smb_io_form_1("", buffer, &form_1, 0);
6068
6069                 return WERR_OK;
6070                         
6071         default:
6072                 SAFE_FREE(list);
6073                 return WERR_UNKNOWN_LEVEL;
6074         }
6075 }
6076
6077 /****************************************************************************
6078 ****************************************************************************/
6079
6080 static void fill_port_1(PORT_INFO_1 *port, char *name)
6081 {
6082         init_unistr(&port->port_name, name);
6083 }
6084
6085 /****************************************************************************
6086 ****************************************************************************/
6087
6088 static void fill_port_2(PORT_INFO_2 *port, char *name)
6089 {
6090         init_unistr(&port->port_name, name);
6091         init_unistr(&port->monitor_name, "Local Monitor");
6092         init_unistr(&port->description, "Local Port");
6093 #define PORT_TYPE_WRITE 1
6094         port->port_type=PORT_TYPE_WRITE;
6095         port->reserved=0x0;     
6096 }
6097
6098 /****************************************************************************
6099  enumports level 1.
6100 ****************************************************************************/
6101
6102 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6103 {
6104         PORT_INFO_1 *ports=NULL;
6105         int i=0;
6106
6107         if (*lp_enumports_cmd()) {
6108                 char *cmd = lp_enumports_cmd();
6109                 char **qlines;
6110                 pstring command;
6111                 int numlines;
6112                 int ret;
6113                 int fd;
6114
6115                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6116
6117                 DEBUG(10,("Running [%s]\n", command));
6118                 ret = smbrun(command, &fd);
6119                 DEBUG(10,("Returned [%d]\n", ret));
6120                 if (ret != 0) {
6121                         if (fd != -1)
6122                                 close(fd);
6123                         /* Is this the best error to return here? */
6124                         return WERR_ACCESS_DENIED;
6125                 }
6126
6127                 numlines = 0;
6128                 qlines = fd_lines_load(fd, &numlines);
6129                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6130                 close(fd);
6131
6132                 if(numlines) {
6133                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6134                                 DEBUG(10,("Returning WERR_NOMEM [%s]\n", 
6135                                           dos_errstr(WERR_NOMEM)));
6136                                 file_lines_free(qlines);
6137                                 return WERR_NOMEM;
6138                         }
6139
6140                         for (i=0; i<numlines; i++) {
6141                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6142                                 fill_port_1(&ports[i], qlines[i]);
6143                         }
6144
6145                         file_lines_free(qlines);
6146                 }
6147
6148                 *returned = numlines;
6149
6150         } else {
6151                 *returned = 1; /* Sole Samba port returned. */
6152
6153                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6154                         return WERR_NOMEM;
6155         
6156                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6157
6158                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6159         }
6160
6161         /* check the required size. */
6162         for (i=0; i<*returned; i++) {
6163                 DEBUGADD(6,("adding port [%d]'s size\n", i));
6164                 *needed += spoolss_size_port_info_1(&ports[i]);
6165         }
6166                 
6167         if (!alloc_buffer_size(buffer, *needed)) {
6168                 SAFE_FREE(ports);
6169                 return WERR_INSUFFICIENT_BUFFER;
6170         }
6171
6172         /* fill the buffer with the ports structures */
6173         for (i=0; i<*returned; i++) {
6174                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6175                 smb_io_port_1("", buffer, &ports[i], 0);
6176         }
6177
6178         SAFE_FREE(ports);
6179
6180         if (*needed > offered) {
6181                 *returned=0;
6182                 return WERR_INSUFFICIENT_BUFFER;
6183         }
6184
6185         return WERR_OK;
6186 }
6187
6188 /****************************************************************************
6189  enumports level 2.
6190 ****************************************************************************/
6191
6192 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6193 {
6194         PORT_INFO_2 *ports=NULL;
6195         int i=0;
6196
6197         if (*lp_enumports_cmd()) {
6198                 char *cmd = lp_enumports_cmd();
6199                 char *path;
6200                 char **qlines;
6201                 pstring tmp_file;
6202                 pstring command;
6203                 int numlines;
6204                 int ret;
6205                 int fd;
6206
6207                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6208                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6209                 else
6210                         path = lp_lockdir();
6211
6212                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6213                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6214
6215                 unlink(tmp_file);
6216                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6217                 ret = smbrun(command, &fd);
6218                 DEBUGADD(10,("returned [%d]\n", ret));
6219                 if (ret != 0) {
6220                         if (fd != -1)
6221                                 close(fd);
6222                         /* Is this the best error to return here? */
6223                         return WERR_ACCESS_DENIED;
6224                 }
6225
6226                 numlines = 0;
6227                 qlines = fd_lines_load(fd, &numlines);
6228                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6229                 close(fd);
6230
6231                 if(numlines) {
6232                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6233                                 file_lines_free(qlines);
6234                                 return WERR_NOMEM;
6235                         }
6236
6237                         for (i=0; i<numlines; i++) {
6238                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6239                                 fill_port_2(&(ports[i]), qlines[i]);
6240                         }
6241
6242                         file_lines_free(qlines);
6243                 }
6244
6245                 *returned = numlines;
6246
6247         } else {
6248
6249                 *returned = 1;
6250
6251                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6252                         return WERR_NOMEM;
6253         
6254                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6255
6256                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6257         }
6258
6259         /* check the required size. */
6260         for (i=0; i<*returned; i++) {
6261                 DEBUGADD(6,("adding port [%d]'s size\n", i));
6262                 *needed += spoolss_size_port_info_2(&ports[i]);
6263         }
6264                 
6265         if (!alloc_buffer_size(buffer, *needed)) {
6266                 SAFE_FREE(ports);
6267                 return WERR_INSUFFICIENT_BUFFER;
6268         }
6269
6270         /* fill the buffer with the ports structures */
6271         for (i=0; i<*returned; i++) {
6272                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6273                 smb_io_port_2("", buffer, &ports[i], 0);
6274         }
6275
6276         SAFE_FREE(ports);
6277
6278         if (*needed > offered) {
6279                 *returned=0;
6280                 return WERR_INSUFFICIENT_BUFFER;
6281         }
6282
6283         return WERR_OK;
6284 }
6285
6286 /****************************************************************************
6287  enumports.
6288 ****************************************************************************/
6289
6290 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6291 {
6292 /*      UNISTR2 *name = &q_u->name; - notused. */
6293         uint32 level = q_u->level;
6294         NEW_BUFFER *buffer = NULL;
6295         uint32 offered = q_u->offered;
6296         uint32 *needed = &r_u->needed;
6297         uint32 *returned = &r_u->returned;
6298
6299         /* that's an [in out] buffer */
6300         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6301         buffer = r_u->buffer;
6302
6303         DEBUG(4,("_spoolss_enumports\n"));
6304         
6305         *returned=0;
6306         *needed=0;
6307         
6308         switch (level) {
6309         case 1:
6310                 return enumports_level_1(buffer, offered, needed, returned);
6311         case 2:
6312                 return enumports_level_2(buffer, offered, needed, returned);
6313         default:
6314                 return WERR_UNKNOWN_LEVEL;
6315         }
6316 }
6317
6318 /****************************************************************************
6319 ****************************************************************************/
6320
6321 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6322                                 const SPOOL_PRINTER_INFO_LEVEL *info,
6323                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6324                                 uint32 user_switch, const SPOOL_USER_CTR *user,
6325                                 POLICY_HND *handle)
6326 {
6327         NT_PRINTER_INFO_LEVEL *printer = NULL;
6328         fstring name;
6329         int     snum;
6330         WERROR err = WERR_OK;
6331
6332         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6333                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6334                 return WERR_NOMEM;
6335         }
6336
6337         ZERO_STRUCTP(printer);
6338
6339         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6340         if (!convert_printer_info(info, printer, 2)) {
6341                 free_a_printer(&printer, 2);
6342                 return WERR_NOMEM;
6343         }
6344
6345         /* check to see if the printer already exists */
6346
6347         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6348                 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n", 
6349                         printer->info_2->sharename));
6350                 free_a_printer(&printer, 2);
6351                 return WERR_PRINTER_ALREADY_EXISTS;
6352         }
6353
6354         if (*lp_addprinter_cmd() )
6355                 if ( !add_printer_hook(printer) ) {
6356                         free_a_printer(&printer,2);
6357                         return WERR_ACCESS_DENIED;
6358         }
6359
6360         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6361              printer->info_2->sharename);
6362
6363         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6364                 free_a_printer(&printer,2);
6365                 return WERR_ACCESS_DENIED;
6366         }
6367
6368         /* you must be a printer admin to add a new printer */
6369         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6370                 free_a_printer(&printer,2);
6371                 return WERR_ACCESS_DENIED;              
6372         }
6373         
6374         /*
6375          * Do sanity check on the requested changes for Samba.
6376          */
6377
6378         if (!check_printer_ok(printer->info_2, snum)) {
6379                 free_a_printer(&printer,2);
6380                 return WERR_INVALID_PARAM;
6381         }
6382
6383         /*
6384          * When a printer is created, the drivername bound to the printer is used
6385          * to lookup previously saved driver initialization info, which is then 
6386          * bound to the new printer, simulating what happens in the Windows arch.
6387          */
6388
6389         if (!devmode)
6390                 set_driver_init(printer, 2);
6391         else {
6392                 /* A valid devmode was included, convert and link it
6393                 */
6394                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6395
6396                 if (!convert_devicemode(printer->info_2->printername, devmode,
6397                                 &printer->info_2->devmode))
6398                         return  WERR_NOMEM;
6399         }
6400
6401         set_driver_init(printer, 2);
6402         
6403         /* write the ASCII on disk */
6404         err = mod_a_printer(*printer, 2);
6405         if (!W_ERROR_IS_OK(err)) {
6406                 free_a_printer(&printer,2);
6407                 return err;
6408         }
6409
6410         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6411                 /* Handle open failed - remove addition. */
6412                 del_a_printer(printer->info_2->sharename);
6413                 free_a_printer(&printer,2);
6414                 return WERR_ACCESS_DENIED;
6415         }
6416
6417         update_c_setprinter(False);
6418
6419         srv_spoolss_sendnotify(printer->info_2->printername, 0, PRINTER_CHANGE_ADD_PRINTER, 0x0);
6420
6421         free_a_printer(&printer,2);
6422
6423         return WERR_OK;
6424 }
6425
6426 /****************************************************************************
6427 ****************************************************************************/
6428
6429 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6430 {
6431         UNISTR2 *uni_srv_name = &q_u->server_name;
6432         uint32 level = q_u->level;
6433         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6434         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6435         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6436         uint32 user_switch = q_u->user_switch;
6437         SPOOL_USER_CTR *user = &q_u->user_ctr;
6438         POLICY_HND *handle = &r_u->handle;
6439
6440         switch (level) {
6441                 case 1:
6442                         /* we don't handle yet */
6443                         /* but I know what to do ... */
6444                         return WERR_UNKNOWN_LEVEL;
6445                 case 2:
6446                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6447                                                             devmode, sdb,
6448                                                             user_switch, user, handle);
6449                 default:
6450                         return WERR_UNKNOWN_LEVEL;
6451         }
6452 }
6453
6454 /****************************************************************************
6455 ****************************************************************************/
6456
6457 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6458 {
6459 /*      UNISTR2 *server_name = &q_u->server_name; - notused. */
6460         uint32 level = q_u->level;
6461         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6462         WERROR err = WERR_OK;
6463         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6464         struct current_user user;
6465         
6466         ZERO_STRUCT(driver);
6467
6468         get_current_user(&user, p);     
6469         
6470         if (!convert_printer_driver_info(info, &driver, level)) {
6471                 err = WERR_NOMEM;
6472                 goto done;
6473         }
6474
6475         DEBUG(5,("Cleaning driver's information\n"));
6476         err = clean_up_driver_struct(driver, level, &user);
6477         if (!W_ERROR_IS_OK(err))
6478                 goto done;
6479
6480         DEBUG(5,("Moving driver to final destination\n"));
6481         if(!move_driver_to_download_area(driver, level, &user, &err)) {
6482                 if (W_ERROR_IS_OK(err))
6483                         err = WERR_ACCESS_DENIED;
6484                 goto done;
6485         }
6486
6487         if (add_a_printer_driver(driver, level)!=0) {
6488                 err = WERR_ACCESS_DENIED;
6489                 goto done;
6490         }
6491
6492  done:
6493         free_a_printer_driver(driver, level);
6494         return err;
6495 }
6496
6497 /****************************************************************************
6498 ****************************************************************************/
6499
6500 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6501 {
6502         init_unistr(&info->name, name);
6503 }
6504
6505 /****************************************************************************
6506 ****************************************************************************/
6507
6508 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6509 {
6510         pstring path;
6511         pstring long_archi;
6512         pstring short_archi;
6513         DRIVER_DIRECTORY_1 *info=NULL;
6514
6515         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6516
6517         if (get_short_archi(short_archi, long_archi)==False)
6518                 return WERR_INVALID_ENVIRONMENT;
6519
6520         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6521                 return WERR_NOMEM;
6522
6523         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6524
6525         DEBUG(4,("printer driver directory: [%s]\n", path));
6526
6527         fill_driverdir_1(info, path);
6528         
6529         *needed += spoolss_size_driverdir_info_1(info);
6530
6531         if (!alloc_buffer_size(buffer, *needed)) {
6532                 SAFE_FREE(info);
6533                 return WERR_INSUFFICIENT_BUFFER;
6534         }
6535
6536         smb_io_driverdir_1("", buffer, info, 0);
6537
6538         SAFE_FREE(info);
6539         
6540         if (*needed > offered)
6541                 return WERR_INSUFFICIENT_BUFFER;
6542
6543         return WERR_OK;
6544 }
6545
6546 /****************************************************************************
6547 ****************************************************************************/
6548
6549 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6550 {
6551         UNISTR2 *name = &q_u->name;
6552         UNISTR2 *uni_environment = &q_u->environment;
6553         uint32 level = q_u->level;
6554         NEW_BUFFER *buffer = NULL;
6555         uint32 offered = q_u->offered;
6556         uint32 *needed = &r_u->needed;
6557
6558         /* that's an [in out] buffer */
6559         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6560         buffer = r_u->buffer;
6561
6562         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6563
6564         *needed=0;
6565
6566         switch(level) {
6567         case 1:
6568                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6569         default:
6570                 return WERR_UNKNOWN_LEVEL;
6571         }
6572 }
6573         
6574 /****************************************************************************
6575 ****************************************************************************/
6576
6577 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6578 {
6579         POLICY_HND *handle = &q_u->handle;
6580         uint32 idx = q_u->index;
6581         uint32 in_value_len = q_u->valuesize;
6582         uint32 in_data_len = q_u->datasize;
6583         uint32 *out_max_value_len = &r_u->valuesize;
6584         uint16 **out_value = &r_u->value;
6585         uint32 *out_value_len = &r_u->realvaluesize;
6586         uint32 *out_type = &r_u->type;
6587         uint32 *out_max_data_len = &r_u->datasize;
6588         uint8  **data_out = &r_u->data;
6589         uint32 *out_data_len = &r_u->realdatasize;
6590
6591         NT_PRINTER_INFO_LEVEL *printer = NULL;
6592         
6593         fstring value;
6594         
6595         uint32 param_index;
6596         uint32 biggest_valuesize;
6597         uint32 biggest_datasize;
6598         uint32 data_len;
6599         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6600         int snum;
6601         uint8 *data=NULL;
6602         uint32 type;
6603         WERROR result;
6604
6605         ZERO_STRUCT(printer);
6606         
6607         *out_type=0;
6608
6609         *out_max_data_len=0;
6610         *data_out=NULL;
6611         *out_data_len=0;
6612
6613         DEBUG(5,("spoolss_enumprinterdata\n"));
6614
6615         if (!Printer) {
6616                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6617                 return WERR_BADFID;
6618         }
6619
6620         if (!get_printer_snum(p,handle, &snum))
6621                 return WERR_BADFID;
6622         
6623         result = get_a_printer(&printer, 2, lp_servicename(snum));
6624         if (!W_ERROR_IS_OK(result))
6625                 return result;
6626
6627         /*
6628          * The NT machine wants to know the biggest size of value and data
6629          *
6630          * cf: MSDN EnumPrinterData remark section
6631          */
6632         if ( (in_value_len==0) && (in_data_len==0) ) {
6633                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6634
6635 #if 0
6636                 /*
6637                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6638                  * if this parameter size doesn't exist.
6639                  * Ok - my opinion here is that the client is not asking for the greatest
6640                  * possible size of all the parameters, but is asking specifically for the size needed
6641                  * for this specific parameter. In that case we can remove the loop below and
6642                  * simplify this lookup code considerably. JF - comments welcome. JRA.
6643                  */
6644
6645                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6646                         SAFE_FREE(data);
6647                         free_a_printer(&printer, 2);
6648                         return WERR_NO_MORE_ITEMS;
6649                 }
6650 #endif
6651
6652                 SAFE_FREE(data);
6653
6654                 param_index=0;
6655                 biggest_valuesize=0;
6656                 biggest_datasize=0;
6657                 
6658                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6659                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6660                         if (data_len > biggest_datasize) biggest_datasize=data_len;
6661
6662                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6663
6664                         SAFE_FREE(data);
6665                         param_index++;
6666                 }
6667
6668                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6669                 *out_value_len=2*(1+biggest_valuesize);
6670                 *out_data_len=biggest_datasize;
6671
6672                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6673
6674                 free_a_printer(&printer, 2);
6675                 return WERR_OK;
6676         }
6677         
6678         /*
6679          * the value len is wrong in NT sp3
6680          * that's the number of bytes not the number of unicode chars
6681          */
6682
6683         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6684
6685                 SAFE_FREE(data);
6686                 free_a_printer(&printer, 2);
6687
6688                 /* out_value should default to "" or else NT4 has
6689                    problems unmarshalling the response */
6690
6691                 *out_max_value_len=(in_value_len/sizeof(uint16));
6692                 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
6693                         return WERR_NOMEM;
6694
6695                 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6696
6697                 /* the data is counted in bytes */
6698                 *out_max_data_len = in_data_len;
6699                 *out_data_len = in_data_len;
6700                 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
6701                         return WERR_NOMEM;
6702
6703                 return WERR_NO_MORE_ITEMS;
6704         }
6705
6706         free_a_printer(&printer, 2);
6707
6708         /*
6709          * the value is:
6710          * - counted in bytes in the request
6711          * - counted in UNICODE chars in the max reply
6712          * - counted in bytes in the real size
6713          *
6714          * take a pause *before* coding not *during* coding
6715          */
6716         
6717         *out_max_value_len=(in_value_len/sizeof(uint16));
6718         if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6719                 SAFE_FREE(data);
6720                 return WERR_NOMEM;
6721         }
6722         
6723         *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6724
6725         *out_type=type;
6726
6727         /* the data is counted in bytes */
6728         *out_max_data_len=in_data_len;
6729         if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6730                 SAFE_FREE(data);
6731                 return WERR_NOMEM;
6732         }
6733         
6734         memcpy(*data_out, data, (size_t)data_len);
6735         *out_data_len=data_len;
6736
6737         SAFE_FREE(data);
6738         
6739         return WERR_OK;
6740 }
6741
6742 /****************************************************************************
6743 ****************************************************************************/
6744
6745 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6746 {
6747         POLICY_HND *handle = &q_u->handle;
6748         UNISTR2 *value = &q_u->value;
6749         uint32 type = q_u->type;
6750 /*      uint32 max_len = q_u->max_len; - notused. */
6751         uint8 *data = q_u->data;
6752         uint32 real_len = q_u->real_len;
6753 /*      uint32 numeric_data = q_u->numeric_data; - notused. */
6754
6755         NT_PRINTER_INFO_LEVEL *printer = NULL;
6756         NT_PRINTER_PARAM *param = NULL, old_param;
6757         int snum=0;
6758         WERROR status = WERR_OK;
6759         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6760         
6761         DEBUG(5,("spoolss_setprinterdata\n"));
6762
6763         if (!Printer) {
6764                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6765                 return WERR_BADFID;
6766         }
6767
6768         if (!get_printer_snum(p,handle, &snum))
6769                 return WERR_BADFID;
6770
6771         ZERO_STRUCT(old_param);
6772
6773         /* 
6774          * Access check : NT returns "access denied" if you make a 
6775          * SetPrinterData call without the necessary privildge.
6776          * we were originally returning OK if nothing changed
6777          * which made Win2k issue **a lot** of SetPrinterData
6778          * when connecting to a printer  --jerry
6779          */
6780
6781         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6782                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
6783                 status = WERR_ACCESS_DENIED;
6784                 goto done;
6785         }
6786
6787         /* Check if we are making any changes or not.  Return true if
6788            nothing is actually changing.  This is not needed anymore but
6789            has been left in as an optimization to keep from from
6790            writing to disk as often  --jerry  */
6791
6792         status = get_a_printer(&printer, 2, lp_servicename(snum));
6793         if (!W_ERROR_IS_OK(status))
6794                 return status;
6795
6796         convert_specific_param(&param, value , type, data, real_len);
6797
6798         unlink_specific_param_if_exist(printer->info_2, param);
6799         
6800         /*
6801          * When client side code sets a magic printer data key, detect it and save
6802          * the current printer data and the magic key's data (its the DEVMODE) for
6803          * future printer/driver initializations.
6804          */
6805         if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6806                 /*
6807                  * Set devmode and printer initialization info
6808                  */
6809                 status = save_driver_init(printer, 2, param);
6810         }
6811         else {
6812                 add_a_specific_param(printer->info_2, &param);
6813                 status = mod_a_printer(*printer, 2);
6814         }
6815
6816  done:
6817         free_a_printer(&printer, 2);
6818         if (param)
6819                 free_nt_printer_param(&param);
6820         SAFE_FREE(old_param.data);
6821
6822         return status;
6823 }
6824
6825 /****************************************************************************
6826 ****************************************************************************/
6827
6828 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
6829 {
6830         POLICY_HND *handle = &q_u->handle;
6831         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6832         int snum;
6833         
6834         DEBUG(5,("_spoolss_resetprinter\n"));
6835
6836         /*
6837          * All we do is to check to see if the handle and queue is valid.
6838          * This call really doesn't mean anything to us because we only
6839          * support RAW printing.   --jerry
6840          */
6841          
6842         if (!Printer) {
6843                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6844                 return WERR_BADFID;
6845         }
6846
6847         if (!get_printer_snum(p,handle, &snum))
6848                 return WERR_BADFID;
6849
6850
6851         /* blindly return success */    
6852         return WERR_OK;
6853 }
6854
6855
6856 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6857 {
6858         POLICY_HND *handle = &q_u->handle;
6859         UNISTR2 *value = &q_u->valuename;
6860
6861         NT_PRINTER_INFO_LEVEL *printer = NULL;
6862         NT_PRINTER_PARAM param;
6863         int snum=0;
6864         WERROR status = WERR_OK;
6865         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6866         
6867         DEBUG(5,("spoolss_deleteprinterdata\n"));
6868         
6869         if (!Printer) {
6870                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6871                 return WERR_BADFID;
6872         }
6873
6874         if (!get_printer_snum(p, handle, &snum))
6875                 return WERR_BADFID;
6876
6877         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6878                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
6879                 return WERR_ACCESS_DENIED;
6880         }
6881
6882         status = get_a_printer(&printer, 2, lp_servicename(snum));
6883         if (!W_ERROR_IS_OK(status))
6884                 return status;
6885
6886         ZERO_STRUCTP(&param);
6887         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6888
6889         if(!unlink_specific_param_if_exist(printer->info_2, &param))
6890                 status = WERR_INVALID_PARAM;
6891         else
6892                 status = mod_a_printer(*printer, 2);
6893
6894         free_a_printer(&printer, 2);
6895         return status;
6896 }
6897
6898 /****************************************************************************
6899 ****************************************************************************/
6900
6901 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6902 {
6903         POLICY_HND *handle = &q_u->handle;
6904 /*      uint32 level = q_u->level; - notused. */
6905         FORM *form = &q_u->form;
6906         nt_forms_struct tmpForm;
6907         int snum;
6908         WERROR status = WERR_OK;
6909         NT_PRINTER_INFO_LEVEL *printer = NULL;
6910
6911         int count=0;
6912         nt_forms_struct *list=NULL;
6913         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6914
6915         DEBUG(5,("spoolss_addform\n"));
6916
6917         if (!Printer) {
6918                 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6919                 return WERR_BADFID;
6920         }
6921
6922         if (!get_printer_snum(p,handle, &snum))
6923                 return WERR_BADFID;
6924
6925         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6926                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
6927                 status = WERR_ACCESS_DENIED;
6928                 goto done;
6929         }
6930                 
6931         /* can't add if builtin */
6932         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6933                 return WERR_ALREADY_EXISTS;
6934         }
6935
6936         count=get_ntforms(&list);
6937         if(!add_a_form(&list, form, &count))
6938                 return WERR_NOMEM;
6939         write_ntforms(&list, count);
6940         
6941         /*
6942          * ChangeID must always be set
6943          */
6944          
6945         status = get_a_printer(&printer, 2, lp_servicename(snum));
6946         if (!W_ERROR_IS_OK(status))
6947                 goto done;
6948         
6949         status = mod_a_printer(*printer, 2);
6950         if (!W_ERROR_IS_OK(status))
6951                 goto done;
6952         
6953 done:
6954         free_a_printer(&printer, 2);
6955         SAFE_FREE(list);
6956
6957         return status;
6958 }
6959
6960 /****************************************************************************
6961 ****************************************************************************/
6962
6963 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6964 {
6965         POLICY_HND *handle = &q_u->handle;
6966         UNISTR2 *form_name = &q_u->name;
6967         nt_forms_struct tmpForm;
6968         int count=0;
6969         WERROR ret = WERR_OK;
6970         nt_forms_struct *list=NULL;
6971         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6972         int snum;
6973         WERROR status = WERR_OK;
6974         NT_PRINTER_INFO_LEVEL *printer = NULL;
6975
6976         DEBUG(5,("spoolss_deleteform\n"));
6977
6978         if (!Printer) {
6979                 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6980                 return WERR_BADFID;
6981         }
6982
6983         if (!get_printer_snum(p, handle, &snum))
6984                 return WERR_BADFID;
6985
6986         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6987                 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
6988                 return WERR_ACCESS_DENIED;
6989         }
6990
6991         /* can't delete if builtin */
6992         if (get_a_builtin_ntform(form_name,&tmpForm)) {
6993                 return WERR_INVALID_PARAM;
6994         }
6995
6996         count = get_ntforms(&list);
6997         if(!delete_a_form(&list, form_name, &count, &ret))
6998                 return WERR_INVALID_PARAM;
6999
7000         /*
7001          * ChangeID must always be set
7002          */
7003          
7004         status = get_a_printer(&printer, 2, lp_servicename(snum));
7005         if (!W_ERROR_IS_OK(status))
7006                 goto done;
7007         
7008         status = mod_a_printer(*printer, 2);
7009         if (!W_ERROR_IS_OK(status))
7010                 goto done;
7011         
7012 done:
7013         free_a_printer(&printer, 2);
7014         SAFE_FREE(list);
7015
7016         return ret;
7017 }
7018
7019 /****************************************************************************
7020 ****************************************************************************/
7021
7022 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7023 {
7024         POLICY_HND *handle = &q_u->handle;
7025 /*      UNISTR2 *uni_name = &q_u->name; - notused. */
7026 /*      uint32 level = q_u->level; - notused. */
7027         FORM *form = &q_u->form;
7028         nt_forms_struct tmpForm;
7029         int snum;
7030         WERROR status = WERR_OK;
7031         NT_PRINTER_INFO_LEVEL *printer = NULL;
7032
7033         int count=0;
7034         nt_forms_struct *list=NULL;
7035         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7036
7037         DEBUG(5,("spoolss_setform\n"));
7038
7039         if (!Printer) {
7040                 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7041                 return WERR_BADFID;
7042         }
7043
7044         if (!get_printer_snum(p, handle, &snum))
7045                 return WERR_BADFID;
7046
7047         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7048                 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7049                 return WERR_ACCESS_DENIED;
7050         }
7051
7052         /* can't set if builtin */
7053         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7054                 return WERR_INVALID_PARAM;
7055         }
7056
7057         count=get_ntforms(&list);
7058         update_a_form(&list, form, count);
7059         write_ntforms(&list, count);
7060
7061         /*
7062          * ChangeID must always be set
7063          */
7064          
7065         status = get_a_printer(&printer, 2, lp_servicename(snum));
7066         if (!W_ERROR_IS_OK(status))
7067                 goto done;
7068         
7069         status = mod_a_printer(*printer, 2);
7070         if (!W_ERROR_IS_OK(status))
7071                 goto done;
7072         
7073 done:
7074         free_a_printer(&printer, 2);
7075         SAFE_FREE(list);
7076
7077         return WERR_OK;
7078 }
7079
7080 /****************************************************************************
7081  enumprintprocessors level 1.
7082 ****************************************************************************/
7083
7084 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7085 {
7086         PRINTPROCESSOR_1 *info_1=NULL;
7087         
7088         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7089                 return WERR_NOMEM;
7090
7091         (*returned) = 0x1;
7092         
7093         init_unistr(&info_1->name, "winprint");
7094
7095         *needed += spoolss_size_printprocessor_info_1(info_1);
7096
7097         if (!alloc_buffer_size(buffer, *needed))
7098                 return WERR_INSUFFICIENT_BUFFER;
7099
7100         smb_io_printprocessor_info_1("", buffer, info_1, 0);
7101
7102         SAFE_FREE(info_1);
7103
7104         if (*needed > offered) {
7105                 *returned=0;
7106                 return WERR_INSUFFICIENT_BUFFER;
7107         }
7108
7109         return WERR_OK;
7110 }
7111
7112 /****************************************************************************
7113 ****************************************************************************/
7114
7115 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7116 {
7117 /*      UNISTR2 *name = &q_u->name; - notused. */
7118 /*      UNISTR2 *environment = &q_u->environment; - notused. */
7119         uint32 level = q_u->level;
7120     NEW_BUFFER *buffer = NULL;
7121         uint32 offered = q_u->offered;
7122     uint32 *needed = &r_u->needed;
7123         uint32 *returned = &r_u->returned;
7124
7125         /* that's an [in out] buffer */
7126         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7127         buffer = r_u->buffer;
7128
7129         DEBUG(5,("spoolss_enumprintprocessors\n"));
7130
7131         /*
7132          * Enumerate the print processors ...
7133          *
7134          * Just reply with "winprint", to keep NT happy
7135          * and I can use my nice printer checker.
7136          */
7137         
7138         *returned=0;
7139         *needed=0;
7140         
7141         switch (level) {
7142         case 1:
7143                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7144         default:
7145                 return WERR_UNKNOWN_LEVEL;
7146         }
7147 }
7148
7149 /****************************************************************************
7150  enumprintprocdatatypes level 1.
7151 ****************************************************************************/
7152
7153 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7154 {
7155         PRINTPROCDATATYPE_1 *info_1=NULL;
7156         
7157         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7158                 return WERR_NOMEM;
7159
7160         (*returned) = 0x1;
7161         
7162         init_unistr(&info_1->name, "RAW");
7163
7164         *needed += spoolss_size_printprocdatatype_info_1(info_1);
7165
7166         if (!alloc_buffer_size(buffer, *needed))
7167                 return WERR_INSUFFICIENT_BUFFER;
7168
7169         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7170
7171         SAFE_FREE(info_1);
7172
7173         if (*needed > offered) {
7174                 *returned=0;
7175                 return WERR_INSUFFICIENT_BUFFER;
7176         }
7177
7178         return WERR_OK;
7179 }
7180
7181 /****************************************************************************
7182 ****************************************************************************/
7183
7184 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7185 {
7186 /*      UNISTR2 *name = &q_u->name; - notused. */
7187 /*      UNISTR2 *processor = &q_u->processor; - notused. */
7188         uint32 level = q_u->level;
7189         NEW_BUFFER *buffer = NULL;
7190         uint32 offered = q_u->offered;
7191         uint32 *needed = &r_u->needed;
7192         uint32 *returned = &r_u->returned;
7193
7194         /* that's an [in out] buffer */
7195         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7196         buffer = r_u->buffer;
7197
7198         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7199         
7200         *returned=0;
7201         *needed=0;
7202         
7203         switch (level) {
7204         case 1:
7205                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7206         default:
7207                 return WERR_UNKNOWN_LEVEL;
7208         }
7209 }
7210
7211 /****************************************************************************
7212  enumprintmonitors level 1.
7213 ****************************************************************************/
7214
7215 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7216 {
7217         PRINTMONITOR_1 *info_1=NULL;
7218         
7219         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7220                 return WERR_NOMEM;
7221
7222         (*returned) = 0x1;
7223         
7224         init_unistr(&info_1->name, "Local Port");
7225
7226         *needed += spoolss_size_printmonitor_info_1(info_1);
7227
7228         if (!alloc_buffer_size(buffer, *needed))
7229                 return WERR_INSUFFICIENT_BUFFER;
7230
7231         smb_io_printmonitor_info_1("", buffer, info_1, 0);
7232
7233         SAFE_FREE(info_1);
7234
7235         if (*needed > offered) {
7236                 *returned=0;
7237                 return WERR_INSUFFICIENT_BUFFER;
7238         }
7239
7240         return WERR_OK;
7241 }
7242
7243 /****************************************************************************
7244  enumprintmonitors level 2.
7245 ****************************************************************************/
7246
7247 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7248 {
7249         PRINTMONITOR_2 *info_2=NULL;
7250         
7251         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7252                 return WERR_NOMEM;
7253
7254         (*returned) = 0x1;
7255         
7256         init_unistr(&info_2->name, "Local Port");
7257         init_unistr(&info_2->environment, "Windows NT X86");
7258         init_unistr(&info_2->dll_name, "localmon.dll");
7259
7260         *needed += spoolss_size_printmonitor_info_2(info_2);
7261
7262         if (!alloc_buffer_size(buffer, *needed))
7263                 return WERR_INSUFFICIENT_BUFFER;
7264
7265         smb_io_printmonitor_info_2("", buffer, info_2, 0);
7266
7267         SAFE_FREE(info_2);
7268
7269         if (*needed > offered) {
7270                 *returned=0;
7271                 return WERR_INSUFFICIENT_BUFFER;
7272         }
7273
7274         return WERR_OK;
7275 }
7276
7277 /****************************************************************************
7278 ****************************************************************************/
7279
7280 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7281 {
7282 /*      UNISTR2 *name = &q_u->name; - notused. */
7283         uint32 level = q_u->level;
7284     NEW_BUFFER *buffer = NULL;
7285         uint32 offered = q_u->offered;
7286     uint32 *needed = &r_u->needed;
7287         uint32 *returned = &r_u->returned;
7288
7289         /* that's an [in out] buffer */
7290         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7291         buffer = r_u->buffer;
7292
7293         DEBUG(5,("spoolss_enumprintmonitors\n"));
7294
7295         /*
7296          * Enumerate the print monitors ...
7297          *
7298          * Just reply with "Local Port", to keep NT happy
7299          * and I can use my nice printer checker.
7300          */
7301         
7302         *returned=0;
7303         *needed=0;
7304         
7305         switch (level) {
7306         case 1:
7307                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7308         case 2:
7309                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7310         default:
7311                 return WERR_UNKNOWN_LEVEL;
7312         }
7313 }
7314
7315 /****************************************************************************
7316 ****************************************************************************/
7317
7318 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7319 {
7320         int i=0;
7321         BOOL found=False;
7322         JOB_INFO_1 *info_1=NULL;
7323
7324         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7325
7326         if (info_1 == NULL) {
7327                 SAFE_FREE(queue);
7328                 return WERR_NOMEM;
7329         }
7330                 
7331         for (i=0; i<count && found==False; i++) {
7332                 if (queue[i].job==(int)jobid)
7333                         found=True;
7334         }
7335         
7336         if (found==False) {
7337                 SAFE_FREE(queue);
7338                 SAFE_FREE(info_1);
7339                 /* NT treats not found as bad param... yet another bad choice */
7340                 return WERR_INVALID_PARAM;
7341         }
7342         
7343         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7344         
7345         SAFE_FREE(queue);
7346         
7347         *needed += spoolss_size_job_info_1(info_1);
7348
7349         if (!alloc_buffer_size(buffer, *needed)) {
7350                 SAFE_FREE(info_1);
7351                 return WERR_INSUFFICIENT_BUFFER;
7352         }
7353
7354         smb_io_job_info_1("", buffer, info_1, 0);
7355
7356         SAFE_FREE(info_1);
7357
7358         if (*needed > offered)
7359                 return WERR_INSUFFICIENT_BUFFER;
7360
7361         return WERR_OK;
7362 }
7363
7364 /****************************************************************************
7365 ****************************************************************************/
7366
7367 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7368 {
7369         int i=0;
7370         BOOL found=False;
7371         JOB_INFO_2 *info_2;
7372         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7373         WERROR ret;
7374         DEVICEMODE *devmode = NULL;
7375
7376         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7377
7378         ZERO_STRUCTP(info_2);
7379
7380         if (info_2 == NULL) {
7381                 ret = WERR_NOMEM;
7382                 goto done;
7383         }
7384
7385         for (i=0; i<count && found==False; i++) {
7386                 if (queue[i].job==(int)jobid)
7387                         found=True;
7388         }
7389         
7390         if (found==False) {
7391                 /* NT treats not found as bad param... yet another bad
7392                    choice */
7393                 ret = WERR_INVALID_PARAM;
7394                 goto done;
7395         }
7396         
7397         ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7398         if (!W_ERROR_IS_OK(ret))
7399                 goto done;
7400         if (construct_dev_mode(snum) == NULL) {
7401                 ret = WERR_NOMEM;
7402                 goto done;
7403         }
7404
7405         fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7406         
7407         *needed += spoolss_size_job_info_2(info_2);
7408
7409         if (!alloc_buffer_size(buffer, *needed)) {
7410                 ret = WERR_INSUFFICIENT_BUFFER;
7411                 goto done;
7412         }
7413
7414         smb_io_job_info_2("", buffer, info_2, 0);
7415
7416         if (*needed > offered) {
7417                 ret = WERR_INSUFFICIENT_BUFFER;
7418                 goto done;
7419         }
7420
7421         ret = WERR_OK;
7422         
7423  done:
7424         /* Cleanup allocated memory */
7425
7426         SAFE_FREE(queue);
7427         free_job_info_2(info_2);        /* Also frees devmode */
7428         SAFE_FREE(info_2);
7429         free_a_printer(&ntprinter, 2);
7430         
7431         return ret;
7432 }
7433
7434 /****************************************************************************
7435 ****************************************************************************/
7436
7437 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7438 {
7439         POLICY_HND *handle = &q_u->handle;
7440         uint32 jobid = q_u->jobid;
7441         uint32 level = q_u->level;
7442         NEW_BUFFER *buffer = NULL;
7443         uint32 offered = q_u->offered;
7444         uint32 *needed = &r_u->needed;
7445
7446         int snum;
7447         int count;
7448         print_queue_struct *queue=NULL;
7449         print_status_struct prt_status;
7450
7451         /* that's an [in out] buffer */
7452         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7453         buffer = r_u->buffer;
7454
7455         DEBUG(5,("spoolss_getjob\n"));
7456         
7457         *needed=0;
7458         
7459         if (!get_printer_snum(p, handle, &snum))
7460                 return WERR_BADFID;
7461         
7462         count = print_queue_status(snum, &queue, &prt_status);
7463         
7464         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7465                      count, prt_status.status, prt_status.message));
7466                 
7467         switch (level) {
7468         case 1:
7469                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7470         case 2:
7471                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7472         default:
7473                 SAFE_FREE(queue);
7474                 return WERR_UNKNOWN_LEVEL;
7475         }
7476 }
7477
7478 /********************************************************************
7479  * spoolss_getprinterdataex
7480  ********************************************************************/
7481
7482 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7483 {
7484         POLICY_HND      *handle = &q_u->handle;
7485         uint32          in_size = q_u->size;
7486         uint32          *type = &r_u->type;
7487         uint32          *out_size = &r_u->size;
7488         uint8           **data = &r_u->data;
7489         uint32          *needed = &r_u->needed;
7490
7491         fstring         key, value;
7492         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7493         BOOL            found = False;
7494
7495         DEBUG(4,("_spoolss_getprinterdataex\n"));
7496
7497         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7498         unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7499
7500         /* in case of problem, return some default values */
7501         *needed=0;
7502         *type=0;
7503         *out_size=0;
7504
7505                 
7506         if (!Printer) {
7507                 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7508                         return WERR_NOMEM;
7509                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7510                 return WERR_BADFID;
7511         }
7512
7513                 
7514         /* Is the handle to a printer or to the server? */
7515
7516         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7517         {
7518                 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7519                 return WERR_INVALID_PARAM;
7520         }
7521         else
7522         {
7523                 /* 
7524                  * From MSDN documentation of GetPrinterDataEx: pass request
7525                  * to GetPrinterData if key is "PrinterDriverData". This is 
7526                  * the only key we really support. Other keys to implement:
7527                  * (a) DsDriver
7528                  * (b) DsSpooler
7529                  * (c) PnPData
7530                  */
7531            
7532                 if (strcmp(key, "PrinterDriverData") != 0)
7533                         return WERR_BADFILE;
7534
7535                 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7536                 found = getprinterdata_printer(p, p->mem_ctx, handle, value, 
7537                         type, data, needed, in_size);
7538                 
7539         }
7540          
7541         if (!found) {
7542                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7543                 
7544                 /* reply this param doesn't exist */
7545                 if (*out_size) {
7546                         if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7547                                 return WERR_NOMEM;
7548                 } else {
7549                         *data = NULL;
7550                 }
7551
7552                 return WERR_INVALID_PARAM;
7553         }
7554         
7555         if (*needed > *out_size)
7556                 return WERR_MORE_DATA;
7557         else
7558                 return WERR_OK;
7559 }
7560
7561 /********************************************************************
7562  * spoolss_setprinterdata
7563  ********************************************************************/
7564
7565 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7566 {
7567         SPOOL_Q_SETPRINTERDATA q_u_local;
7568         SPOOL_R_SETPRINTERDATA r_u_local;
7569         fstring key;
7570
7571         DEBUG(4,("_spoolss_setprinterdataex\n"));
7572
7573         /* From MSDN documentation of SetPrinterDataEx: pass request to
7574            SetPrinterData if key is "PrinterDriverData" */
7575
7576         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7577
7578         if (strcmp(key, "PrinterDriverData") != 0)
7579                 return WERR_INVALID_PARAM;
7580                 
7581         ZERO_STRUCT(q_u_local); 
7582         ZERO_STRUCT(r_u_local); 
7583         
7584         /* make a copy to call _spoolss_setprinterdata() */
7585
7586         memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7587         copy_unistr2(&q_u_local.value, &q_u->value);
7588         q_u_local.type = q_u->type;
7589         q_u_local.max_len = q_u->max_len;
7590         q_u_local.data = q_u->data;
7591         q_u_local.real_len = q_u->real_len;
7592         q_u_local.numeric_data = q_u->numeric_data;
7593                 
7594         return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7595 }
7596
7597 /********************************************************************
7598  * spoolss_enumprinterkey
7599  ********************************************************************/
7600
7601 /* constants for EnumPrinterKey() */
7602 #define ENUMERATED_KEY_SIZE     19
7603
7604 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7605 {
7606         fstring key;
7607         uint16  enumkeys[ENUMERATED_KEY_SIZE+1];
7608         char*   ptr = NULL;
7609         int     i;
7610         char    *PrinterKey = "PrinterDriverData";
7611
7612         DEBUG(4,("_spoolss_enumprinterkey\n"));
7613
7614         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7615
7616         /* 
7617          * we only support enumating all keys (key == "")
7618          * Of course, the only key we support is the "PrinterDriverData" 
7619          * key
7620          */     
7621         if (strlen(key) == 0)
7622         {
7623                 r_u->needed = ENUMERATED_KEY_SIZE *2;
7624                 if (q_u->size < r_u->needed)
7625                         return WERR_MORE_DATA;
7626         
7627                 ptr = PrinterKey;
7628                 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7629                 {
7630                         enumkeys[i] = (uint16)(*ptr);
7631                         ptr++;
7632                 }
7633
7634                 /* tag of with 2 '\0's */
7635                 enumkeys[i++] = '\0';
7636                 enumkeys[i] = '\0';
7637         
7638                 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7639                         return WERR_BADFILE;
7640                         
7641                 return WERR_OK;
7642         }
7643         
7644         /* The "PrinterDriverData" key should have no subkeys */
7645         if (strcmp(key, PrinterKey) == 0)
7646         {
7647                 r_u-> needed = 2;
7648                 if (q_u->size < r_u->needed)
7649                         return WERR_MORE_DATA;
7650                 enumkeys[0] = 0x0;
7651                 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7652                         return WERR_BADFILE;
7653                         
7654                 return WERR_OK;
7655         }
7656         
7657
7658         /* The return value for an unknown key is documented in MSDN
7659            EnumPrinterKey description */
7660         return WERR_BADFILE;
7661 }
7662
7663 /********************************************************************
7664  * spoolss_enumprinterdataex
7665  ********************************************************************/
7666
7667 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7668 {
7669         POLICY_HND      *handle = &q_u->handle; 
7670         uint32          in_size = q_u->size;
7671         uint32          num_entries, 
7672                         needed;
7673         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7674         PRINTER_ENUM_VALUES     *enum_values = NULL;
7675         fstring         key, value;
7676         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7677         int             snum;
7678         uint32          param_index, 
7679                         data_len,
7680                         type;
7681         WERROR          result;
7682         uint8           *data=NULL;
7683         
7684
7685         DEBUG(4,("_spoolss_enumprinterdataex\n"));
7686
7687         if (!Printer) {
7688                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
7689                 return WERR_BADFID;
7690         }
7691
7692                 
7693         /* 
7694          * The only key we support is "PrinterDriverData". This should return 
7695          > an array of all the key/value pairs returned by EnumPrinterDataSee 
7696          * _spoolss_getprinterdataex() for details    --jerry
7697          */
7698    
7699         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7700         if (strcmp(key, "PrinterDriverData") != 0)
7701         {
7702                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7703                 return WERR_INVALID_PARAM;
7704         }
7705
7706
7707         if (!get_printer_snum(p,handle, &snum))
7708                 return WERR_BADFID;
7709         
7710         ZERO_STRUCT(printer);
7711         result = get_a_printer(&printer, 2, lp_servicename(snum));
7712         if (!W_ERROR_IS_OK(result))
7713                 return result;
7714
7715         
7716         /* 
7717          * loop through all params and build the array to pass 
7718          * back to the  client 
7719          */
7720         result = WERR_OK;
7721         param_index             = 0;
7722         needed                  = 0;
7723         num_entries             = 0;
7724         
7725         while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) 
7726         {
7727                 PRINTER_ENUM_VALUES     *ptr;
7728                 uint32                  add_len = 0;
7729
7730                 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7731
7732                 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7733                 {
7734                         DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7735                         result = WERR_NOMEM;
7736                         goto done;
7737                 }
7738                 enum_values = ptr;
7739
7740                 /* copy the data */
7741                 init_unistr(&enum_values[num_entries].valuename, value);
7742                 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7743                 enum_values[num_entries].type      = type;
7744                 
7745                 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7746                         DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7747                         result = WERR_NOMEM;
7748                         goto done;
7749                 }
7750                 memcpy(enum_values[num_entries].data, data, data_len);
7751                 enum_values[num_entries].data_len = data_len + add_len;
7752
7753                 /* keep track of the size of the array in bytes */
7754                 
7755                 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7756                 
7757                 num_entries++;
7758                 param_index++;
7759         }
7760         
7761         r_u->needed             = needed;
7762         r_u->returned           = num_entries;
7763
7764         if (needed > in_size) {
7765                 result = WERR_MORE_DATA;
7766                 goto done;
7767         }
7768                 
7769         /* copy data into the reply */
7770         
7771         r_u->ctr.size           = r_u->needed;
7772         r_u->ctr.size_of_array  = r_u->returned;
7773         r_u->ctr.values         = enum_values;
7774         
7775         
7776                 
7777 done:   
7778         free_a_printer(&printer, 2);
7779
7780         return result;
7781 }
7782
7783 /****************************************************************************
7784 ****************************************************************************/
7785
7786 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7787 {
7788         init_unistr(&info->name, name);
7789 }
7790
7791 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
7792                                                  UNISTR2 *environment, 
7793                                                  NEW_BUFFER *buffer, 
7794                                                  uint32 offered, 
7795                                                  uint32 *needed)
7796 {
7797         pstring path;
7798         pstring long_archi;
7799         pstring short_archi;
7800         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7801
7802         unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7803
7804         if (get_short_archi(short_archi, long_archi)==FALSE)
7805                 return WERR_INVALID_ENVIRONMENT;
7806
7807         if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7808                 return WERR_NOMEM;
7809
7810         pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
7811
7812         fill_printprocessordirectory_1(info, path);
7813         
7814         *needed += spoolss_size_printprocessordirectory_info_1(info);
7815
7816         if (!alloc_buffer_size(buffer, *needed)) {
7817                 safe_free(info);
7818                 return WERR_INSUFFICIENT_BUFFER;
7819         }
7820
7821         smb_io_printprocessordirectory_1("", buffer, info, 0);
7822
7823         safe_free(info);
7824         
7825         if (*needed > offered)
7826                 return WERR_INSUFFICIENT_BUFFER;
7827         else
7828                 return WERR_OK;
7829 }
7830
7831 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7832 {
7833         uint32 level = q_u->level;
7834         NEW_BUFFER *buffer = NULL;
7835         uint32 offered = q_u->offered;
7836         uint32 *needed = &r_u->needed;
7837
7838         /* that's an [in out] buffer */
7839         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7840         buffer = r_u->buffer;
7841
7842         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7843         
7844         *needed=0;
7845
7846         switch(level) {
7847         case 1:
7848                 return getprintprocessordirectory_level_1
7849                   (&q_u->name, &q_u->environment, buffer, offered, needed);
7850         default:
7851                 return WERR_UNKNOWN_LEVEL;
7852         }
7853
7854         return WERR_ACCESS_DENIED;
7855 }
7856