More printf portability fixes. Got caught out by some gcc'isms last
[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-2003,
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         ubi_dlNode Next;
68         ubi_dlNode Prev;
69         
70         int snum;
71         uint32 counter;
72 } counter_printer_0;
73
74 static ubi_dlList 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_PRINTING );
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->dev.handlename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         free_spool_notify_option(&Printer->notify.option);
216         Printer->notify.option=NULL;
217         Printer->notify.client_connected=False;
218         
219         free_nt_devicemode( &Printer->nt_devmode );
220         free_a_printer( &Printer->printer_info, 2 );
221         
222         talloc_destroy( Printer->ctx );
223
224         /* Remove from the internal list. */
225         DLIST_REMOVE(printers_list, Printer);
226
227         SAFE_FREE(Printer);
228 }
229
230 /****************************************************************************
231  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
233
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
235 {
236         SPOOL_NOTIFY_OPTION *new_sp = NULL;
237
238         if (!sp)
239                 return NULL;
240
241         new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
242         if (!new_sp)
243                 return NULL;
244
245         *new_sp = *sp;
246
247         if (sp->ctr.count) {
248                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
249
250                 if (!new_sp->ctr.type) {
251                         SAFE_FREE(new_sp);
252                         return NULL;
253                 }
254         }
255
256         return new_sp;
257 }
258
259 /****************************************************************************
260   find printer index by handle
261 ****************************************************************************/
262
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
264 {
265         Printer_entry *find_printer = NULL;
266
267         if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
268                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269                 return NULL;
270         }
271
272         return find_printer;
273 }
274
275 /****************************************************************************
276  look for a printer object cached on an open printer handle
277 ****************************************************************************/
278
279 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2, 
280                                         const char *printername )
281 {
282         Printer_entry *p;
283         
284         DEBUG(10,("find_printer_in_print_hnd_cache: printer [%s]\n", printername));
285
286         for ( p=printers_list; p; p=p->next )
287         {
288                 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER 
289                         && p->printer_info
290                         && StrCaseCmp(p->dev.handlename, printername) == 0 )
291                 {
292                         DEBUG(10,("Found printer\n"));
293                         *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
294                         if ( *info2 )
295                                 return WERR_OK;
296                 }
297         }
298
299         return WERR_INVALID_PRINTER_NAME;
300 }
301
302 /****************************************************************************
303   destroy any cached printer_info_2 structures on open handles
304 ****************************************************************************/
305
306 void invalidate_printer_hnd_cache( char *printername )
307 {
308         Printer_entry *p;
309         
310         DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
311
312         for ( p=printers_list; p; p=p->next )
313         {
314                 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER 
315                         && StrCaseCmp(p->dev.handlename, printername)==0)
316                 {
317                         DEBUG(10,("invalidating printer_info cache for handl:\n"));
318                         free_a_printer( &p->printer_info, 2 );
319                         p->printer_info = NULL;
320                 }
321         }
322
323         return;
324 }
325 /****************************************************************************
326  Close printer index by handle.
327 ****************************************************************************/
328
329 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
330 {
331         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
332
333         if (!Printer) {
334                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
335                 return False;
336         }
337
338         close_policy_hnd(p, hnd);
339
340         return True;
341 }       
342
343 /****************************************************************************
344  Delete a printer given a handle.
345 ****************************************************************************/
346
347 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
348 {
349         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
350
351         if (!Printer) {
352                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
353                 return WERR_BADFID;
354         }
355
356         /* 
357          * It turns out that Windows allows delete printer on a handle
358          * opened by an admin user, then used on a pipe handle created
359          * by an anonymous user..... but they're working on security.... riiight !
360          * JRA.
361          */
362
363         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
364                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
365                 return WERR_ACCESS_DENIED;
366         }
367
368 #if 0
369         /* Check calling user has permission to delete printer.  Note that
370            since we set the snum parameter to -1 only administrators can
371            delete the printer.  This stops people with the Full Control
372            permission from deleting the printer. */
373
374         if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
375                 DEBUG(3, ("printer delete denied by security descriptor\n"));
376                 return WERR_ACCESS_DENIED;
377         }
378 #endif
379
380         if (del_a_printer(Printer->dev.handlename) != 0) {
381                 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
382                 return WERR_BADFID;
383         }
384
385         if (*lp_deleteprinter_cmd()) {
386
387                 char *cmd = lp_deleteprinter_cmd();
388                 pstring command;
389                 int ret;
390                 int i;
391
392                 /* Printer->dev.handlename equals portname equals sharename */
393                 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
394                                         Printer->dev.handlename);
395
396                 DEBUG(10,("Running [%s]\n", command));
397                 ret = smbrun(command, NULL);
398                 if (ret != 0) {
399                         return WERR_BADFID; /* What to return here? */
400                 }
401                 DEBUGADD(10,("returned [%d]\n", ret));
402
403                 /* Send SIGHUP to process group... is there a better way? */
404                 kill(0, SIGHUP);
405
406                 /* go ahead and re-read the services immediately */
407                 reload_services( False );
408
409                 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
410                         return WERR_ACCESS_DENIED;
411         }
412
413         return WERR_OK;
414 }
415
416 /****************************************************************************
417  Return the snum of a printer corresponding to an handle.
418 ****************************************************************************/
419
420 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
421 {
422         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
423                 
424         if (!Printer) {
425                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
426                 return False;
427         }
428         
429         switch (Printer->printer_type) {
430         case PRINTER_HANDLE_IS_PRINTER:         
431                 DEBUG(4,("short name:%s\n", Printer->dev.handlename));                  
432                 *number = print_queue_snum(Printer->dev.handlename);
433                 return (*number != -1);
434         case PRINTER_HANDLE_IS_PRINTSERVER:
435                 return False;
436         default:
437                 return False;
438         }
439 }
440
441 /****************************************************************************
442  Set printer handle type.
443  Check if it's \\server or \\server\printer
444 ****************************************************************************/
445
446 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
447 {
448         DEBUG(3,("Setting printer type=%s\n", handlename));
449
450         if ( strlen(handlename) < 3 ) {
451                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
452                 return False;
453         }
454
455         /* it's a print server */
456         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
457                 DEBUGADD(4,("Printer is a print server\n"));
458                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;          
459         }
460         /* it's a printer */
461         else {
462                 DEBUGADD(4,("Printer is a printer\n"));
463                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
464         }
465
466         return True;
467 }
468
469 /****************************************************************************
470  Set printer handle name.
471 ****************************************************************************/
472
473 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
474 {
475         int snum;
476         int n_services=lp_numservices();
477         char *aprinter;
478         fstring sname;
479         BOOL found=False;
480         
481         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
482
483         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
484                 ZERO_STRUCT(Printer->dev.printerservername);
485                 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
486                 return True;
487         }
488
489         if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
490                 return False;
491         
492         if (*handlename=='\\') {
493                 aprinter=strchr_m(handlename+2, '\\');
494                 aprinter++;
495         }
496         else {
497                 aprinter=handlename;
498         }
499
500         DEBUGADD(5,("searching for [%s] (len=%lu)\n", aprinter, (unsigned long)strlen(aprinter)));
501
502         /*
503          * The original code allowed smbd to store a printer name that
504          * was different from the share name.  This is not possible 
505          * anymore, so I've simplified this loop greatly.  Here
506          * we are just verifying that the printer name is a valid
507          * printer service defined in smb.conf
508          *                          --jerry [Fri Feb 15 11:17:46 CST 2002]
509          */
510
511         for (snum=0; snum<n_services; snum++) {
512
513                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
514                         continue;
515                 
516                 fstrcpy(sname, lp_servicename(snum));
517
518                 DEBUGADD(5,("share:%s\n",sname));
519                 
520                 if (! StrCaseCmp(sname, aprinter)) {
521                         found = True;
522                         break;
523                 }
524
525         }
526
527                 
528         if (!found) {
529                 DEBUGADD(4,("Printer not found\n"));
530                 return False;
531         }
532         
533         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
534
535         ZERO_STRUCT(Printer->dev.handlename);
536         fstrcpy(Printer->dev.handlename, sname);
537
538         return True;
539 }
540
541 /****************************************************************************
542  Find first available printer slot. creates a printer handle for you.
543  ****************************************************************************/
544
545 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
546 {
547         Printer_entry *new_printer;
548
549         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
550
551         if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
552                 return False;
553
554         ZERO_STRUCTP(new_printer);
555         
556         if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
557                 SAFE_FREE(new_printer);
558                 return False;
559         }
560         
561         /* Add to the internal list. */
562         DLIST_ADD(printers_list, new_printer);
563         
564         new_printer->notify.option=NULL;
565                                 
566         if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
567                 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
568                 close_printer_handle(p, hnd);
569                 return False;
570         }
571         
572         if (!set_printer_hnd_printertype(new_printer, name)) {
573                 close_printer_handle(p, hnd);
574                 return False;
575         }
576         
577         if (!set_printer_hnd_name(new_printer, name)) {
578                 close_printer_handle(p, hnd);
579                 return False;
580         }
581
582         new_printer->access_granted = access_granted;
583
584         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
585
586         return True;
587 }
588
589 /****************************************************************************
590  Allocate more memory for a BUFFER.
591 ****************************************************************************/
592
593 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
594 {
595         prs_struct *ps;
596         uint32 extra_space;
597         uint32 old_offset;
598         
599         ps= &buffer->prs;
600
601         /* damn, I'm doing the reverse operation of prs_grow() :) */
602         if (buffer_size < prs_data_size(ps))
603                 extra_space=0;
604         else    
605                 extra_space = buffer_size - prs_data_size(ps);
606
607         /*
608          * save the offset and move to the end of the buffer
609          * prs_grow() checks the extra_space against the offset
610          */
611         old_offset=prs_offset(ps);      
612         prs_set_offset(ps, prs_data_size(ps));
613         
614         if (!prs_grow(ps, extra_space))
615                 return False;
616
617         prs_set_offset(ps, old_offset);
618
619         buffer->string_at_end=prs_data_size(ps);
620
621         return True;
622 }
623
624 /***************************************************************************
625  check to see if the client motify handle is monitoring the notification
626  given by (notify_type, notify_field).
627  **************************************************************************/
628
629 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
630                                       uint16 notify_field)
631 {
632         return True;
633 }
634
635 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
636                                 uint16 notify_field)
637 {
638         SPOOL_NOTIFY_OPTION *option = p->notify.option;
639         uint32 i, j;
640
641         /* 
642          * Flags should always be zero when the change notify
643          * is registered by the client's spooler.  A user Win32 app
644          * might use the flags though instead of the NOTIFY_OPTION_INFO 
645          * --jerry
646          */
647          
648         if (p->notify.flags)
649                 return is_monitoring_event_flags(
650                         p->notify.flags, notify_type, notify_field);
651
652         for (i = 0; i < option->count; i++) {
653                 
654                 /* Check match for notify_type */
655                 
656                 if (option->ctr.type[i].type != notify_type)
657                         continue;
658
659                 /* Check match for field */
660                 
661                 for (j = 0; j < option->ctr.type[i].count; j++) {
662                         if (option->ctr.type[i].fields[j] == notify_field) {
663                                 return True;
664                         }
665                 }
666         }
667         
668         DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
669                    (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
670                    p->dev.handlename : p->dev.printerservername,
671                    notify_type, notify_field));
672         
673         return False;
674 }
675
676 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677
678 static void notify_one_value(struct spoolss_notify_msg *msg,
679                              SPOOL_NOTIFY_INFO_DATA *data,
680                              TALLOC_CTX *mem_ctx)
681 {
682         data->notify_data.value[0] = msg->notify.value[0];
683         data->notify_data.value[1] = 0;
684 }
685
686 static void notify_string(struct spoolss_notify_msg *msg,
687                           SPOOL_NOTIFY_INFO_DATA *data,
688                           TALLOC_CTX *mem_ctx)
689 {
690         UNISTR2 unistr;
691         
692         /* The length of the message includes the trailing \0 */
693
694         init_unistr2(&unistr, msg->notify.data, msg->len);
695
696         data->notify_data.data.length = msg->len * 2;
697         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
698
699         if (!data->notify_data.data.string) {
700                 data->notify_data.data.length = 0;
701                 return;
702         }
703         
704         memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
705 }
706
707 static void notify_system_time(struct spoolss_notify_msg *msg,
708                                SPOOL_NOTIFY_INFO_DATA *data,
709                                TALLOC_CTX *mem_ctx)
710 {
711         SYSTEMTIME systime;
712         prs_struct ps;
713
714         if (msg->len != sizeof(time_t)) {
715                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
716                           msg->len));
717                 return;
718         }
719
720         if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
721                 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
722                 return;
723         }
724
725         if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
726                 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
727                 return;
728         }
729
730         if (!spoolss_io_system_time("", &ps, 0, &systime))
731                 return;
732
733         data->notify_data.data.length = prs_offset(&ps);
734         data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
735
736         prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
737
738         prs_mem_free(&ps);
739 }
740
741 struct notify2_message_table {
742         const char *name;
743         void (*fn)(struct spoolss_notify_msg *msg,
744                    SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
745 };
746
747 static struct notify2_message_table printer_notify_table[] = {
748         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
749         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
750         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
751         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
752         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
753         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
754         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
755         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
756         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
757         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
758         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
759         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
760         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
761         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
762         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
763         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
764         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
765         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
766         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
767 };
768
769 static struct notify2_message_table job_notify_table[] = {
770         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
771         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
772         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
773         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
774         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
775         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
776         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
777         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
778         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
779         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
780         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
781         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
782         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
783         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
784         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
785         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
786         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
787         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
788         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
789         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
790         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
791         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
792         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
793         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
794 };
795
796
797 /***********************************************************************
798  Allocate talloc context for container object
799  **********************************************************************/
800  
801 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
802 {
803         if ( !ctr )
804                 return;
805
806         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
807                 
808         return;
809 }
810
811 /***********************************************************************
812  release all allocated memory and zero out structure
813  **********************************************************************/
814  
815 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
816 {
817         if ( !ctr )
818                 return;
819
820         if ( ctr->ctx )
821                 talloc_destroy(ctr->ctx);
822                 
823         ZERO_STRUCTP(ctr);
824                 
825         return;
826 }
827
828 /***********************************************************************
829  **********************************************************************/
830  
831 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
832 {
833         if ( !ctr )
834                 return NULL;
835                 
836         return ctr->ctx;
837 }
838
839 /***********************************************************************
840  **********************************************************************/
841  
842 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
843 {
844         if ( !ctr || !ctr->msg_groups )
845                 return NULL;
846         
847         if ( idx >= ctr->num_groups )
848                 return NULL;
849                 
850         return &ctr->msg_groups[idx];
851
852 }
853
854 /***********************************************************************
855  How many groups of change messages do we have ?
856  **********************************************************************/
857  
858 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
859 {
860         if ( !ctr )
861                 return 0;
862                 
863         return ctr->num_groups;
864 }
865
866 /***********************************************************************
867  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
868  **********************************************************************/
869  
870 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
871 {
872         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
873         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
874         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
875         int                             i, new_slot;
876         
877         if ( !ctr || !msg )
878                 return 0;
879         
880         /* loop over all groups looking for a matching printer name */
881         
882         for ( i=0; i<ctr->num_groups; i++ ) {
883                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
884                         break;
885         }
886         
887         /* add a new group? */
888         
889         if ( i == ctr->num_groups ) {
890                 ctr->num_groups++;
891
892                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
893                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
894                         return 0;
895                 }
896                 ctr->msg_groups = groups;
897
898                 /* clear the new entry and set the printer name */
899                 
900                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
901                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
902         }
903         
904         /* add the change messages; 'i' is the correct index now regardless */
905         
906         msg_grp = &ctr->msg_groups[i];
907         
908         msg_grp->num_msgs++;
909         
910         if ( !(msg_list =  talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
911                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
912                 return 0;
913         }
914         msg_grp->msgs = msg_list;
915         
916         new_slot = msg_grp->num_msgs-1;
917         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
918         
919         /* need to allocate own copy of data */
920         
921         if ( msg->len != 0 ) 
922                 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
923         
924         return ctr->num_groups;
925 }
926
927 /***********************************************************************
928  Send a change notication message on all handles which have a call 
929  back registered
930  **********************************************************************/
931
932 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
933 {
934         Printer_entry            *p;
935         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
936         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
937         SPOOLSS_NOTIFY_MSG       *messages;
938         int                      sending_msg_count;
939         
940         if ( !msg_group ) {
941                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
942                 return;
943         }
944         
945         messages = msg_group->msgs;
946         
947         if ( !messages ) {
948                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
949                 return;
950         }
951         
952         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
953         
954         /* loop over all printers */
955         
956         for (p = printers_list; p; p = p->next) {
957                 SPOOL_NOTIFY_INFO_DATA *data;
958                 uint32  data_len = 0;
959                 uint32  id;
960                 int     i, event_index;
961
962                 /* Is there notification on this handle? */
963
964                 if ( !p->notify.client_connected )
965                         continue;
966
967                 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
968
969                 /* For this printer?  Print servers always receive 
970                    notifications. */
971
972                 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER )  &&
973                     ( !strequal(msg_group->printername, p->dev.handlename) ) )
974                         continue;
975
976                 DEBUG(10,("Our printer\n"));
977                 
978                 /* allocate the max entries possible */
979                 
980                 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
981                 ZERO_STRUCTP(data);
982                 
983                 event_index = 0;
984                 
985                 /* build the array of change notifications */
986                 
987                 sending_msg_count = 0;
988                 
989                 for ( i=0; i<msg_group->num_msgs; i++ ) {
990                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
991                         
992                         /* Are we monitoring this event? */
993
994                         if (!is_monitoring_event(p, msg->type, msg->field))
995                                 continue;
996
997                         sending_msg_count++;
998                         
999                         
1000                         DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
1001                                 msg->type, msg->field, p->dev.handlename));
1002
1003                         /* 
1004                          * if the is a printer notification handle and not a job notification 
1005                          * type, then set the id to 0.  Other wise just use what was specified
1006                          * in the message.  
1007                          *
1008                          * When registering change notification on a print server handle 
1009                          * we always need to send back the id (snum) matching the printer
1010                          * for which the change took place.  For change notify registered
1011                          * on a printer handle, this does not matter and the id should be 0.
1012                          *
1013                          * --jerry
1014                          */
1015
1016                         if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1017                                 id = 0;
1018                         else
1019                                 id = msg->id;
1020
1021
1022                         /* Convert unix jobid to smb jobid */
1023
1024                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1025                                 id = sysjob_to_jobid(msg->id);
1026
1027                                 if (id == -1) {
1028                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1029                                         goto done;
1030                                 }
1031                         }
1032
1033                         construct_info_data( &data[data_len], msg->type, msg->field, id );
1034
1035                         switch(msg->type) {
1036                         case PRINTER_NOTIFY_TYPE:
1037                                 if ( printer_notify_table[msg->field].fn )
1038                                         printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1039                                 break;
1040                         
1041                         case JOB_NOTIFY_TYPE:
1042                                 if ( job_notify_table[msg->field].fn )
1043                                         job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1044                                 break;
1045
1046                         default:
1047                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1048                                 goto done;
1049                         }
1050
1051                         data_len++;
1052                 }
1053
1054                 if ( sending_msg_count ) {
1055                         cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd, 
1056                                         data_len, data, p->notify.change, 0 );
1057                 }
1058         }
1059         
1060 done:
1061         DEBUG(8,("send_notify2_changes: Exit...\n"));
1062         return;
1063 }
1064
1065 /***********************************************************************
1066  **********************************************************************/
1067
1068 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1069 {
1070
1071         uint32 tv_sec, tv_usec;
1072         size_t offset = 0;
1073
1074         /* Unpack message */
1075
1076         offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1077                              msg->printer);
1078         
1079         offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1080                                 &tv_sec, &tv_usec,
1081                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1082
1083         if (msg->len == 0)
1084                 tdb_unpack((char *)buf + offset, len - offset, "dd",
1085                            &msg->notify.value[0], &msg->notify.value[1]);
1086         else
1087                 tdb_unpack((char *)buf + offset, len - offset, "B", 
1088                            &msg->len, &msg->notify.data);
1089
1090         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1091                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1092
1093         tv->tv_sec = tv_sec;
1094         tv->tv_usec = tv_usec;
1095
1096         if (msg->len == 0)
1097                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1098                           msg->notify.value[1]));
1099         else
1100                 dump_data(3, msg->notify.data, msg->len);
1101
1102         return True;
1103 }
1104
1105 /* ENUMJOB last timestamp list. */
1106 struct ejts_list {
1107         struct ejts_list *next, *prev;
1108         char *printer_name;
1109         struct timeval tv;
1110 };
1111
1112 static struct ejts_list *ejts_head;
1113
1114 static struct ejts_list *find_enumjobs_timestamp(const char *printer_name)
1115 {
1116         struct ejts_list *ejtsl;
1117
1118         for( ejtsl = ejts_head; ejtsl; ejtsl = ejtsl->next)
1119                 if (strequal(ejtsl->printer_name, printer_name))
1120                         return ejtsl;
1121         return NULL;
1122 }
1123
1124 static void set_enumjobs_timestamp(int snum)
1125 {
1126         const char *printer_name = lp_const_servicename(snum);
1127         struct ejts_list *ejtsl = find_enumjobs_timestamp(printer_name);
1128
1129         if (!ejtsl) {
1130                 ejtsl = (struct ejts_list *)malloc(sizeof(struct ejts_list));
1131                 if (!ejtsl)
1132                         return;
1133                 ejtsl->printer_name = strdup(printer_name);
1134                 if (!ejtsl->printer_name) {
1135                         SAFE_FREE(ejtsl);
1136                         return;
1137                 }
1138                 DLIST_ADD(ejts_head, ejtsl);
1139         }
1140
1141         gettimeofday(&ejtsl->tv, NULL);
1142 }
1143
1144 static int timeval_diff(struct timeval *tv1, struct timeval *tv2)
1145 {
1146         if (tv1->tv_sec > tv2->tv_sec)
1147                 return 1;
1148         if (tv1->tv_sec < tv2->tv_sec)
1149                 return -1;
1150         if (tv1->tv_usec > tv2->tv_usec)
1151                 return 1;
1152         if (tv1->tv_usec < tv2->tv_usec)
1153                 return -1;
1154         return 0;
1155 }
1156
1157 /********************************************************************
1158  Receive a notify2 message list
1159  ********************************************************************/
1160
1161 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1162 {
1163         size_t                  msg_count, i;
1164         char                    *buf = (char *)msg;
1165         char                    *msg_ptr;
1166         size_t                  msg_len;
1167         SPOOLSS_NOTIFY_MSG      notify;
1168         SPOOLSS_NOTIFY_MSG_CTR  messages;
1169         int                     num_groups;
1170
1171         if (len < 4) {
1172                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1173                 return;
1174         }
1175         
1176         msg_count = IVAL(buf, 0);
1177         msg_ptr = buf + 4;
1178
1179         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1180
1181         if (msg_count == 0) {
1182                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1183                 return;
1184         }
1185
1186         /* initialize the container */
1187         
1188         ZERO_STRUCT( messages );
1189         notify_msg_ctr_init( &messages );
1190         
1191         /* 
1192          * build message groups for each printer identified
1193          * in a change_notify msg.  Remember that a PCN message
1194          * includes the handle returned for the srv_spoolss_replyopenprinter()
1195          * call.  Therefore messages are grouped according to printer handle.
1196          */
1197          
1198         for ( i=0; i<msg_count; i++ ) {
1199                 struct timeval msg_tv;
1200
1201                 if (msg_ptr + 4 - buf > len) {
1202                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1203                         return;
1204                 }
1205
1206                 msg_len = IVAL(msg_ptr,0);
1207                 msg_ptr += 4;
1208
1209                 if (msg_ptr + msg_len - buf > len) {
1210                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1211                         return;
1212                 }
1213                 
1214                 /* unpack messages */
1215                 
1216                 ZERO_STRUCT( notify );
1217                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1218                 msg_ptr += msg_len;
1219                 
1220                 /* See if it is still relevent. */
1221                 if (notify.type == JOB_NOTIFY_TYPE) {
1222                         BOOL status_is_deleting = False;
1223
1224                         if (notify.field == JOB_NOTIFY_STATUS && (notify.notify.value[0] & (JOB_STATUS_DELETING|JOB_STATUS_DELETED)))
1225                                 status_is_deleting = True;
1226
1227                         if (!status_is_deleting) {
1228                                 struct ejts_list *ejtsl = find_enumjobs_timestamp(notify.printer);
1229
1230                                 if (ejtsl && (timeval_diff(&ejtsl->tv, &msg_tv) > 0)) {
1231
1232                                         DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n",
1233                                                 (unsigned int)ejtsl->tv.tv_sec, (unsigned int)ejtsl->tv.tv_usec,
1234                                                 (unsigned int)msg_tv.tv_sec, (unsigned int)msg_tv.tv_usec ));
1235
1236                                         /* Message no longer relevent. Ignore it. */
1237                                         if ( notify.len != 0 )
1238                                                 SAFE_FREE( notify.notify.data );
1239                                         continue;
1240                                 }
1241                         }
1242                 }
1243                 /* add to correct list in container */
1244                 
1245                 notify_msg_ctr_addmsg( &messages, &notify );
1246                 
1247                 /* free memory that might have been allocated by notify2_unpack_msg() */
1248                 
1249                 if ( notify.len != 0 )
1250                         SAFE_FREE( notify.notify.data );
1251         }
1252         
1253         /* process each group of messages */
1254         
1255         num_groups = notify_msg_ctr_numgroups( &messages );
1256         for ( i=0; i<num_groups; i++ )
1257                 send_notify2_changes( &messages, i );
1258         
1259         
1260         /* cleanup */
1261                 
1262         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1263                 
1264         notify_msg_ctr_destroy( &messages );
1265         
1266         return;
1267 }
1268
1269 /********************************************************************
1270  Send a message to ourself about new driver being installed
1271  so we can upgrade the information for each printer bound to this
1272  driver
1273  ********************************************************************/
1274  
1275 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1276 {
1277         int len = strlen(drivername);
1278         
1279         if (!len)
1280                 return False;
1281
1282         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1283                 drivername));
1284                 
1285         message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1286
1287         return True;
1288 }
1289
1290 /**********************************************************************
1291  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1292  over all printers, upgrading ones as necessary 
1293  **********************************************************************/
1294  
1295 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1296 {
1297         fstring drivername;
1298         int snum;
1299         int n_services = lp_numservices();
1300         
1301         len = MIN(len,sizeof(drivername)-1);
1302         strncpy(drivername, buf, len);
1303         
1304         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1305
1306         /* Iterate the printer list */
1307         
1308         for (snum=0; snum<n_services; snum++)
1309         {
1310                 if (lp_snum_ok(snum) && lp_print_ok(snum) ) 
1311                 {
1312                         WERROR result;
1313                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1314                         
1315                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1316                         if (!W_ERROR_IS_OK(result))
1317                                 continue;
1318                                 
1319                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername)) 
1320                         {
1321                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1322                                 
1323                                 /* all we care about currently is the change_id */
1324                                 
1325                                 result = mod_a_printer(*printer, 2);
1326                                 if (!W_ERROR_IS_OK(result)) {
1327                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n", 
1328                                                 dos_errstr(result)));
1329                                 }
1330                         }
1331                         
1332                         free_a_printer(&printer, 2);                    
1333                 }
1334         }
1335         
1336         /* all done */  
1337 }
1338
1339 /********************************************************************
1340  Update the cache for all printq's with a registered client 
1341  connection
1342  ********************************************************************/
1343
1344 void update_monitored_printq_cache( void )
1345 {
1346         Printer_entry *printer = printers_list;
1347         int snum;
1348         
1349         /* loop through all printers and update the cache where 
1350            client_connected == True */
1351         while ( printer ) 
1352         {
1353                 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER) 
1354                         && printer->notify.client_connected ) 
1355                 {
1356                         snum = print_queue_snum(printer->dev.handlename);
1357                         print_queue_status( snum, NULL, NULL );
1358                 }
1359                 
1360                 printer = printer->next;
1361         }
1362         
1363         return;
1364 }
1365 /********************************************************************
1366  Send a message to ourself about new driver being installed
1367  so we can upgrade the information for each printer bound to this
1368  driver
1369  ********************************************************************/
1370  
1371 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1372 {
1373         int len = strlen(drivername);
1374         
1375         if (!len)
1376                 return False;
1377
1378         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1379                 drivername));
1380                 
1381         message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1382
1383         return True;
1384 }
1385
1386 /**********************************************************************
1387  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1388  over all printers, resetting printer data as neessary 
1389  **********************************************************************/
1390  
1391 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1392 {
1393         fstring drivername;
1394         int snum;
1395         int n_services = lp_numservices();
1396         
1397         len = MIN( len, sizeof(drivername)-1 );
1398         strncpy( drivername, buf, len );
1399         
1400         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1401
1402         /* Iterate the printer list */
1403         
1404         for ( snum=0; snum<n_services; snum++ )
1405         {
1406                 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) 
1407                 {
1408                         WERROR result;
1409                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1410                         
1411                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1412                         if ( !W_ERROR_IS_OK(result) )
1413                                 continue;
1414                                 
1415                         /* 
1416                          * if the printer is bound to the driver, 
1417                          * then reset to the new driver initdata 
1418                          */
1419                         
1420                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) ) 
1421                         {
1422                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1423                                 
1424                                 if ( !set_driver_init(printer, 2) ) {
1425                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1426                                                 printer->info_2->printername, printer->info_2->drivername));
1427                                 }       
1428                                 
1429                                 result = mod_a_printer( *printer, 2 );
1430                                 if ( !W_ERROR_IS_OK(result) ) {
1431                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n", 
1432                                                 get_dos_error_msg(result)));
1433                                 }
1434                         }
1435                         
1436                         free_a_printer( &printer, 2 );
1437                 }
1438         }
1439         
1440         /* all done */  
1441         
1442         return;
1443 }
1444
1445 /********************************************************************
1446  Copy routines used by convert_to_openprinterex()
1447  *******************************************************************/
1448
1449 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1450 {
1451         DEVICEMODE *d;
1452         int len;
1453
1454         if (!devmode)
1455                 return NULL;
1456                 
1457         DEBUG (8,("dup_devmode\n"));
1458         
1459         /* bulk copy first */
1460         
1461         d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1462         if (!d)
1463                 return NULL;
1464                 
1465         /* dup the pointer members separately */
1466         
1467         len = unistrlen(devmode->devicename.buffer);
1468         if (len != -1) {
1469                 d->devicename.buffer = talloc(ctx, len*2);
1470                 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1471                         return NULL;
1472         }
1473                 
1474
1475         len = unistrlen(devmode->formname.buffer);
1476         if (len != -1) {
1477                 d->devicename.buffer = talloc(ctx, len*2);
1478                 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1479                         return NULL;
1480         }
1481
1482         d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1483         
1484         return d;
1485 }
1486
1487 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1488 {
1489         if (!new_ctr || !ctr)
1490                 return;
1491                 
1492         DEBUG(8,("copy_devmode_ctr\n"));
1493         
1494         new_ctr->size = ctr->size;
1495         new_ctr->devmode_ptr = ctr->devmode_ptr;
1496         
1497         if(ctr->devmode_ptr)
1498                 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1499 }
1500
1501 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1502 {
1503         if (!new_def || !def)
1504                 return;
1505         
1506         DEBUG(8,("copy_printer_defaults\n"));
1507         
1508         new_def->datatype_ptr = def->datatype_ptr;
1509         
1510         if (def->datatype_ptr)
1511                 copy_unistr2(&new_def->datatype, &def->datatype);
1512         
1513         copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1514         
1515         new_def->access_required = def->access_required;
1516 }
1517
1518 /********************************************************************
1519  * Convert a SPOOL_Q_OPEN_PRINTER structure to a 
1520  * SPOOL_Q_OPEN_PRINTER_EX structure
1521  ********************************************************************/
1522
1523 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1524 {
1525         if (!q_u_ex || !q_u)
1526                 return;
1527
1528         DEBUG(8,("convert_to_openprinterex\n"));
1529                                 
1530         q_u_ex->printername_ptr = q_u->printername_ptr;
1531         
1532         if (q_u->printername_ptr)
1533                 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1534         
1535         copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1536 }
1537
1538 /********************************************************************
1539  * spoolss_open_printer
1540  *
1541  * called from the spoolss dispatcher
1542  ********************************************************************/
1543
1544 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1545 {
1546         SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1547         SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1548         
1549         if (!q_u || !r_u)
1550                 return WERR_NOMEM;
1551         
1552         ZERO_STRUCT(q_u_ex);
1553         ZERO_STRUCT(r_u_ex);
1554         
1555         /* convert the OpenPrinter() call to OpenPrinterEx() */
1556         
1557         convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1558         
1559         r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1560         
1561         /* convert back to OpenPrinter() */
1562         
1563         memcpy(r_u, &r_u_ex, sizeof(*r_u));
1564         
1565         return r_u->status;
1566 }
1567
1568 /********************************************************************
1569  * spoolss_open_printer
1570  *
1571  * If the openprinterex rpc call contains a devmode,
1572  * it's a per-user one. This per-user devmode is derivated
1573  * from the global devmode. Openprinterex() contains a per-user 
1574  * devmode for when you do EMF printing and spooling.
1575  * In the EMF case, the NT workstation is only doing half the job
1576  * of rendering the page. The other half is done by running the printer
1577  * driver on the server.
1578  * The EMF file doesn't contain the page description (paper size, orientation, ...).
1579  * The EMF file only contains what is to be printed on the page.
1580  * So in order for the server to know how to print, the NT client sends
1581  * a devicemode attached to the openprinterex call.
1582  * But this devicemode is short lived, it's only valid for the current print job.
1583  *
1584  * If Samba would have supported EMF spooling, this devicemode would
1585  * have been attached to the handle, to sent it to the driver to correctly
1586  * rasterize the EMF file.
1587  *
1588  * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1589  * we just act as a pass-thru between windows and the printer.
1590  *
1591  * In order to know that Samba supports only RAW spooling, NT has to call
1592  * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1593  * and until NT sends a RAW job, we refuse it.
1594  *
1595  * But to call getprinter() or startdoc(), you first need a valid handle,
1596  * and to get an handle you have to call openprintex(). Hence why you have
1597  * a devicemode in the openprinterex() call.
1598  *
1599  *
1600  * Differences between NT4 and NT 2000.
1601  * NT4:
1602  * ---
1603  * On NT4, you only have a global devicemode. This global devicemode can be changed
1604  * by the administrator (or by a user with enough privs). Everytime a user
1605  * wants to print, the devicemode is resetted to the default. In Word, everytime
1606  * you print, the printer's characteristics are always reset to the global devicemode.
1607  *
1608  * NT 2000:
1609  * -------
1610  * In W2K, there is the notion of per-user devicemode. The first time you use
1611  * a printer, a per-user devicemode is build from the global devicemode.
1612  * If you change your per-user devicemode, it is saved in the registry, under the
1613  * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1614  * printer preferences available.
1615  *
1616  * To change the per-user devicemode: it's the "Printing Preferences ..." button
1617  * on the General Tab of the printer properties windows.
1618  *
1619  * To change the global devicemode: it's the "Printing Defaults..." button
1620  * on the Advanced Tab of the printer properties window.
1621  *
1622  * JFM.
1623  ********************************************************************/
1624
1625 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1626 {
1627         UNISTR2                 *printername = NULL;
1628         PRINTER_DEFAULT         *printer_default = &q_u->printer_default;
1629         POLICY_HND              *handle = &r_u->handle;
1630
1631         fstring name;
1632         int snum;
1633         struct current_user user;
1634         Printer_entry *Printer=NULL;
1635
1636         if (q_u->printername_ptr != 0)
1637                 printername = &q_u->printername;
1638
1639         if (printername == NULL)
1640                 return WERR_INVALID_PRINTER_NAME;
1641
1642         /* some sanity check because you can open a printer or a print server */
1643         /* aka: \\server\printer or \\server */
1644         unistr2_to_ascii(name, printername, sizeof(name)-1);
1645
1646         DEBUGADD(3,("checking name: %s\n",name));
1647
1648         if (!open_printer_hnd(p, handle, name, 0))
1649                 return WERR_INVALID_PRINTER_NAME;
1650         
1651         Printer=find_printer_index_by_hnd(p, handle);
1652         if (!Printer) {
1653                 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1654 Can't find printer handle we created for printer %s\n", name ));
1655                 close_printer_handle(p,handle);
1656                 return WERR_INVALID_PRINTER_NAME;
1657         }
1658
1659         get_current_user(&user, p);
1660
1661         /*
1662          * First case: the user is opening the print server:
1663          *
1664          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1665          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1666          *
1667          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1668          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1669          * or if the user is listed in the smb.conf printer admin parameter.
1670          *
1671          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1672          * client view printer folder, but does not show the MSAPW.
1673          *
1674          * Note: this test needs code to check access rights here too. Jeremy
1675          * could you look at this?
1676          * 
1677          * Second case: the user is opening a printer:
1678          * NT doesn't let us connect to a printer if the connecting user
1679          * doesn't have print permission.
1680          */
1681
1682         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) 
1683         {
1684                 /* Printserver handles use global struct... */
1685
1686                 snum = -1;
1687
1688                 /* Map standard access rights to object specific access rights */
1689                 
1690                 se_map_standard(&printer_default->access_required, 
1691                                 &printserver_std_mapping);
1692         
1693                 /* Deny any object specific bits that don't apply to print
1694                    servers (i.e printer and job specific bits) */
1695
1696                 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1697
1698                 if (printer_default->access_required &
1699                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1700                         DEBUG(3, ("access DENIED for non-printserver bits"));
1701                         close_printer_handle(p, handle);
1702                         return WERR_ACCESS_DENIED;
1703                 }
1704
1705                 /* Allow admin access */
1706
1707                 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER ) 
1708                 {
1709                         if (!lp_ms_add_printer_wizard()) {
1710                                 close_printer_handle(p, handle);
1711                                 return WERR_ACCESS_DENIED;
1712                         }
1713
1714                         /* if the user is not root and not a printer admin, then fail */
1715                         
1716                         if ( user.uid != 0
1717                              && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1718                         {
1719                                 close_printer_handle(p, handle);
1720                                 return WERR_ACCESS_DENIED;
1721                         }
1722                         
1723                         printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1724                 }
1725                 else
1726                 {
1727                         printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1728                 }
1729
1730                 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER) 
1731                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1732                         
1733                 /* We fall through to return WERR_OK */
1734                 
1735         }
1736         else
1737         {
1738                 /* NT doesn't let us connect to a printer if the connecting user
1739                    doesn't have print permission.  */
1740
1741                 if (!get_printer_snum(p, handle, &snum)) {
1742                         close_printer_handle(p, handle);
1743                         return WERR_BADFID;
1744                 }
1745
1746                 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1747                 
1748                 /* map an empty access mask to the minimum access mask */
1749                 if (printer_default->access_required == 0x0)
1750                         printer_default->access_required = PRINTER_ACCESS_USE;
1751
1752                 /*
1753                  * If we are not serving the printer driver for this printer,
1754                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1755                  * will keep NT clients happy  --jerry  
1756                  */
1757                  
1758                 if (lp_use_client_driver(snum) 
1759                         && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1760                 {
1761                         printer_default->access_required = PRINTER_ACCESS_USE;
1762                 }
1763
1764                 /* check smb.conf parameters and the the sec_desc */
1765                 
1766                 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1767                         DEBUG(3, ("access DENIED for printer open\n"));
1768                         close_printer_handle(p, handle);
1769                         return WERR_ACCESS_DENIED;
1770                 }
1771
1772                 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1773                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1774                         close_printer_handle(p, handle);
1775                         return WERR_ACCESS_DENIED;
1776                 }
1777
1778                 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1779                         printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1780                 else
1781                         printer_default->access_required = PRINTER_ACCESS_USE;
1782
1783                 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER) 
1784                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1785
1786         }
1787         
1788         Printer->access_granted = printer_default->access_required;
1789         
1790         /* 
1791          * If the client sent a devmode in the OpenPrinter() call, then
1792          * save it here in case we get a job submission on this handle
1793          */
1794         
1795          if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1796                 && q_u->printer_default.devmode_cont.devmode_ptr )
1797          { 
1798                 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1799                         &Printer->nt_devmode );
1800          }
1801
1802         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN 
1803            optimization in Windows 2000 clients  --jerry */
1804
1805         if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER) 
1806                 && (RA_WIN2K == get_remote_arch()) )
1807         {
1808                 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1809                 usleep( 500000 );
1810         }
1811
1812         return WERR_OK;
1813 }
1814
1815 /****************************************************************************
1816 ****************************************************************************/
1817
1818 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1819                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1820 {
1821         BOOL ret = True;
1822
1823         switch (level) {
1824                 case 2:
1825                         ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1826                         break;
1827                 default:
1828                         break;
1829         }
1830
1831         return ret;
1832 }
1833
1834 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1835                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1836 {
1837         BOOL result = True;
1838
1839         switch (level) {
1840                 case 3:
1841                         printer->info_3=NULL;
1842                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1843                                 result = False;
1844                         break;
1845                 case 6:
1846                         printer->info_6=NULL;
1847                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1848                                 result = False;
1849                         break;
1850                 default:
1851                         break;
1852         }
1853
1854         return result;
1855 }
1856
1857 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1858                                 NT_DEVICEMODE **pp_nt_devmode)
1859 {
1860         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1861
1862         /*
1863          * Ensure nt_devmode is a valid pointer
1864          * as we will be overwriting it.
1865          */
1866                 
1867         if (nt_devmode == NULL) {
1868                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1869                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1870                         return False;
1871         }
1872
1873         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1874         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1875
1876         nt_devmode->specversion=devmode->specversion;
1877         nt_devmode->driverversion=devmode->driverversion;
1878         nt_devmode->size=devmode->size;
1879         nt_devmode->fields=devmode->fields;
1880         nt_devmode->orientation=devmode->orientation;
1881         nt_devmode->papersize=devmode->papersize;
1882         nt_devmode->paperlength=devmode->paperlength;
1883         nt_devmode->paperwidth=devmode->paperwidth;
1884         nt_devmode->scale=devmode->scale;
1885         nt_devmode->copies=devmode->copies;
1886         nt_devmode->defaultsource=devmode->defaultsource;
1887         nt_devmode->printquality=devmode->printquality;
1888         nt_devmode->color=devmode->color;
1889         nt_devmode->duplex=devmode->duplex;
1890         nt_devmode->yresolution=devmode->yresolution;
1891         nt_devmode->ttoption=devmode->ttoption;
1892         nt_devmode->collate=devmode->collate;
1893
1894         nt_devmode->logpixels=devmode->logpixels;
1895         nt_devmode->bitsperpel=devmode->bitsperpel;
1896         nt_devmode->pelswidth=devmode->pelswidth;
1897         nt_devmode->pelsheight=devmode->pelsheight;
1898         nt_devmode->displayflags=devmode->displayflags;
1899         nt_devmode->displayfrequency=devmode->displayfrequency;
1900         nt_devmode->icmmethod=devmode->icmmethod;
1901         nt_devmode->icmintent=devmode->icmintent;
1902         nt_devmode->mediatype=devmode->mediatype;
1903         nt_devmode->dithertype=devmode->dithertype;
1904         nt_devmode->reserved1=devmode->reserved1;
1905         nt_devmode->reserved2=devmode->reserved2;
1906         nt_devmode->panningwidth=devmode->panningwidth;
1907         nt_devmode->panningheight=devmode->panningheight;
1908
1909         /*
1910          * Only change private and driverextra if the incoming devmode
1911          * has a new one. JRA.
1912          */
1913
1914         if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1915                 SAFE_FREE(nt_devmode->private);
1916                 nt_devmode->driverextra=devmode->driverextra;
1917                 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1918                         return False;
1919                 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1920         }
1921
1922         *pp_nt_devmode = nt_devmode;
1923
1924         return True;
1925 }
1926
1927 /********************************************************************
1928  * _spoolss_enddocprinter_internal.
1929  ********************************************************************/
1930
1931 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1932 {
1933         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1934         int snum;
1935
1936         if (!Printer) {
1937                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1938                 return WERR_BADFID;
1939         }
1940         
1941         if (!get_printer_snum(p, handle, &snum))
1942                 return WERR_BADFID;
1943
1944         Printer->document_started=False;
1945         print_job_end(snum, Printer->jobid,True);
1946         /* error codes unhandled so far ... */
1947
1948         return WERR_OK;
1949 }
1950
1951 /********************************************************************
1952  * api_spoolss_closeprinter
1953  ********************************************************************/
1954
1955 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1956 {
1957         POLICY_HND *handle = &q_u->handle;
1958
1959         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1960
1961         if (Printer && Printer->document_started)
1962                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1963
1964         if (!close_printer_handle(p, handle))
1965                 return WERR_BADFID;     
1966                 
1967         /* clear the returned printer handle.  Observed behavior 
1968            from Win2k server.  Don't think this really matters.
1969            Previous code just copied the value of the closed
1970            handle.    --jerry */
1971
1972         memset(&r_u->handle, '\0', sizeof(r_u->handle));
1973
1974         return WERR_OK;
1975 }
1976
1977 /********************************************************************
1978  * api_spoolss_deleteprinter
1979
1980  ********************************************************************/
1981
1982 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1983 {
1984         POLICY_HND *handle = &q_u->handle;
1985         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1986         WERROR result;
1987
1988         if (Printer && Printer->document_started)
1989                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1990
1991         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1992
1993         result = delete_printer_handle(p, handle);
1994
1995         update_c_setprinter(False);
1996
1997         return result;
1998 }
1999
2000 /*******************************************************************
2001  * static function to lookup the version id corresponding to an
2002  * long architecture string
2003  ******************************************************************/
2004
2005 static int get_version_id (char * arch)
2006 {
2007         int i;
2008         struct table_node archi_table[]= {
2009  
2010                 {"Windows 4.0",          "WIN40",       0 },
2011                 {"Windows NT x86",       "W32X86",      2 },
2012                 {"Windows NT R4000",     "W32MIPS",     2 },    
2013                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2014                 {"Windows NT PowerPC",   "W32PPC",      2 },
2015                 {NULL,                   "",            -1 }
2016         };
2017  
2018         for (i=0; archi_table[i].long_archi != NULL; i++)
2019         {
2020                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2021                         return (archi_table[i].version);
2022         }
2023         
2024         return -1;
2025 }
2026
2027 /********************************************************************
2028  * _spoolss_deleteprinterdriver
2029  ********************************************************************/
2030
2031 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2032 {
2033         fstring                         driver;
2034         fstring                         arch;
2035         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2036         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2037         int                             version;
2038         struct current_user             user;
2039         WERROR                          status;
2040         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2041         
2042         get_current_user(&user, p);
2043          
2044         unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2045         unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
2046         
2047         /* check that we have a valid driver name first */
2048         
2049         if ((version=get_version_id(arch)) == -1) 
2050                 return WERR_INVALID_ENVIRONMENT;
2051                                 
2052         ZERO_STRUCT(info);
2053         ZERO_STRUCT(info_win2k);
2054         
2055         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) 
2056         {
2057                 /* try for Win2k driver if "Windows NT x86" */
2058                 
2059                 if ( version == 2 ) {
2060                         version = 3;
2061                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2062                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2063                                 goto done;
2064                         }
2065                 }
2066                 /* otherwise it was a failure */
2067                 else {
2068                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2069                         goto done;
2070                 }
2071                 
2072         }
2073         
2074         if (printer_driver_in_use(info.info_3)) {
2075                 status = WERR_PRINTER_DRIVER_IN_USE;
2076                 goto done;
2077         }
2078         
2079         if ( version == 2 )
2080         {               
2081                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2082                 {
2083                         /* if we get to here, we now have 2 driver info structures to remove */
2084                         /* remove the Win2k driver first*/
2085                 
2086                         status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2087                         free_a_printer_driver( info_win2k, 3 );
2088                 
2089                         /* this should not have failed---if it did, report to client */
2090                         if ( !W_ERROR_IS_OK(status_win2k) )
2091                                 goto done;
2092                 }
2093         }
2094         
2095         status = delete_printer_driver(info.info_3, &user, version, False);
2096         
2097         /* if at least one of the deletes succeeded return OK */
2098         
2099         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2100                 status = WERR_OK;
2101         
2102 done:
2103         free_a_printer_driver( info, 3 );
2104
2105         return status;
2106 }
2107
2108 /********************************************************************
2109  * spoolss_deleteprinterdriverex
2110  ********************************************************************/
2111
2112 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2113 {
2114         fstring                         driver;
2115         fstring                         arch;
2116         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2117         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2118         int                             version;
2119         uint32                          flags = q_u->delete_flags;
2120         BOOL                            delete_files;
2121         struct current_user             user;
2122         WERROR                          status;
2123         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2124         
2125         get_current_user(&user, p);
2126         
2127         unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2128         unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
2129
2130         /* check that we have a valid driver name first */
2131         if ((version=get_version_id(arch)) == -1) {
2132                 /* this is what NT returns */
2133                 return WERR_INVALID_ENVIRONMENT;
2134         }
2135         
2136         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2137                 version = q_u->version;
2138                 
2139         ZERO_STRUCT(info);
2140         ZERO_STRUCT(info_win2k);
2141                 
2142         status = get_a_printer_driver(&info, 3, driver, arch, version);
2143         
2144         if ( !W_ERROR_IS_OK(status) ) 
2145         {
2146                 /* 
2147                  * if the client asked for a specific version, 
2148                  * or this is something other than Windows NT x86,
2149                  * then we've failed 
2150                  */
2151                 
2152                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2153                         goto done;
2154                         
2155                 /* try for Win2k driver if "Windows NT x86" */
2156                 
2157                 version = 3;
2158                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2159                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2160                         goto done;
2161                 }
2162         }
2163                 
2164         if ( printer_driver_in_use(info.info_3) ) {
2165                 status = WERR_PRINTER_DRIVER_IN_USE;
2166                 goto done;
2167         }
2168         
2169         /* 
2170          * we have a couple of cases to consider. 
2171          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2172          *     then the delete should fail if **any** files overlap with 
2173          *     other drivers 
2174          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2175          *     non-overlapping files 
2176          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2177          *     is set, the do not delete any files
2178          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2179          */
2180         
2181         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2182         
2183         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2184                 
2185         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2186                 /* no idea of the correct error here */
2187                 status = WERR_ACCESS_DENIED;    
2188                 goto done;
2189         }
2190
2191                         
2192         /* also check for W32X86/3 if necessary; maybe we already have? */
2193                 
2194         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2195                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3))) 
2196                 {
2197                         
2198                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2199                                 /* no idea of the correct error here */
2200                                 free_a_printer_driver( info_win2k, 3 );
2201                                 status = WERR_ACCESS_DENIED;    
2202                                 goto done;
2203                         }
2204                 
2205                         /* if we get to here, we now have 2 driver info structures to remove */
2206                         /* remove the Win2k driver first*/
2207                 
2208                         status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2209                         free_a_printer_driver( info_win2k, 3 );
2210                                 
2211                         /* this should not have failed---if it did, report to client */
2212                                 
2213                         if ( !W_ERROR_IS_OK(status_win2k) )
2214                                 goto done;
2215                 }
2216         }
2217
2218         status = delete_printer_driver(info.info_3, &user, version, delete_files);
2219
2220         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2221                 status = WERR_OK;
2222 done:
2223         free_a_printer_driver( info, 3 );
2224         
2225         return status;
2226 }
2227
2228
2229 /****************************************************************************
2230  Internal routine for retreiving printerdata
2231  ***************************************************************************/
2232
2233 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, 
2234                                   const char *key, const char *value, uint32 *type, uint8 **data, 
2235                                   uint32 *needed, uint32 in_size  )
2236 {
2237         REGISTRY_VALUE          *val;
2238         int                     size, data_len;
2239         
2240         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2241                 return WERR_BADFILE;
2242         
2243         *type = regval_type( val );
2244
2245         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2246
2247         size = regval_size( val );
2248         
2249         /* copy the min(in_size, len) */
2250         
2251         if ( in_size ) {
2252                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2253                 
2254                 /* special case for 0 length values */
2255                 if ( data_len ) {
2256                         if ( (*data  = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2257                                 return WERR_NOMEM;
2258                 }
2259                 else {
2260                         if ( (*data  = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2261                                 return WERR_NOMEM;
2262                 }
2263         }
2264         else
2265                 *data = NULL;
2266
2267         *needed = size;
2268         
2269         DEBUG(5,("get_printer_dataex: copy done\n"));
2270
2271         return WERR_OK;
2272 }
2273
2274 /****************************************************************************
2275  Internal routine for removing printerdata
2276  ***************************************************************************/
2277
2278 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2279 {
2280         return delete_printer_data( printer->info_2, key, value );
2281 }
2282
2283 /****************************************************************************
2284  Internal routine for storing printerdata
2285  ***************************************************************************/
2286
2287 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value, 
2288                                   uint32 type, uint8 *data, int real_len  )
2289 {
2290         delete_printer_data( printer->info_2, key, value );
2291         
2292         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2293 }
2294
2295 /********************************************************************
2296  GetPrinterData on a printer server Handle.
2297 ********************************************************************/
2298
2299 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2300 {               
2301         int i;
2302         
2303         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2304                 
2305         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2306                 *type = 0x4;
2307                 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2308                         return WERR_NOMEM;
2309                 *needed = 0x4;
2310                 return WERR_OK;
2311         }
2312
2313         if (!StrCaseCmp(value, "BeepEnabled")) {
2314                 *type = 0x4;
2315                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2316                         return WERR_NOMEM;
2317                 SIVAL(*data, 0, 0x00);
2318                 *needed = 0x4;                  
2319                 return WERR_OK;
2320         }
2321
2322         if (!StrCaseCmp(value, "EventLog")) {
2323                 *type = 0x4;
2324                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2325                         return WERR_NOMEM;
2326                 /* formally was 0x1b */
2327                 SIVAL(*data, 0, 0x0);
2328                 *needed = 0x4;                  
2329                 return WERR_OK;
2330         }
2331
2332         if (!StrCaseCmp(value, "NetPopup")) {
2333                 *type = 0x4;
2334                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2335                         return WERR_NOMEM;
2336                 SIVAL(*data, 0, 0x00);
2337                 *needed = 0x4;
2338                 return WERR_OK;
2339         }
2340
2341         if (!StrCaseCmp(value, "MajorVersion")) {
2342                 *type = 0x4;
2343                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2344                         return WERR_NOMEM;
2345
2346                 /* Windows NT 4.0 seems to not allow uploading of drivers
2347                    to a server that reports 0x3 as the MajorVersion.
2348                    need to investigate more how Win2k gets around this .
2349                    -- jerry */
2350
2351                 if ( RA_WINNT == get_remote_arch() )
2352                         SIVAL(*data, 0, 2);
2353                 else
2354                         SIVAL(*data, 0, 3);
2355                 
2356                 *needed = 0x4;
2357                 return WERR_OK;
2358         }
2359
2360         if (!StrCaseCmp(value, "MinorVersion")) {
2361                 *type = 0x4;
2362                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2363                         return WERR_NOMEM;
2364                 SIVAL(*data, 0, 0);
2365                 *needed = 0x4;
2366                 return WERR_OK;
2367         }
2368
2369         /* REG_BINARY
2370          *  uint32 size          = 0x114
2371          *  uint32 major         = 5
2372          *  uint32 minor         = [0|1]
2373          *  uint32 build         = [2195|2600]
2374          *  extra unicode string = e.g. "Service Pack 3"
2375          */
2376         if (!StrCaseCmp(value, "OSVersion")) {
2377                 *type = 0x3;
2378                 *needed = 0x114;
2379
2380                 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2381                         return WERR_NOMEM;
2382                 ZERO_STRUCTP( *data );
2383                 
2384                 SIVAL(*data, 0, *needed);       /* size */
2385                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2386                 SIVAL(*data, 8, 0);
2387                 SIVAL(*data, 12, 2195);         /* build */
2388                 
2389                 /* leave extra string empty */
2390                 
2391                 return WERR_OK;
2392         }
2393
2394
2395         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2396                 fstring string;
2397
2398                 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2399                 *type = 0x1;                    
2400                 *needed = 2*(strlen(string)+1);         
2401                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2402                         return WERR_NOMEM;
2403                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404                 
2405                 /* it's done by hand ready to go on the wire */
2406                 for (i=0; i<strlen(string); i++) {
2407                         (*data)[2*i]=string[i];
2408                         (*data)[2*i+1]='\0';
2409                 }                       
2410                 return WERR_OK;
2411         }
2412
2413         if (!StrCaseCmp(value, "Architecture")) {                       
2414                 pstring string="Windows NT x86";
2415                 *type = 0x1;                    
2416                 *needed = 2*(strlen(string)+1); 
2417                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2418                         return WERR_NOMEM;
2419                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2420                 for (i=0; i<strlen(string); i++) {
2421                         (*data)[2*i]=string[i];
2422                         (*data)[2*i+1]='\0';
2423                 }                       
2424                 return WERR_OK;
2425         }
2426
2427         if (!StrCaseCmp(value, "DsPresent")) {
2428                 *type = 0x4;
2429                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2430                         return WERR_NOMEM;
2431                 SIVAL(*data, 0, 0x01);
2432                 *needed = 0x4;
2433                 return WERR_OK;
2434         }
2435
2436         if (!StrCaseCmp(value, "DNSMachineName")) {                     
2437                 pstring hostname;
2438                 
2439                 if (!get_myfullname(hostname))
2440                         return WERR_BADFILE;
2441                 *type = 0x1;                    
2442                 *needed = 2*(strlen(hostname)+1);       
2443                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2444                         return WERR_NOMEM;
2445                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2446                 for (i=0; i<strlen(hostname); i++) {
2447                         (*data)[2*i]=hostname[i];
2448                         (*data)[2*i+1]='\0';
2449                 }                       
2450                 return WERR_OK;
2451         }
2452
2453
2454         return WERR_BADFILE;
2455 }
2456
2457 /********************************************************************
2458  * spoolss_getprinterdata
2459  ********************************************************************/
2460
2461 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2462 {
2463         POLICY_HND      *handle = &q_u->handle;
2464         UNISTR2         *valuename = &q_u->valuename;
2465         uint32          in_size = q_u->size;
2466         uint32          *type = &r_u->type;
2467         uint32          *out_size = &r_u->size;
2468         uint8           **data = &r_u->data;
2469         uint32          *needed = &r_u->needed;
2470         WERROR          status;
2471         fstring         value;
2472         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2473         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2474         int             snum = 0;
2475         
2476         /*
2477          * Reminder: when it's a string, the length is in BYTES
2478          * even if UNICODE is negociated.
2479          *
2480          * JFM, 4/19/1999
2481          */
2482
2483         *out_size = in_size;
2484
2485         /* in case of problem, return some default values */
2486         
2487         *needed = 0;
2488         *type   = 0;
2489         
2490         DEBUG(4,("_spoolss_getprinterdata\n"));
2491         
2492         if ( !Printer ) {
2493                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2494                 status = WERR_BADFID;
2495                 goto done;
2496         }
2497         
2498         unistr2_to_ascii(value, valuename, sizeof(value)-1);
2499         
2500         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2501                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2502         else
2503         {
2504                 if ( !get_printer_snum(p,handle, &snum) ) {
2505                         status = WERR_BADFID;
2506                         goto done;
2507                 }
2508
2509                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2510                 if ( !W_ERROR_IS_OK(status) )
2511                         goto done;
2512
2513                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2514
2515                 if ( strequal(value, "ChangeId") ) {
2516                         *type = REG_DWORD;
2517                         *needed = sizeof(uint32);
2518                         if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2519                                 status = WERR_NOMEM;
2520                                 goto done;
2521                         }
2522                         SIVAL( *data, 0, printer->info_2->changeid );
2523                         status = WERR_OK;
2524                 }
2525                 else
2526                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2527         }
2528
2529         if (*needed > *out_size)
2530                 status = WERR_MORE_DATA;
2531         
2532 done:
2533         if ( !W_ERROR_IS_OK(status) ) 
2534         {
2535                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2536                 
2537                 /* reply this param doesn't exist */
2538                 
2539                 if ( *out_size ) {
2540                         if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2541                                 if ( printer ) 
2542                                         free_a_printer( &printer, 2 );
2543                                 return WERR_NOMEM;
2544                 } 
2545                 } 
2546                 else {
2547                         *data = NULL;
2548                 }
2549         }
2550         
2551         /* cleanup & exit */
2552
2553         if ( printer )
2554                 free_a_printer( &printer, 2 );
2555         
2556         return status;
2557 }
2558
2559 /*********************************************************
2560  Connect to the client machine.
2561 **********************************************************/
2562
2563 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, 
2564                         struct in_addr *client_ip, const char *remote_machine)
2565 {
2566         ZERO_STRUCTP(the_cli);
2567         
2568         if(cli_initialise(the_cli) == NULL) {
2569                 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2570                 return False;
2571         }
2572         
2573         if ( is_zero_ip(*client_ip) ) {
2574                 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2575                         DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2576                         cli_shutdown(the_cli);
2577                 return False;
2578                 }
2579
2580                 if (ismyip(the_cli->dest_ip)) {
2581                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2582                         cli_shutdown(the_cli);
2583                         return False;
2584                 }
2585         }
2586         else {
2587                 the_cli->dest_ip.s_addr = client_ip->s_addr;
2588                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2589                         inet_ntoa(*client_ip) ));
2590         }
2591
2592         if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2593                 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) ));
2594                 cli_shutdown(the_cli);
2595                 return False;
2596         }
2597   
2598         if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2599                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n", 
2600                         remote_machine));
2601                 cli_shutdown(the_cli);
2602                 return False;
2603         }
2604
2605         the_cli->protocol = PROTOCOL_NT1;
2606     
2607         if (!cli_negprot(the_cli)) {
2608                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2609                 cli_shutdown(the_cli);
2610                 return False;
2611         }
2612
2613         if (the_cli->protocol != PROTOCOL_NT1) {
2614                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2615                 cli_shutdown(the_cli);
2616                 return False;
2617         }
2618     
2619         /*
2620          * Do an anonymous session setup.
2621          */
2622     
2623         if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2624                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2625                 cli_shutdown(the_cli);
2626                 return False;
2627         }
2628     
2629         if (!(the_cli->sec_mode & 1)) {
2630                 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2631                 cli_shutdown(the_cli);
2632                 return False;
2633         }
2634     
2635         if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2636                 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) ));
2637                 cli_shutdown(the_cli);
2638                 return False;
2639         }
2640
2641         /*
2642          * Ok - we have an anonymous connection to the IPC$ share.
2643          * Now start the NT Domain stuff :-).
2644          */
2645
2646         if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2647                 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)));
2648                 cli_nt_session_close(the_cli);
2649                 cli_ulogoff(the_cli);
2650                 cli_shutdown(the_cli);
2651                 return False;
2652         } 
2653
2654         return True;
2655 }
2656
2657 /***************************************************************************
2658  Connect to the client.
2659 ****************************************************************************/
2660
2661 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, 
2662                                         uint32 localprinter, uint32 type, 
2663                                         POLICY_HND *handle, struct in_addr *client_ip)
2664 {
2665         WERROR result;
2666
2667         /*
2668          * If it's the first connection, contact the client
2669          * and connect to the IPC$ share anonymously
2670          */
2671         if (smb_connections==0) {
2672                 fstring unix_printer;
2673
2674                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2675
2676                 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2677                         return False;
2678                         
2679                 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2680                 /* Tell the connections db we're now interested in printer
2681                  * notify messages. */
2682                 register_message_flags( True, FLAG_MSG_PRINTING );
2683         }
2684
2685         /* 
2686          * Tell the specific printing tdb we want messages for this printer
2687          * by registering our PID.
2688          */
2689
2690         if (!print_notify_register_pid(snum))
2691                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2692
2693         smb_connections++;
2694
2695         result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter, 
2696                         type, handle);
2697                         
2698         if (!W_ERROR_IS_OK(result))
2699                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2700                         dos_errstr(result)));
2701
2702         return (W_ERROR_IS_OK(result)); 
2703 }
2704
2705 /********************************************************************
2706  * _spoolss_rffpcnex
2707  * ReplyFindFirstPrinterChangeNotifyEx
2708  *
2709  * before replying OK: status=0 a rpc call is made to the workstation
2710  * asking ReplyOpenPrinter 
2711  *
2712  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2713  * called from api_spoolss_rffpcnex
2714  ********************************************************************/
2715
2716 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2717 {
2718         POLICY_HND *handle = &q_u->handle;
2719         uint32 flags = q_u->flags;
2720         uint32 options = q_u->options;
2721         UNISTR2 *localmachine = &q_u->localmachine;
2722         uint32 printerlocal = q_u->printerlocal;
2723         int snum = -1;
2724         SPOOL_NOTIFY_OPTION *option = q_u->option;
2725         struct in_addr client_ip;
2726
2727         /* store the notify value in the printer struct */
2728
2729         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2730
2731         if (!Printer) {
2732                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2733                 return WERR_BADFID;
2734         }
2735
2736         Printer->notify.flags=flags;
2737         Printer->notify.options=options;
2738         Printer->notify.printerlocal=printerlocal;
2739
2740         if (Printer->notify.option)
2741                 free_spool_notify_option(&Printer->notify.option);
2742
2743         Printer->notify.option=dup_spool_notify_option(option);
2744
2745         unistr2_to_ascii(Printer->notify.localmachine, localmachine, 
2746                        sizeof(Printer->notify.localmachine)-1);
2747
2748         /* Connect to the client machine and send a ReplyOpenPrinter */
2749
2750         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2751                 snum = -1;
2752         else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2753                         !get_printer_snum(p, handle, &snum) )
2754                 return WERR_BADFID;
2755                 
2756         client_ip.s_addr = inet_addr(p->conn->client_address);
2757
2758         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2759                                         Printer->notify.printerlocal, 1,
2760                                         &Printer->notify.client_hnd, &client_ip))
2761                 return WERR_SERVER_UNAVAILABLE;
2762
2763         Printer->notify.client_connected=True;
2764
2765         return WERR_OK;
2766 }
2767
2768 /*******************************************************************
2769  * fill a notify_info_data with the servername
2770  ********************************************************************/
2771
2772 void spoolss_notify_server_name(int snum, 
2773                                        SPOOL_NOTIFY_INFO_DATA *data, 
2774                                        print_queue_struct *queue,
2775                                        NT_PRINTER_INFO_LEVEL *printer,
2776                                        TALLOC_CTX *mem_ctx) 
2777 {
2778         pstring temp_name, temp;
2779         uint32 len;
2780
2781         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2782
2783         len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2784
2785         data->notify_data.data.length = len;
2786         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2787
2788         if (!data->notify_data.data.string) {
2789                 data->notify_data.data.length = 0;
2790                 return;
2791         }
2792         
2793         memcpy(data->notify_data.data.string, temp, len);
2794 }
2795
2796 /*******************************************************************
2797  * fill a notify_info_data with the printername (not including the servername).
2798  ********************************************************************/
2799
2800 void spoolss_notify_printer_name(int snum, 
2801                                         SPOOL_NOTIFY_INFO_DATA *data, 
2802                                         print_queue_struct *queue,
2803                                         NT_PRINTER_INFO_LEVEL *printer,
2804                                         TALLOC_CTX *mem_ctx)
2805 {
2806         pstring temp;
2807         uint32 len;
2808                 
2809         /* the notify name should not contain the \\server\ part */
2810         char *p = strrchr(printer->info_2->printername, '\\');
2811
2812         if (!p) {
2813                 p = printer->info_2->printername;
2814         } else {
2815                 p++;
2816         }
2817
2818         len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2819
2820         data->notify_data.data.length = len;
2821         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2822         
2823         if (!data->notify_data.data.string) {
2824                 data->notify_data.data.length = 0;
2825                 return;
2826         }
2827         
2828         memcpy(data->notify_data.data.string, temp, len);
2829 }
2830
2831 /*******************************************************************
2832  * fill a notify_info_data with the servicename
2833  ********************************************************************/
2834
2835 void spoolss_notify_share_name(int snum, 
2836                                       SPOOL_NOTIFY_INFO_DATA *data, 
2837                                       print_queue_struct *queue,
2838                                       NT_PRINTER_INFO_LEVEL *printer,
2839                                       TALLOC_CTX *mem_ctx)
2840 {
2841         pstring temp;
2842         uint32 len;
2843
2844         len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2845
2846         data->notify_data.data.length = len;
2847         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2848         
2849         if (!data->notify_data.data.string) {
2850                 data->notify_data.data.length = 0;
2851                 return;
2852         }
2853         
2854         memcpy(data->notify_data.data.string, temp, len);
2855 }
2856
2857 /*******************************************************************
2858  * fill a notify_info_data with the port name
2859  ********************************************************************/
2860
2861 void spoolss_notify_port_name(int snum, 
2862                                      SPOOL_NOTIFY_INFO_DATA *data, 
2863                                      print_queue_struct *queue,
2864                                      NT_PRINTER_INFO_LEVEL *printer,
2865                                      TALLOC_CTX *mem_ctx)
2866 {
2867         pstring temp;
2868         uint32 len;
2869
2870         /* even if it's strange, that's consistant in all the code */
2871
2872         len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2873
2874         data->notify_data.data.length = len;
2875         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2876         
2877         if (!data->notify_data.data.string) {
2878                 data->notify_data.data.length = 0;
2879                 return;
2880         }
2881         
2882         memcpy(data->notify_data.data.string, temp, len);
2883 }
2884
2885 /*******************************************************************
2886  * fill a notify_info_data with the printername
2887  * but it doesn't exist, have to see what to do
2888  ********************************************************************/
2889
2890 void spoolss_notify_driver_name(int snum, 
2891                                        SPOOL_NOTIFY_INFO_DATA *data,
2892                                        print_queue_struct *queue,
2893                                        NT_PRINTER_INFO_LEVEL *printer,
2894                                        TALLOC_CTX *mem_ctx)
2895 {
2896         pstring temp;
2897         uint32 len;
2898
2899         len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2900
2901         data->notify_data.data.length = len;
2902         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2903         
2904         if (!data->notify_data.data.string) {
2905                 data->notify_data.data.length = 0;
2906                 return;
2907         }
2908         
2909         memcpy(data->notify_data.data.string, temp, len);
2910 }
2911
2912 /*******************************************************************
2913  * fill a notify_info_data with the comment
2914  ********************************************************************/
2915
2916 void spoolss_notify_comment(int snum, 
2917                                    SPOOL_NOTIFY_INFO_DATA *data,
2918                                    print_queue_struct *queue,
2919                                    NT_PRINTER_INFO_LEVEL *printer,
2920                                    TALLOC_CTX *mem_ctx)
2921 {
2922         pstring temp;
2923         uint32 len;
2924
2925         if (*printer->info_2->comment == '\0')
2926                 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2927         else
2928                 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2929
2930         data->notify_data.data.length = len;
2931         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2932         
2933         if (!data->notify_data.data.string) {
2934                 data->notify_data.data.length = 0;
2935                 return;
2936         }
2937         
2938         memcpy(data->notify_data.data.string, temp, len);
2939 }
2940
2941 /*******************************************************************
2942  * fill a notify_info_data with the comment
2943  * location = "Room 1, floor 2, building 3"
2944  ********************************************************************/
2945
2946 void spoolss_notify_location(int snum, 
2947                                     SPOOL_NOTIFY_INFO_DATA *data,
2948                                     print_queue_struct *queue,
2949                                     NT_PRINTER_INFO_LEVEL *printer,
2950                                     TALLOC_CTX *mem_ctx)
2951 {
2952         pstring temp;
2953         uint32 len;
2954
2955         len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2956
2957         data->notify_data.data.length = len;
2958         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2959         
2960         if (!data->notify_data.data.string) {
2961                 data->notify_data.data.length = 0;
2962                 return;
2963         }
2964         
2965         memcpy(data->notify_data.data.string, temp, len);
2966 }
2967
2968 /*******************************************************************
2969  * fill a notify_info_data with the device mode
2970  * jfm:xxxx don't to it for know but that's a real problem !!!
2971  ********************************************************************/
2972
2973 static void spoolss_notify_devmode(int snum, 
2974                                    SPOOL_NOTIFY_INFO_DATA *data,
2975                                    print_queue_struct *queue,
2976                                    NT_PRINTER_INFO_LEVEL *printer,
2977                                    TALLOC_CTX *mem_ctx)
2978 {
2979 }
2980
2981 /*******************************************************************
2982  * fill a notify_info_data with the separator file name
2983  ********************************************************************/
2984
2985 void spoolss_notify_sepfile(int snum, 
2986                                    SPOOL_NOTIFY_INFO_DATA *data, 
2987                                    print_queue_struct *queue,
2988                                    NT_PRINTER_INFO_LEVEL *printer,
2989                                    TALLOC_CTX *mem_ctx)
2990 {
2991         pstring temp;
2992         uint32 len;
2993
2994         len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2995
2996         data->notify_data.data.length = len;
2997         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2998         
2999         if (!data->notify_data.data.string) {
3000                 data->notify_data.data.length = 0;
3001                 return;
3002         }
3003         
3004         memcpy(data->notify_data.data.string, temp, len);
3005 }
3006
3007 /*******************************************************************
3008  * fill a notify_info_data with the print processor
3009  * jfm:xxxx return always winprint to indicate we don't do anything to it
3010  ********************************************************************/
3011
3012 void spoolss_notify_print_processor(int snum, 
3013                                            SPOOL_NOTIFY_INFO_DATA *data,
3014                                            print_queue_struct *queue,
3015                                            NT_PRINTER_INFO_LEVEL *printer,
3016                                            TALLOC_CTX *mem_ctx)
3017 {
3018         pstring temp;
3019         uint32 len;
3020
3021         len = rpcstr_push(temp,  printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3022
3023         data->notify_data.data.length = len;
3024         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3025         
3026         if (!data->notify_data.data.string) {
3027                 data->notify_data.data.length = 0;
3028                 return;
3029         }
3030         
3031         memcpy(data->notify_data.data.string, temp, len);
3032 }
3033
3034 /*******************************************************************
3035  * fill a notify_info_data with the print processor options
3036  * jfm:xxxx send an empty string
3037  ********************************************************************/
3038
3039 void spoolss_notify_parameters(int snum, 
3040                                       SPOOL_NOTIFY_INFO_DATA *data,
3041                                       print_queue_struct *queue,
3042                                       NT_PRINTER_INFO_LEVEL *printer,
3043                                       TALLOC_CTX *mem_ctx)
3044 {
3045         pstring temp;
3046         uint32 len;
3047
3048         len = rpcstr_push(temp,  printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3049
3050         data->notify_data.data.length = len;
3051         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3052         
3053         if (!data->notify_data.data.string) {
3054                 data->notify_data.data.length = 0;
3055                 return;
3056         }
3057         
3058         memcpy(data->notify_data.data.string, temp, len);
3059 }
3060
3061 /*******************************************************************
3062  * fill a notify_info_data with the data type
3063  * jfm:xxxx always send RAW as data type
3064  ********************************************************************/
3065
3066 void spoolss_notify_datatype(int snum, 
3067                                     SPOOL_NOTIFY_INFO_DATA *data,
3068                                     print_queue_struct *queue,
3069                                     NT_PRINTER_INFO_LEVEL *printer,
3070                                     TALLOC_CTX *mem_ctx)
3071 {
3072         pstring temp;
3073         uint32 len;
3074
3075         len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3076
3077         data->notify_data.data.length = len;
3078         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3079         
3080         if (!data->notify_data.data.string) {
3081                 data->notify_data.data.length = 0;
3082                 return;
3083         }
3084         
3085         memcpy(data->notify_data.data.string, temp, len);
3086 }
3087
3088 /*******************************************************************
3089  * fill a notify_info_data with the security descriptor
3090  * jfm:xxxx send an null pointer to say no security desc
3091  * have to implement security before !
3092  ********************************************************************/
3093
3094 static void spoolss_notify_security_desc(int snum, 
3095                                          SPOOL_NOTIFY_INFO_DATA *data,
3096                                          print_queue_struct *queue,
3097                                          NT_PRINTER_INFO_LEVEL *printer,