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