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