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