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