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