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