5233d6c252df040734f2a77bea58473b1bee2d53
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean Fran├žois Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30
31 extern userdom_struct current_user_info;
32
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
35
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
38 #endif
39
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42
43
44 /* Table to map the driver version */
45 /* to OS */
46 static const char * drv_ver_to_os[] = {
47         "WIN9X",   /* driver version/cversion 0 */
48         "",        /* unused ? */
49         "WINNT",   /* driver version/cversion 2 */
50         "WIN2K",   /* driver version/cversion 3 */
51 };
52
53 static const char *get_drv_ver_to_os(int ver)
54 {
55         if (ver < 0 || ver > 3)
56                 return "";
57         return drv_ver_to_os[ver];
58 }
59
60 struct table_node {
61         const char    *long_archi;
62         const char    *short_archi;
63         int     version;
64 };
65
66 static Printer_entry *printers_list;
67
68 typedef struct _counter_printer_0 {
69         struct _counter_printer_0 *next;
70         struct _counter_printer_0 *prev;
71         
72         int snum;
73         uint32 counter;
74 } counter_printer_0;
75
76 static counter_printer_0 *counter_list;
77
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
80
81
82 /* in printing/nt_printing.c */
83
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
85
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
88
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
91 {
92         switch (v) {
93         case LPQ_QUEUED:
94                 return 0;
95         case LPQ_PAUSED:
96                 return JOB_STATUS_PAUSED;
97         case LPQ_SPOOLING:
98                 return JOB_STATUS_SPOOLING;
99         case LPQ_PRINTING:
100                 return JOB_STATUS_PRINTING;
101         case LPQ_ERROR:
102                 return JOB_STATUS_ERROR;
103         case LPQ_DELETING:
104                 return JOB_STATUS_DELETING;
105         case LPQ_OFFLINE:
106                 return JOB_STATUS_OFFLINE;
107         case LPQ_PAPEROUT:
108                 return JOB_STATUS_PAPEROUT;
109         case LPQ_PRINTED:
110                 return JOB_STATUS_PRINTED;
111         case LPQ_DELETED:
112                 return JOB_STATUS_DELETED;
113         case LPQ_BLOCKED:
114                 return JOB_STATUS_BLOCKED;
115         case LPQ_USER_INTERVENTION:
116                 return JOB_STATUS_USER_INTERVENTION;
117         }
118         return 0;
119 }
120
121 static int nt_printq_status(int v)
122 {
123         switch (v) {
124         case LPQ_PAUSED:
125                 return PRINTER_STATUS_PAUSED;
126         case LPQ_QUEUED:
127         case LPQ_SPOOLING:
128         case LPQ_PRINTING:
129                 return 0;
130         }
131         return 0;
132 }
133
134 /****************************************************************************
135  Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
137
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
139 {
140         if (*pp == NULL)
141                 return;
142
143         SAFE_FREE((*pp)->ctr.type);
144         SAFE_FREE(*pp);
145 }
146
147 /***************************************************************************
148  Disconnect from the client
149 ****************************************************************************/
150
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
152 {
153         WERROR result;
154
155         /* 
156          * Tell the specific printing tdb we no longer want messages for this printer
157          * by deregistering our PID.
158          */
159
160         if (!print_notify_deregister_pid(snum))
161                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162
163         /* weird if the test succeds !!! */
164         if (smb_connections==0) {
165                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166                 return;
167         }
168
169         result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
170         
171         if (!W_ERROR_IS_OK(result))
172                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173                         dos_errstr(result)));
174
175         /* if it's the last connection, deconnect the IPC$ share */
176         if (smb_connections==1) {
177                 cli_shutdown(notify_cli_pipe->cli);
178                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
179                 message_deregister(MSG_PRINTER_NOTIFY2);
180
181                 /* Tell the connections db we're no longer interested in
182                  * printer notify messages. */
183
184                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
185         }
186
187         smb_connections--;
188 }
189
190 /****************************************************************************
191  Functions to free a printer entry datastruct.
192 ****************************************************************************/
193
194 static void free_printer_entry(void *ptr)
195 {
196         Printer_entry *Printer = (Printer_entry *)ptr;
197
198         if (Printer->notify.client_connected==True) {
199                 int snum = -1;
200
201                 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
202                         snum = -1;
203                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
204                 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
205                         snum = print_queue_snum(Printer->sharename);
206                         if (snum != -1)
207                                 srv_spoolss_replycloseprinter(snum,
208                                                 &Printer->notify.client_hnd);
209                 }
210         }
211
212         Printer->notify.flags=0;
213         Printer->notify.options=0;
214         Printer->notify.localmachine[0]='\0';
215         Printer->notify.printerlocal=0;
216         free_spool_notify_option(&Printer->notify.option);
217         Printer->notify.option=NULL;
218         Printer->notify.client_connected=False;
219         
220         free_nt_devicemode( &Printer->nt_devmode );
221         free_a_printer( &Printer->printer_info, 2 );
222         
223         talloc_destroy( Printer->ctx );
224
225         /* Remove from the internal list. */
226         DLIST_REMOVE(printers_list, Printer);
227
228         SAFE_FREE(Printer);
229 }
230
231 /****************************************************************************
232  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
233 ****************************************************************************/
234
235 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 {
237         SPOOL_NOTIFY_OPTION *new_sp = NULL;
238
239         if (!sp)
240                 return NULL;
241
242         new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
243         if (!new_sp)
244                 return NULL;
245
246         *new_sp = *sp;
247
248         if (sp->ctr.count) {
249                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250
251                 if (!new_sp->ctr.type) {
252                         SAFE_FREE(new_sp);
253                         return NULL;
254                 }
255         }
256
257         return new_sp;
258 }
259
260 /****************************************************************************
261   find printer index by handle
262 ****************************************************************************/
263
264 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 {
266         Printer_entry *find_printer = NULL;
267
268         if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
269                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
270                 return NULL;
271         }
272
273         return find_printer;
274 }
275
276 /****************************************************************************
277  Close printer index by handle.
278 ****************************************************************************/
279
280 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
281 {
282         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
283
284         if (!Printer) {
285                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
286                 return False;
287         }
288
289         close_policy_hnd(p, hnd);
290
291         return True;
292 }       
293
294 /****************************************************************************
295  Delete a printer given a handle.
296 ****************************************************************************/
297 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
298 {
299         char *cmd = lp_deleteprinter_cmd();
300         pstring command;
301         int ret;
302         SE_PRIV se_printop = SE_PRINT_OPERATOR;
303         BOOL is_print_op = False;
304                 
305         /* can't fail if we don't try */
306         
307         if ( !*cmd )
308                 return WERR_OK;
309                 
310         pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
311
312         if ( token )
313                 is_print_op = user_has_privileges( token, &se_printop );
314         
315         DEBUG(10,("Running [%s]\n", command));
316
317         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
318         
319         if ( is_print_op )
320                 become_root();
321                 
322         if ( (ret = smbrun(command, NULL)) == 0 ) {
323                 /* Tell everyone we updated smb.conf. */
324                 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
325         }
326                 
327         if ( is_print_op )
328                 unbecome_root();
329
330         /********** END SePrintOperatorPrivlege BLOCK **********/
331         
332         DEBUGADD(10,("returned [%d]\n", ret));
333
334         if (ret != 0) 
335                 return WERR_BADFID; /* What to return here? */
336
337         /* go ahead and re-read the services immediately */
338         reload_services( False );
339         
340         if ( lp_servicenumber( sharename )  < 0 )
341                 return WERR_ACCESS_DENIED;
342                 
343         return WERR_OK;
344 }
345
346 /****************************************************************************
347  Delete a printer given a handle.
348 ****************************************************************************/
349
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
351 {
352         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
353
354         if (!Printer) {
355                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
356                 return WERR_BADFID;
357         }
358
359         /* 
360          * It turns out that Windows allows delete printer on a handle
361          * opened by an admin user, then used on a pipe handle created
362          * by an anonymous user..... but they're working on security.... riiight !
363          * JRA.
364          */
365
366         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368                 return WERR_ACCESS_DENIED;
369         }
370         
371         /* this does not need a become root since the access check has been 
372            done on the handle already */
373            
374         if (del_a_printer( Printer->sharename ) != 0) {
375                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
376                 return WERR_BADFID;
377         }
378
379         return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
380 }
381
382 /****************************************************************************
383  Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
385
386 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
387 {
388         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
389                 
390         if (!Printer) {
391                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
392                 return False;
393         }
394         
395         switch (Printer->printer_type) {
396                 case PRINTER_HANDLE_IS_PRINTER:         
397                         DEBUG(4,("short name:%s\n", Printer->sharename));                       
398                         *number = print_queue_snum(Printer->sharename);
399                         return (*number != -1);
400                 case PRINTER_HANDLE_IS_PRINTSERVER:
401                         return False;
402                 default:
403                         return False;
404         }
405 }
406
407 /****************************************************************************
408  Set printer handle type.
409  Check if it's \\server or \\server\printer
410 ****************************************************************************/
411
412 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
413 {
414         DEBUG(3,("Setting printer type=%s\n", handlename));
415
416         if ( strlen(handlename) < 3 ) {
417                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
418                 return False;
419         }
420
421         /* it's a print server */
422         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
423                 DEBUGADD(4,("Printer is a print server\n"));
424                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;          
425         }
426         /* it's a printer */
427         else {
428                 DEBUGADD(4,("Printer is a printer\n"));
429                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
430         }
431
432         return True;
433 }
434
435 /****************************************************************************
436  Set printer handle name.
437 ****************************************************************************/
438
439 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
440 {
441         int snum;
442         int n_services=lp_numservices();
443         char *aprinter, *printername;
444         const char *servername;
445         fstring sname;
446         BOOL found=False;
447         NT_PRINTER_INFO_LEVEL *printer;
448         WERROR result;
449         
450         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
451
452         aprinter = handlename;
453         if ( *handlename == '\\' ) {
454                 servername = handlename + 2;
455                 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
456                         *aprinter = '\0';
457                         aprinter++;
458                 }
459         }
460         else {
461                 servername = "";
462         }
463         
464         /* save the servername to fill in replies on this handle */
465         
466         if ( !is_myname_or_ipaddr( servername ) )
467                 return False;
468
469         fstrcpy( Printer->servername, servername );
470         
471         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
472                 return True;
473
474         if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
475                 return False;
476
477         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
478
479         /* Search all sharenames first as this is easier than pulling 
480            the printer_info_2 off of disk */
481         
482         snum = find_service(aprinter);
483         
484         if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
485                 found = True;
486                 fstrcpy( sname, aprinter );
487         }
488
489         /* do another loop to look for printernames */
490         
491         for (snum=0; !found && snum<n_services; snum++) {
492
493                 /* no point in checking if this is not a printer or 
494                    we aren't allowing printername != sharename */
495
496                 if ( !(lp_snum_ok(snum) 
497                         && lp_print_ok(snum) 
498                         && !lp_force_printername(snum)) ) 
499                 {
500                         continue;
501                 }
502                 
503                 fstrcpy(sname, lp_servicename(snum));
504
505                 printer = NULL;
506                 result = get_a_printer( NULL, &printer, 2, sname );
507                 if ( !W_ERROR_IS_OK(result) ) {
508                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
509                                 sname, dos_errstr(result)));
510                         continue;
511                 }
512                 
513                 /* printername is always returned as \\server\printername */
514                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
515                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
516                                 printer->info_2->printername));
517                         free_a_printer( &printer, 2);
518                         continue;
519                 }
520                 
521                 printername++;
522                 
523                 if ( strequal(printername, aprinter) ) {
524                         found = True;
525                 }
526                 
527                 DEBUGADD(10, ("printername: %s\n", printername));
528                 
529                 free_a_printer( &printer, 2);
530         }
531
532         if ( !found ) {
533                 DEBUGADD(4,("Printer not found\n"));
534                 return False;
535         }
536         
537         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
538
539         fstrcpy(Printer->sharename, sname);
540
541         return True;
542 }
543
544 /****************************************************************************
545  Find first available printer slot. creates a printer handle for you.
546  ****************************************************************************/
547
548 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
549 {
550         Printer_entry *new_printer;
551
552         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
553
554         if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
555                 return False;
556
557         ZERO_STRUCTP(new_printer);
558         
559         if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
560                 SAFE_FREE(new_printer);
561                 return False;
562         }
563         
564         /* Add to the internal list. */
565         DLIST_ADD(printers_list, new_printer);
566         
567         new_printer->notify.option=NULL;
568                                 
569         if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
570                 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
571                 close_printer_handle(p, hnd);
572                 return False;
573         }
574         
575         if (!set_printer_hnd_printertype(new_printer, name)) {
576                 close_printer_handle(p, hnd);
577                 return False;
578         }
579         
580         if (!set_printer_hnd_name(new_printer, name)) {
581                 close_printer_handle(p, hnd);
582                 return False;
583         }
584
585         new_printer->access_granted = access_granted;
586
587         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
588
589         return True;
590 }
591
592 /***************************************************************************
593  check to see if the client motify handle is monitoring the notification
594  given by (notify_type, notify_field).
595  **************************************************************************/
596
597 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
598                                       uint16 notify_field)
599 {
600         return True;
601 }
602
603 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
604                                 uint16 notify_field)
605 {
606         SPOOL_NOTIFY_OPTION *option = p->notify.option;
607         uint32 i, j;
608
609         /* 
610          * Flags should always be zero when the change notify
611          * is registered by the client's spooler.  A user Win32 app
612          * might use the flags though instead of the NOTIFY_OPTION_INFO 
613          * --jerry
614          */
615
616         if (!option) {
617                 return False;
618         }
619
620         if (p->notify.flags)
621                 return is_monitoring_event_flags(
622                         p->notify.flags, notify_type, notify_field);
623
624         for (i = 0; i < option->count; i++) {
625                 
626                 /* Check match for notify_type */
627                 
628                 if (option->ctr.type[i].type != notify_type)
629                         continue;
630
631                 /* Check match for field */
632                 
633                 for (j = 0; j < option->ctr.type[i].count; j++) {
634                         if (option->ctr.type[i].fields[j] == notify_field) {
635                                 return True;
636                         }
637                 }
638         }
639         
640         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
641                    p->servername, p->sharename, notify_type, notify_field));
642         
643         return False;
644 }
645
646 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
647
648 static void notify_one_value(struct spoolss_notify_msg *msg,
649                              SPOOL_NOTIFY_INFO_DATA *data,
650                              TALLOC_CTX *mem_ctx)
651 {
652         data->notify_data.value[0] = msg->notify.value[0];
653         data->notify_data.value[1] = 0;
654 }
655
656 static void notify_string(struct spoolss_notify_msg *msg,
657                           SPOOL_NOTIFY_INFO_DATA *data,
658                           TALLOC_CTX *mem_ctx)
659 {
660         UNISTR2 unistr;
661         
662         /* The length of the message includes the trailing \0 */
663
664         init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
665
666         data->notify_data.data.length = msg->len * 2;
667         data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
668
669         if (!data->notify_data.data.string) {
670                 data->notify_data.data.length = 0;
671                 return;
672         }
673         
674         memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
675 }
676
677 static void notify_system_time(struct spoolss_notify_msg *msg,
678                                SPOOL_NOTIFY_INFO_DATA *data,
679                                TALLOC_CTX *mem_ctx)
680 {
681         SYSTEMTIME systime;
682         prs_struct ps;
683
684         if (msg->len != sizeof(time_t)) {
685                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
686                           msg->len));
687                 return;
688         }
689
690         if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
691                 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
692                 return;
693         }
694
695         if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
696                 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
697                 return;
698         }
699
700         if (!spoolss_io_system_time("", &ps, 0, &systime))
701                 return;
702
703         data->notify_data.data.length = prs_offset(&ps);
704         data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
705
706         prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
707
708         prs_mem_free(&ps);
709 }
710
711 struct notify2_message_table {
712         const char *name;
713         void (*fn)(struct spoolss_notify_msg *msg,
714                    SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
715 };
716
717 static struct notify2_message_table printer_notify_table[] = {
718         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
719         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
720         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
721         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
722         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
723         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
724         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
725         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
726         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
727         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
728         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
729         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
730         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
731         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
732         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
733         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
734         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
735         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
736         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
737 };
738
739 static struct notify2_message_table job_notify_table[] = {
740         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
741         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
742         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
743         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
744         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
745         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
746         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
747         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
748         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
749         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
750         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
751         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
752         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
753         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
754         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
755         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
756         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
757         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
758         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
759         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
760         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
761         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
762         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
763         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
764 };
765
766
767 /***********************************************************************
768  Allocate talloc context for container object
769  **********************************************************************/
770  
771 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
772 {
773         if ( !ctr )
774                 return;
775
776         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
777                 
778         return;
779 }
780
781 /***********************************************************************
782  release all allocated memory and zero out structure
783  **********************************************************************/
784  
785 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
786 {
787         if ( !ctr )
788                 return;
789
790         if ( ctr->ctx )
791                 talloc_destroy(ctr->ctx);
792                 
793         ZERO_STRUCTP(ctr);
794                 
795         return;
796 }
797
798 /***********************************************************************
799  **********************************************************************/
800  
801 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
802 {
803         if ( !ctr )
804                 return NULL;
805                 
806         return ctr->ctx;
807 }
808
809 /***********************************************************************
810  **********************************************************************/
811  
812 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
813 {
814         if ( !ctr || !ctr->msg_groups )
815                 return NULL;
816         
817         if ( idx >= ctr->num_groups )
818                 return NULL;
819                 
820         return &ctr->msg_groups[idx];
821
822 }
823
824 /***********************************************************************
825  How many groups of change messages do we have ?
826  **********************************************************************/
827  
828 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
829 {
830         if ( !ctr )
831                 return 0;
832                 
833         return ctr->num_groups;
834 }
835
836 /***********************************************************************
837  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
838  **********************************************************************/
839  
840 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
841 {
842         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
843         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
844         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
845         int                             i, new_slot;
846         
847         if ( !ctr || !msg )
848                 return 0;
849         
850         /* loop over all groups looking for a matching printer name */
851         
852         for ( i=0; i<ctr->num_groups; i++ ) {
853                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
854                         break;
855         }
856         
857         /* add a new group? */
858         
859         if ( i == ctr->num_groups ) {
860                 ctr->num_groups++;
861
862                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
863                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
864                         return 0;
865                 }
866                 ctr->msg_groups = groups;
867
868                 /* clear the new entry and set the printer name */
869                 
870                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
871                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
872         }
873         
874         /* add the change messages; 'i' is the correct index now regardless */
875         
876         msg_grp = &ctr->msg_groups[i];
877         
878         msg_grp->num_msgs++;
879         
880         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
881                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
882                 return 0;
883         }
884         msg_grp->msgs = msg_list;
885         
886         new_slot = msg_grp->num_msgs-1;
887         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
888         
889         /* need to allocate own copy of data */
890         
891         if ( msg->len != 0 ) 
892                 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
893         
894         return ctr->num_groups;
895 }
896
897 /***********************************************************************
898  Send a change notication message on all handles which have a call 
899  back registered
900  **********************************************************************/
901
902 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
903 {
904         Printer_entry            *p;
905         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
906         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
907         SPOOLSS_NOTIFY_MSG       *messages;
908         int                      sending_msg_count;
909         
910         if ( !msg_group ) {
911                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
912                 return;
913         }
914         
915         messages = msg_group->msgs;
916         
917         if ( !messages ) {
918                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
919                 return;
920         }
921         
922         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
923         
924         /* loop over all printers */
925         
926         for (p = printers_list; p; p = p->next) {
927                 SPOOL_NOTIFY_INFO_DATA *data;
928                 uint32  data_len = 0;
929                 uint32  id;
930                 int     i;
931
932                 /* Is there notification on this handle? */
933
934                 if ( !p->notify.client_connected )
935                         continue;
936
937                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
938
939                 /* For this printer?  Print servers always receive 
940                    notifications. */
941
942                 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER )  &&
943                     ( !strequal(msg_group->printername, p->sharename) ) )
944                         continue;
945
946                 DEBUG(10,("Our printer\n"));
947                 
948                 /* allocate the max entries possible */
949                 
950                 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
951                 ZERO_STRUCTP(data);
952                 
953                 /* build the array of change notifications */
954                 
955                 sending_msg_count = 0;
956                 
957                 for ( i=0; i<msg_group->num_msgs; i++ ) {
958                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
959                         
960                         /* Are we monitoring this event? */
961
962                         if (!is_monitoring_event(p, msg->type, msg->field))
963                                 continue;
964
965                         sending_msg_count++;
966                         
967                         
968                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
969                                 msg->type, msg->field, p->sharename));
970
971                         /* 
972                          * if the is a printer notification handle and not a job notification 
973                          * type, then set the id to 0.  Other wise just use what was specified
974                          * in the message.  
975                          *
976                          * When registering change notification on a print server handle 
977                          * we always need to send back the id (snum) matching the printer
978                          * for which the change took place.  For change notify registered
979                          * on a printer handle, this does not matter and the id should be 0.
980                          *
981                          * --jerry
982                          */
983
984                         if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
985                                 id = 0;
986                         else
987                                 id = msg->id;
988
989
990                         /* Convert unix jobid to smb jobid */
991
992                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
993                                 id = sysjob_to_jobid(msg->id);
994
995                                 if (id == -1) {
996                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
997                                         goto done;
998                                 }
999                         }
1000
1001                         construct_info_data( &data[data_len], msg->type, msg->field, id );
1002
1003                         switch(msg->type) {
1004                         case PRINTER_NOTIFY_TYPE:
1005                                 if ( printer_notify_table[msg->field].fn )
1006                                         printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1007                                 break;
1008                         
1009                         case JOB_NOTIFY_TYPE:
1010                                 if ( job_notify_table[msg->field].fn )
1011                                         job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1012                                 break;
1013
1014                         default:
1015                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1016                                 goto done;
1017                         }
1018
1019                         data_len++;
1020                 }
1021
1022                 if ( sending_msg_count ) {
1023                         rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd, 
1024                                         data_len, data, p->notify.change, 0 );
1025                 }
1026         }
1027         
1028 done:
1029         DEBUG(8,("send_notify2_changes: Exit...\n"));
1030         return;
1031 }
1032
1033 /***********************************************************************
1034  **********************************************************************/
1035
1036 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1037 {
1038
1039         uint32 tv_sec, tv_usec;
1040         size_t offset = 0;
1041
1042         /* Unpack message */
1043
1044         offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1045                              msg->printer);
1046         
1047         offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1048                                 &tv_sec, &tv_usec,
1049                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1050
1051         if (msg->len == 0)
1052                 tdb_unpack((char *)buf + offset, len - offset, "dd",
1053                            &msg->notify.value[0], &msg->notify.value[1]);
1054         else
1055                 tdb_unpack((char *)buf + offset, len - offset, "B", 
1056                            &msg->len, &msg->notify.data);
1057
1058         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1059                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1060
1061         tv->tv_sec = tv_sec;
1062         tv->tv_usec = tv_usec;
1063
1064         if (msg->len == 0)
1065                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1066                           msg->notify.value[1]));
1067         else
1068                 dump_data(3, msg->notify.data, msg->len);
1069
1070         return True;
1071 }
1072
1073 /********************************************************************
1074  Receive a notify2 message list
1075  ********************************************************************/
1076
1077 static void receive_notify2_message_list(int msg_type, struct process_id src,
1078                                          void *msg, size_t len)
1079 {
1080         size_t                  msg_count, i;
1081         char                    *buf = (char *)msg;
1082         char                    *msg_ptr;
1083         size_t                  msg_len;
1084         SPOOLSS_NOTIFY_MSG      notify;
1085         SPOOLSS_NOTIFY_MSG_CTR  messages;
1086         int                     num_groups;
1087
1088         if (len < 4) {
1089                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1090                 return;
1091         }
1092         
1093         msg_count = IVAL(buf, 0);
1094         msg_ptr = buf + 4;
1095
1096         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1097
1098         if (msg_count == 0) {
1099                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1100                 return;
1101         }
1102
1103         /* initialize the container */
1104         
1105         ZERO_STRUCT( messages );
1106         notify_msg_ctr_init( &messages );
1107         
1108         /* 
1109          * build message groups for each printer identified
1110          * in a change_notify msg.  Remember that a PCN message
1111          * includes the handle returned for the srv_spoolss_replyopenprinter()
1112          * call.  Therefore messages are grouped according to printer handle.
1113          */
1114          
1115         for ( i=0; i<msg_count; i++ ) {
1116                 struct timeval msg_tv;
1117
1118                 if (msg_ptr + 4 - buf > len) {
1119                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1120                         return;
1121                 }
1122
1123                 msg_len = IVAL(msg_ptr,0);
1124                 msg_ptr += 4;
1125
1126                 if (msg_ptr + msg_len - buf > len) {
1127                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1128                         return;
1129                 }
1130                 
1131                 /* unpack messages */
1132                 
1133                 ZERO_STRUCT( notify );
1134                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1135                 msg_ptr += msg_len;
1136
1137                 /* add to correct list in container */
1138                 
1139                 notify_msg_ctr_addmsg( &messages, &notify );
1140                 
1141                 /* free memory that might have been allocated by notify2_unpack_msg() */
1142                 
1143                 if ( notify.len != 0 )
1144                         SAFE_FREE( notify.notify.data );
1145         }
1146         
1147         /* process each group of messages */
1148         
1149         num_groups = notify_msg_ctr_numgroups( &messages );
1150         for ( i=0; i<num_groups; i++ )
1151                 send_notify2_changes( &messages, i );
1152         
1153         
1154         /* cleanup */
1155                 
1156         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1157                 
1158         notify_msg_ctr_destroy( &messages );
1159         
1160         return;
1161 }
1162
1163 /********************************************************************
1164  Send a message to ourself about new driver being installed
1165  so we can upgrade the information for each printer bound to this
1166  driver
1167  ********************************************************************/
1168  
1169 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1170 {
1171         int len = strlen(drivername);
1172         
1173         if (!len)
1174                 return False;
1175
1176         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1177                 drivername));
1178                 
1179         message_send_pid(pid_to_procid(sys_getpid()),
1180                          MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1181
1182         return True;
1183 }
1184
1185 /**********************************************************************
1186  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1187  over all printers, upgrading ones as necessary 
1188  **********************************************************************/
1189  
1190 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1191 {
1192         fstring drivername;
1193         int snum;
1194         int n_services = lp_numservices();
1195         
1196         len = MIN(len,sizeof(drivername)-1);
1197         strncpy(drivername, buf, len);
1198         
1199         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1200
1201         /* Iterate the printer list */
1202         
1203         for (snum=0; snum<n_services; snum++)
1204         {
1205                 if (lp_snum_ok(snum) && lp_print_ok(snum) ) 
1206                 {
1207                         WERROR result;
1208                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1209                         
1210                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1211                         if (!W_ERROR_IS_OK(result))
1212                                 continue;
1213                                 
1214                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername)) 
1215                         {
1216                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1217                                 
1218                                 /* all we care about currently is the change_id */
1219                                 
1220                                 result = mod_a_printer(printer, 2);
1221                                 if (!W_ERROR_IS_OK(result)) {
1222                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n", 
1223                                                 dos_errstr(result)));
1224                                 }
1225                         }
1226                         
1227                         free_a_printer(&printer, 2);                    
1228                 }
1229         }
1230         
1231         /* all done */  
1232 }
1233
1234 /********************************************************************
1235  Update the cache for all printq's with a registered client 
1236  connection
1237  ********************************************************************/
1238
1239 void update_monitored_printq_cache( void )
1240 {
1241         Printer_entry *printer = printers_list;
1242         int snum;
1243         
1244         /* loop through all printers and update the cache where 
1245            client_connected == True */
1246         while ( printer ) 
1247         {
1248                 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER) 
1249                         && printer->notify.client_connected ) 
1250                 {
1251                         snum = print_queue_snum(printer->sharename);
1252                         print_queue_status( snum, NULL, NULL );
1253                 }
1254                 
1255                 printer = printer->next;
1256         }
1257         
1258         return;
1259 }
1260 /********************************************************************
1261  Send a message to ourself about new driver being installed
1262  so we can upgrade the information for each printer bound to this
1263  driver
1264  ********************************************************************/
1265  
1266 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1267 {
1268         int len = strlen(drivername);
1269         
1270         if (!len)
1271                 return False;
1272
1273         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1274                 drivername));
1275                 
1276         message_send_pid(pid_to_procid(sys_getpid()),
1277                          MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1278
1279         return True;
1280 }
1281
1282 /**********************************************************************
1283  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1284  over all printers, resetting printer data as neessary 
1285  **********************************************************************/
1286  
1287 void reset_all_printerdata(int msg_type, struct process_id src,
1288                            void *buf, size_t len)
1289 {
1290         fstring drivername;
1291         int snum;
1292         int n_services = lp_numservices();
1293         
1294         len = MIN( len, sizeof(drivername)-1 );
1295         strncpy( drivername, buf, len );
1296         
1297         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1298
1299         /* Iterate the printer list */
1300         
1301         for ( snum=0; snum<n_services; snum++ )
1302         {
1303                 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) 
1304                 {
1305                         WERROR result;
1306                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1307                         
1308                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1309                         if ( !W_ERROR_IS_OK(result) )
1310                                 continue;
1311                                 
1312                         /* 
1313                          * if the printer is bound to the driver, 
1314                          * then reset to the new driver initdata 
1315                          */
1316                         
1317                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) ) 
1318                         {
1319                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1320                                 
1321                                 if ( !set_driver_init(printer, 2) ) {
1322                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1323                                                 printer->info_2->printername, printer->info_2->drivername));
1324                                 }       
1325                                 
1326                                 result = mod_a_printer( printer, 2 );
1327                                 if ( !W_ERROR_IS_OK(result) ) {
1328                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n", 
1329                                                 get_dos_error_msg(result)));
1330                                 }
1331                         }
1332                         
1333                         free_a_printer( &printer, 2 );
1334                 }
1335         }
1336         
1337         /* all done */  
1338         
1339         return;
1340 }
1341
1342 /********************************************************************
1343  Copy routines used by convert_to_openprinterex()
1344  *******************************************************************/
1345
1346 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1347 {
1348         DEVICEMODE *d;
1349         int len;
1350
1351         if (!devmode)
1352                 return NULL;
1353                 
1354         DEBUG (8,("dup_devmode\n"));
1355         
1356         /* bulk copy first */
1357         
1358         d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1359         if (!d)
1360                 return NULL;
1361                 
1362         /* dup the pointer members separately */
1363         
1364         len = unistrlen(devmode->devicename.buffer);
1365         if (len != -1) {
1366                 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1367                 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1368                         return NULL;
1369         }
1370                 
1371
1372         len = unistrlen(devmode->formname.buffer);
1373         if (len != -1) {
1374                 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1375                 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1376                         return NULL;
1377         }
1378
1379         d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1380         
1381         return d;
1382 }
1383
1384 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1385 {
1386         if (!new_ctr || !ctr)
1387                 return;
1388                 
1389         DEBUG(8,("copy_devmode_ctr\n"));
1390         
1391         new_ctr->size = ctr->size;
1392         new_ctr->devmode_ptr = ctr->devmode_ptr;
1393         
1394         if(ctr->devmode_ptr)
1395                 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1396 }
1397
1398 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1399 {
1400         if (!new_def || !def)
1401                 return;
1402         
1403         DEBUG(8,("copy_printer_defaults\n"));
1404         
1405         new_def->datatype_ptr = def->datatype_ptr;
1406         
1407         if (def->datatype_ptr)
1408                 copy_unistr2(&new_def->datatype, &def->datatype);
1409         
1410         copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1411         
1412         new_def->access_required = def->access_required;
1413 }
1414
1415 /********************************************************************
1416  * Convert a SPOOL_Q_OPEN_PRINTER structure to a 
1417  * SPOOL_Q_OPEN_PRINTER_EX structure
1418  ********************************************************************/
1419
1420 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1421 {
1422         if (!q_u_ex || !q_u)
1423                 return WERR_OK;
1424
1425         DEBUG(8,("convert_to_openprinterex\n"));
1426                                 
1427         if ( q_u->printername ) {
1428                 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1429                 if (q_u_ex->printername == NULL)
1430                         return WERR_NOMEM;
1431                 copy_unistr2(q_u_ex->printername, q_u->printername);
1432         }
1433         
1434         copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1435
1436         return WERR_OK;
1437 }
1438
1439 /********************************************************************
1440  * spoolss_open_printer
1441  *
1442  * called from the spoolss dispatcher
1443  ********************************************************************/
1444
1445 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1446 {
1447         SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1448         SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1449         
1450         if (!q_u || !r_u)
1451                 return WERR_NOMEM;
1452         
1453         ZERO_STRUCT(q_u_ex);
1454         ZERO_STRUCT(r_u_ex);
1455         
1456         /* convert the OpenPrinter() call to OpenPrinterEx() */
1457         
1458         r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1459         if (!W_ERROR_IS_OK(r_u_ex.status))
1460                 return r_u_ex.status;
1461         
1462         r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1463         
1464         /* convert back to OpenPrinter() */
1465         
1466         memcpy(r_u, &r_u_ex, sizeof(*r_u));
1467         
1468         return r_u->status;
1469 }
1470
1471 /********************************************************************
1472  * spoolss_open_printer
1473  *
1474  * If the openprinterex rpc call contains a devmode,
1475  * it's a per-user one. This per-user devmode is derivated
1476  * from the global devmode. Openprinterex() contains a per-user 
1477  * devmode for when you do EMF printing and spooling.
1478  * In the EMF case, the NT workstation is only doing half the job
1479  * of rendering the page. The other half is done by running the printer
1480  * driver on the server.
1481  * The EMF file doesn't contain the page description (paper size, orientation, ...).
1482  * The EMF file only contains what is to be printed on the page.
1483  * So in order for the server to know how to print, the NT client sends
1484  * a devicemode attached to the openprinterex call.
1485  * But this devicemode is short lived, it's only valid for the current print job.
1486  *
1487  * If Samba would have supported EMF spooling, this devicemode would
1488  * have been attached to the handle, to sent it to the driver to correctly
1489  * rasterize the EMF file.
1490  *
1491  * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1492  * we just act as a pass-thru between windows and the printer.
1493  *
1494  * In order to know that Samba supports only RAW spooling, NT has to call
1495  * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1496  * and until NT sends a RAW job, we refuse it.
1497  *
1498  * But to call getprinter() or startdoc(), you first need a valid handle,
1499  * and to get an handle you have to call openprintex(). Hence why you have
1500  * a devicemode in the openprinterex() call.
1501  *
1502  *
1503  * Differences between NT4 and NT 2000.
1504  * NT4:
1505  * ---
1506  * On NT4, you only have a global devicemode. This global devicemode can be changed
1507  * by the administrator (or by a user with enough privs). Everytime a user
1508  * wants to print, the devicemode is resetted to the default. In Word, everytime
1509  * you print, the printer's characteristics are always reset to the global devicemode.
1510  *
1511  * NT 2000:
1512  * -------
1513  * In W2K, there is the notion of per-user devicemode. The first time you use
1514  * a printer, a per-user devicemode is build from the global devicemode.
1515  * If you change your per-user devicemode, it is saved in the registry, under the
1516  * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1517  * printer preferences available.
1518  *
1519  * To change the per-user devicemode: it's the "Printing Preferences ..." button
1520  * on the General Tab of the printer properties windows.
1521  *
1522  * To change the global devicemode: it's the "Printing Defaults..." button
1523  * on the Advanced Tab of the printer properties window.
1524  *
1525  * JFM.
1526  ********************************************************************/
1527
1528 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1529 {
1530         PRINTER_DEFAULT         *printer_default = &q_u->printer_default;
1531         POLICY_HND              *handle = &r_u->handle;
1532
1533         fstring name;
1534         int snum;
1535         struct current_user user;
1536         Printer_entry *Printer=NULL;
1537
1538         if ( !q_u->printername )
1539                 return WERR_INVALID_PRINTER_NAME;
1540
1541         /* some sanity check because you can open a printer or a print server */
1542         /* aka: \\server\printer or \\server */
1543
1544         unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1545
1546         DEBUGADD(3,("checking name: %s\n",name));
1547
1548         if (!open_printer_hnd(p, handle, name, 0))
1549                 return WERR_INVALID_PRINTER_NAME;
1550         
1551         Printer=find_printer_index_by_hnd(p, handle);
1552         if ( !Printer ) {
1553                 DEBUG(0,(" _spoolss_open_printer_ex: logic error.  Can't find printer "
1554                         "handle we created for printer %s\n", name ));
1555                 close_printer_handle(p,handle);
1556                 return WERR_INVALID_PRINTER_NAME;
1557         }
1558
1559         get_current_user(&user, p);
1560
1561         /*
1562          * First case: the user is opening the print server:
1563          *
1564          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1565          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1566          *
1567          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1568          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1569          * or if the user is listed in the smb.conf printer admin parameter.
1570          *
1571          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1572          * client view printer folder, but does not show the MSAPW.
1573          *
1574          * Note: this test needs code to check access rights here too. Jeremy
1575          * could you look at this?
1576          * 
1577          * Second case: the user is opening a printer:
1578          * NT doesn't let us connect to a printer if the connecting user
1579          * doesn't have print permission.
1580          */
1581
1582         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) 
1583         {
1584                 /* Printserver handles use global struct... */
1585
1586                 snum = -1;
1587
1588                 /* Map standard access rights to object specific access rights */
1589                 
1590                 se_map_standard(&printer_default->access_required, 
1591                                 &printserver_std_mapping);
1592         
1593                 /* Deny any object specific bits that don't apply to print
1594                    servers (i.e printer and job specific bits) */
1595
1596                 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1597
1598                 if (printer_default->access_required &
1599                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1600                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1601                         close_printer_handle(p, handle);
1602                         return WERR_ACCESS_DENIED;
1603                 }
1604
1605                 /* Allow admin access */
1606
1607                 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER ) 
1608                 {
1609                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1610
1611                         if (!lp_ms_add_printer_wizard()) {
1612                                 close_printer_handle(p, handle);
1613                                 return WERR_ACCESS_DENIED;
1614                         }
1615
1616                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1617                            and not a printer admin, then fail */
1618                         
1619                         if ( user.uid != 0
1620                                 && !user_has_privileges( user.nt_user_token, &se_printop )
1621                                 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1622                         {
1623                                 close_printer_handle(p, handle);
1624                                 return WERR_ACCESS_DENIED;
1625                         }
1626                         
1627                         printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1628                 }
1629                 else
1630                 {
1631                         printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1632                 }
1633
1634                 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER) 
1635                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1636                         
1637                 /* We fall through to return WERR_OK */
1638                 
1639         }
1640         else
1641         {
1642                 /* NT doesn't let us connect to a printer if the connecting user
1643                    doesn't have print permission.  */
1644
1645                 if (!get_printer_snum(p, handle, &snum)) {
1646                         close_printer_handle(p, handle);
1647                         return WERR_BADFID;
1648                 }
1649
1650                 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1651                 
1652                 /* map an empty access mask to the minimum access mask */
1653                 if (printer_default->access_required == 0x0)
1654                         printer_default->access_required = PRINTER_ACCESS_USE;
1655
1656                 /*
1657                  * If we are not serving the printer driver for this printer,
1658                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1659                  * will keep NT clients happy  --jerry  
1660                  */
1661                  
1662                 if (lp_use_client_driver(snum) 
1663                         && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1664                 {
1665                         printer_default->access_required = PRINTER_ACCESS_USE;
1666                 }
1667
1668                 /* check smb.conf parameters and the the sec_desc */
1669                 
1670                 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {    
1671                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1672                         return WERR_ACCESS_DENIED;
1673                 }
1674
1675                 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1676                         DEBUG(3, ("access DENIED for printer open\n"));
1677                         close_printer_handle(p, handle);
1678                         return WERR_ACCESS_DENIED;
1679                 }
1680
1681                 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1682                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1683                         close_printer_handle(p, handle);
1684                         return WERR_ACCESS_DENIED;
1685                 }
1686
1687                 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1688                         printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1689                 else
1690                         printer_default->access_required = PRINTER_ACCESS_USE;
1691
1692                 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER) 
1693                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1694
1695         }
1696         
1697         Printer->access_granted = printer_default->access_required;
1698         
1699         /* 
1700          * If the client sent a devmode in the OpenPrinter() call, then
1701          * save it here in case we get a job submission on this handle
1702          */
1703         
1704          if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1705                 && q_u->printer_default.devmode_cont.devmode_ptr )
1706          { 
1707                 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1708                         &Printer->nt_devmode );
1709          }
1710
1711 #if 0   /* JERRY -- I'm doubtful this is really effective */
1712         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN 
1713            optimization in Windows 2000 clients  --jerry */
1714
1715         if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER) 
1716                 && (RA_WIN2K == get_remote_arch()) )
1717         {
1718                 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1719                 sys_usleep( 500000 );
1720         }
1721 #endif
1722
1723         return WERR_OK;
1724 }
1725
1726 /****************************************************************************
1727 ****************************************************************************/
1728
1729 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1731 {
1732         BOOL ret = True;
1733
1734         switch (level) {
1735                 case 2:
1736                         /* printer->info_2  is already a valid printer */
1737                         ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1738                         printer->info_2->setuptime = time(NULL);
1739
1740                         break;
1741                 default:
1742                         break;
1743         }
1744
1745         return ret;
1746 }
1747
1748 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1749                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1750 {
1751         BOOL result = True;
1752
1753         switch (level) {
1754                 case 3:
1755                         printer->info_3=NULL;
1756                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1757                                 result = False;
1758                         break;
1759                 case 6:
1760                         printer->info_6=NULL;
1761                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1762                                 result = False;
1763                         break;
1764                 default:
1765                         break;
1766         }
1767
1768         return result;
1769 }
1770
1771 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1772                                 NT_DEVICEMODE **pp_nt_devmode)
1773 {
1774         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1775
1776         /*
1777          * Ensure nt_devmode is a valid pointer
1778          * as we will be overwriting it.
1779          */
1780                 
1781         if (nt_devmode == NULL) {
1782                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1783                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1784                         return False;
1785         }
1786
1787         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1788         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1789
1790         nt_devmode->specversion=devmode->specversion;
1791         nt_devmode->driverversion=devmode->driverversion;
1792         nt_devmode->size=devmode->size;
1793         nt_devmode->fields=devmode->fields;
1794         nt_devmode->orientation=devmode->orientation;
1795         nt_devmode->papersize=devmode->papersize;
1796         nt_devmode->paperlength=devmode->paperlength;
1797         nt_devmode->paperwidth=devmode->paperwidth;
1798         nt_devmode->scale=devmode->scale;
1799         nt_devmode->copies=devmode->copies;
1800         nt_devmode->defaultsource=devmode->defaultsource;
1801         nt_devmode->printquality=devmode->printquality;
1802         nt_devmode->color=devmode->color;
1803         nt_devmode->duplex=devmode->duplex;
1804         nt_devmode->yresolution=devmode->yresolution;
1805         nt_devmode->ttoption=devmode->ttoption;
1806         nt_devmode->collate=devmode->collate;
1807
1808         nt_devmode->logpixels=devmode->logpixels;
1809         nt_devmode->bitsperpel=devmode->bitsperpel;
1810         nt_devmode->pelswidth=devmode->pelswidth;
1811         nt_devmode->pelsheight=devmode->pelsheight;
1812         nt_devmode->displayflags=devmode->displayflags;
1813         nt_devmode->displayfrequency=devmode->displayfrequency;
1814         nt_devmode->icmmethod=devmode->icmmethod;
1815         nt_devmode->icmintent=devmode->icmintent;
1816         nt_devmode->mediatype=devmode->mediatype;
1817         nt_devmode->dithertype=devmode->dithertype;
1818         nt_devmode->reserved1=devmode->reserved1;
1819         nt_devmode->reserved2=devmode->reserved2;
1820         nt_devmode->panningwidth=devmode->panningwidth;
1821         nt_devmode->panningheight=devmode->panningheight;
1822
1823         /*
1824          * Only change private and driverextra if the incoming devmode
1825          * has a new one. JRA.
1826          */
1827
1828         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1829                 SAFE_FREE(nt_devmode->nt_dev_private);
1830                 nt_devmode->driverextra=devmode->driverextra;
1831                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1832                         return False;
1833                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1834         }
1835
1836         *pp_nt_devmode = nt_devmode;
1837
1838         return True;
1839 }
1840
1841 /********************************************************************
1842  * _spoolss_enddocprinter_internal.
1843  ********************************************************************/
1844
1845 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1846 {
1847         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1848         int snum;
1849
1850         if (!Printer) {
1851                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1852                 return WERR_BADFID;
1853         }
1854         
1855         if (!get_printer_snum(p, handle, &snum))
1856                 return WERR_BADFID;
1857
1858         Printer->document_started=False;
1859         print_job_end(snum, Printer->jobid,True);
1860         /* error codes unhandled so far ... */
1861
1862         return WERR_OK;
1863 }
1864
1865 /********************************************************************
1866  * api_spoolss_closeprinter
1867  ********************************************************************/
1868
1869 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1870 {
1871         POLICY_HND *handle = &q_u->handle;
1872
1873         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1874
1875         if (Printer && Printer->document_started)
1876                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1877
1878         if (!close_printer_handle(p, handle))
1879                 return WERR_BADFID;     
1880                 
1881         /* clear the returned printer handle.  Observed behavior 
1882            from Win2k server.  Don't think this really matters.
1883            Previous code just copied the value of the closed
1884            handle.    --jerry */
1885
1886         memset(&r_u->handle, '\0', sizeof(r_u->handle));
1887
1888         return WERR_OK;
1889 }
1890
1891 /********************************************************************
1892  * api_spoolss_deleteprinter
1893
1894  ********************************************************************/
1895
1896 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1897 {
1898         POLICY_HND *handle = &q_u->handle;
1899         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1900         WERROR result;
1901
1902         if (Printer && Printer->document_started)
1903                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1904
1905         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1906
1907         result = delete_printer_handle(p, handle);
1908
1909         update_c_setprinter(False);
1910
1911         return result;
1912 }
1913
1914 /*******************************************************************
1915  * static function to lookup the version id corresponding to an
1916  * long architecture string
1917  ******************************************************************/
1918
1919 static int get_version_id (char * arch)
1920 {
1921         int i;
1922         struct table_node archi_table[]= {
1923  
1924                 {"Windows 4.0",          "WIN40",       0 },
1925                 {"Windows NT x86",       "W32X86",      2 },
1926                 {"Windows NT R4000",     "W32MIPS",     2 },    
1927                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
1928                 {"Windows NT PowerPC",   "W32PPC",      2 },
1929                 {"Windows IA64",         "IA64",        3 },
1930                 {"Windows x64",          "x64",         3 },
1931                 {NULL,                   "",            -1 }
1932         };
1933  
1934         for (i=0; archi_table[i].long_archi != NULL; i++)
1935         {
1936                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1937                         return (archi_table[i].version);
1938         }
1939         
1940         return -1;
1941 }
1942
1943 /********************************************************************
1944  * _spoolss_deleteprinterdriver
1945  ********************************************************************/
1946
1947 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1948 {
1949         fstring                         driver;
1950         fstring                         arch;
1951         NT_PRINTER_DRIVER_INFO_LEVEL    info;
1952         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
1953         int                             version;
1954         struct current_user             user;
1955         WERROR                          status;
1956         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1957         
1958         get_current_user(&user, p);
1959          
1960         unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1961         unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
1962         
1963         /* check that we have a valid driver name first */
1964         
1965         if ((version=get_version_id(arch)) == -1) 
1966                 return WERR_INVALID_ENVIRONMENT;
1967                                 
1968         ZERO_STRUCT(info);
1969         ZERO_STRUCT(info_win2k);
1970         
1971         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) 
1972         {
1973                 /* try for Win2k driver if "Windows NT x86" */
1974                 
1975                 if ( version == 2 ) {
1976                         version = 3;
1977                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1978                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1979                                 goto done;
1980                         }
1981                 }
1982                 /* otherwise it was a failure */
1983                 else {
1984                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1985                         goto done;
1986                 }
1987                 
1988         }
1989         
1990         if (printer_driver_in_use(info.info_3)) {
1991                 status = WERR_PRINTER_DRIVER_IN_USE;
1992                 goto done;
1993         }
1994         
1995         if ( version == 2 )
1996         {               
1997                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1998                 {
1999                         /* if we get to here, we now have 2 driver info structures to remove */
2000                         /* remove the Win2k driver first*/
2001                 
2002                         status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2003                         free_a_printer_driver( info_win2k, 3 );
2004                 
2005                         /* this should not have failed---if it did, report to client */
2006                         if ( !W_ERROR_IS_OK(status_win2k) )
2007                         {
2008                                 status = status_win2k;
2009                                 goto done;
2010                         }
2011                 }
2012         }
2013         
2014         status = delete_printer_driver(info.info_3, &user, version, False);
2015         
2016         /* if at least one of the deletes succeeded return OK */
2017         
2018         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2019                 status = WERR_OK;
2020         
2021 done:
2022         free_a_printer_driver( info, 3 );
2023
2024         return status;
2025 }
2026
2027 /********************************************************************
2028  * spoolss_deleteprinterdriverex
2029  ********************************************************************/
2030
2031 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *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         uint32                          flags = q_u->delete_flags;
2039         BOOL                            delete_files;
2040         struct current_user             user;
2041         WERROR                          status;
2042         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2043         
2044         get_current_user(&user, p);
2045         
2046         unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2047         unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
2048
2049         /* check that we have a valid driver name first */
2050         if ((version=get_version_id(arch)) == -1) {
2051                 /* this is what NT returns */
2052                 return WERR_INVALID_ENVIRONMENT;
2053         }
2054         
2055         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2056                 version = q_u->version;
2057                 
2058         ZERO_STRUCT(info);
2059         ZERO_STRUCT(info_win2k);
2060                 
2061         status = get_a_printer_driver(&info, 3, driver, arch, version);
2062         
2063         if ( !W_ERROR_IS_OK(status) ) 
2064         {
2065                 /* 
2066                  * if the client asked for a specific version, 
2067                  * or this is something other than Windows NT x86,
2068                  * then we've failed 
2069                  */
2070                 
2071                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2072                         goto done;
2073                         
2074                 /* try for Win2k driver if "Windows NT x86" */
2075                 
2076                 version = 3;
2077                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2078                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2079                         goto done;
2080                 }
2081         }
2082                 
2083         if ( printer_driver_in_use(info.info_3) ) {
2084                 status = WERR_PRINTER_DRIVER_IN_USE;
2085                 goto done;
2086         }
2087         
2088         /* 
2089          * we have a couple of cases to consider. 
2090          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2091          *     then the delete should fail if **any** files overlap with 
2092          *     other drivers 
2093          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094          *     non-overlapping files 
2095          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096          *     is set, the do not delete any files
2097          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2098          */
2099         
2100         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2101         
2102         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2103                 
2104         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2105                 /* no idea of the correct error here */
2106                 status = WERR_ACCESS_DENIED;    
2107                 goto done;
2108         }
2109
2110                         
2111         /* also check for W32X86/3 if necessary; maybe we already have? */
2112                 
2113         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2114                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3))) 
2115                 {
2116                         
2117                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2118                                 /* no idea of the correct error here */
2119                                 free_a_printer_driver( info_win2k, 3 );
2120                                 status = WERR_ACCESS_DENIED;    
2121                                 goto done;
2122                         }
2123                 
2124                         /* if we get to here, we now have 2 driver info structures to remove */
2125                         /* remove the Win2k driver first*/
2126                 
2127                         status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2128                         free_a_printer_driver( info_win2k, 3 );
2129                                 
2130                         /* this should not have failed---if it did, report to client */
2131                                 
2132                         if ( !W_ERROR_IS_OK(status_win2k) )
2133                                 goto done;
2134                 }
2135         }
2136
2137         status = delete_printer_driver(info.info_3, &user, version, delete_files);
2138
2139         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2140                 status = WERR_OK;
2141 done:
2142         free_a_printer_driver( info, 3 );
2143         
2144         return status;
2145 }
2146
2147
2148 /****************************************************************************
2149  Internal routine for retreiving printerdata
2150  ***************************************************************************/
2151
2152 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, 
2153                                   const char *key, const char *value, uint32 *type, uint8 **data, 
2154                                   uint32 *needed, uint32 in_size  )
2155 {
2156         REGISTRY_VALUE          *val;
2157         uint32                  size;
2158         int                     data_len;
2159         
2160         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2161                 return WERR_BADFILE;
2162         
2163         *type = regval_type( val );
2164
2165         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2166
2167         size = regval_size( val );
2168         
2169         /* copy the min(in_size, len) */
2170         
2171         if ( in_size ) {
2172                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2173                 
2174                 /* special case for 0 length values */
2175                 if ( data_len ) {
2176                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2177                                 return WERR_NOMEM;
2178                 }
2179                 else {
2180                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2181                                 return WERR_NOMEM;
2182                 }
2183         }
2184         else
2185                 *data = NULL;
2186
2187         *needed = size;
2188         
2189         DEBUG(5,("get_printer_dataex: copy done\n"));
2190
2191         return WERR_OK;
2192 }
2193
2194 /****************************************************************************
2195  Internal routine for removing printerdata
2196  ***************************************************************************/
2197
2198 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2199 {
2200         return delete_printer_data( printer->info_2, key, value );
2201 }
2202
2203 /****************************************************************************
2204  Internal routine for storing printerdata
2205  ***************************************************************************/
2206
2207 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value, 
2208                                   uint32 type, uint8 *data, int real_len  )
2209 {
2210         /* the registry objects enforce uniqueness based on value name */
2211
2212         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2213 }
2214
2215 /********************************************************************
2216  GetPrinterData on a printer server Handle.
2217 ********************************************************************/
2218
2219 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2220 {               
2221         int i;
2222         
2223         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2224                 
2225         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2226                 *type = REG_DWORD;
2227                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2228                         return WERR_NOMEM;
2229                 *needed = 0x4;
2230                 return WERR_OK;
2231         }
2232
2233         if (!StrCaseCmp(value, "BeepEnabled")) {
2234                 *type = REG_DWORD;
2235                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2236                         return WERR_NOMEM;
2237                 SIVAL(*data, 0, 0x00);
2238                 *needed = 0x4;                  
2239                 return WERR_OK;
2240         }
2241
2242         if (!StrCaseCmp(value, "EventLog")) {
2243                 *type = REG_DWORD;
2244                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2245                         return WERR_NOMEM;
2246                 /* formally was 0x1b */
2247                 SIVAL(*data, 0, 0x0);
2248                 *needed = 0x4;                  
2249                 return WERR_OK;
2250         }
2251
2252         if (!StrCaseCmp(value, "NetPopup")) {
2253                 *type = REG_DWORD;
2254                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2255                         return WERR_NOMEM;
2256                 SIVAL(*data, 0, 0x00);
2257                 *needed = 0x4;
2258                 return WERR_OK;
2259         }
2260
2261         if (!StrCaseCmp(value, "MajorVersion")) {
2262                 *type = REG_DWORD;
2263                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2264                         return WERR_NOMEM;
2265
2266                 /* Windows NT 4.0 seems to not allow uploading of drivers
2267                    to a server that reports 0x3 as the MajorVersion.
2268                    need to investigate more how Win2k gets around this .
2269                    -- jerry */
2270
2271                 if ( RA_WINNT == get_remote_arch() )
2272                         SIVAL(*data, 0, 2);
2273                 else
2274                         SIVAL(*data, 0, 3);
2275                 
2276                 *needed = 0x4;
2277                 return WERR_OK;
2278         }
2279
2280         if (!StrCaseCmp(value, "MinorVersion")) {
2281                 *type = REG_DWORD;
2282                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2283                         return WERR_NOMEM;
2284                 SIVAL(*data, 0, 0);
2285                 *needed = 0x4;
2286                 return WERR_OK;
2287         }
2288
2289         /* REG_BINARY
2290          *  uint32 size          = 0x114
2291          *  uint32 major         = 5
2292          *  uint32 minor         = [0|1]
2293          *  uint32 build         = [2195|2600]
2294          *  extra unicode string = e.g. "Service Pack 3"
2295          */
2296         if (!StrCaseCmp(value, "OSVersion")) {
2297                 *type = REG_BINARY;
2298                 *needed = 0x114;
2299
2300                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2301                         return WERR_NOMEM;
2302
2303                 SIVAL(*data, 0, *needed);       /* size */
2304                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2305                 SIVAL(*data, 8, 0);
2306                 SIVAL(*data, 12, 2195);         /* build */
2307                 
2308                 /* leave extra string empty */
2309                 
2310                 return WERR_OK;
2311         }
2312
2313
2314         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2315                 const char *string="C:\\PRINTERS";
2316                 *type = REG_SZ;
2317                 *needed = 2*(strlen(string)+1);         
2318                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2319                         return WERR_NOMEM;
2320                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2321                 
2322                 /* it's done by hand ready to go on the wire */
2323                 for (i=0; i<strlen(string); i++) {
2324                         (*data)[2*i]=string[i];
2325                         (*data)[2*i+1]='\0';
2326                 }                       
2327                 return WERR_OK;
2328         }
2329
2330         if (!StrCaseCmp(value, "Architecture")) {                       
2331                 const char *string="Windows NT x86";
2332                 *type = REG_SZ;
2333                 *needed = 2*(strlen(string)+1); 
2334                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2335                         return WERR_NOMEM;
2336                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2337                 for (i=0; i<strlen(string); i++) {
2338                         (*data)[2*i]=string[i];
2339                         (*data)[2*i+1]='\0';
2340                 }                       
2341                 return WERR_OK;
2342         }
2343
2344         if (!StrCaseCmp(value, "DsPresent")) {
2345                 *type = REG_DWORD;
2346                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2347                         return WERR_NOMEM;
2348
2349                 /* only show the publish check box if we are a 
2350                    memeber of a AD domain */
2351
2352                 if ( lp_security() == SEC_ADS )
2353                         SIVAL(*data, 0, 0x01);
2354                 else
2355                         SIVAL(*data, 0, 0x00);
2356
2357                 *needed = 0x4;
2358                 return WERR_OK;
2359         }
2360
2361         if (!StrCaseCmp(value, "DNSMachineName")) {                     
2362                 pstring hostname;
2363                 
2364                 if (!get_mydnsfullname(hostname))
2365                         return WERR_BADFILE;
2366                 *type = REG_SZ;
2367                 *needed = 2*(strlen(hostname)+1);       
2368                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2369                         return WERR_NOMEM;
2370                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2371                 for (i=0; i<strlen(hostname); i++) {
2372                         (*data)[2*i]=hostname[i];
2373                         (*data)[2*i+1]='\0';
2374                 }                       
2375                 return WERR_OK;
2376         }
2377
2378
2379         return WERR_BADFILE;
2380 }
2381
2382 /********************************************************************
2383  * spoolss_getprinterdata
2384  ********************************************************************/
2385
2386 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2387 {
2388         POLICY_HND      *handle = &q_u->handle;
2389         UNISTR2         *valuename = &q_u->valuename;
2390         uint32          in_size = q_u->size;
2391         uint32          *type = &r_u->type;
2392         uint32          *out_size = &r_u->size;
2393         uint8           **data = &r_u->data;
2394         uint32          *needed = &r_u->needed;
2395         WERROR          status;
2396         fstring         value;
2397         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2398         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2399         int             snum = 0;
2400         
2401         /*
2402          * Reminder: when it's a string, the length is in BYTES
2403          * even if UNICODE is negociated.
2404          *
2405          * JFM, 4/19/1999
2406          */
2407
2408         *out_size = in_size;
2409
2410         /* in case of problem, return some default values */
2411         
2412         *needed = 0;
2413         *type   = 0;
2414         
2415         DEBUG(4,("_spoolss_getprinterdata\n"));
2416         
2417         if ( !Printer ) {
2418                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2419                 status = WERR_BADFID;
2420                 goto done;
2421         }
2422         
2423         unistr2_to_ascii(value, valuename, sizeof(value)-1);
2424         
2425         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2426                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2427         else
2428         {
2429                 if ( !get_printer_snum(p,handle, &snum) ) {
2430                         status = WERR_BADFID;
2431                         goto done;
2432                 }
2433
2434                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2435                 if ( !W_ERROR_IS_OK(status) )
2436                         goto done;
2437
2438                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2439
2440                 if ( strequal(value, "ChangeId") ) {
2441                         *type = REG_DWORD;
2442                         *needed = sizeof(uint32);
2443                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2444                                 status = WERR_NOMEM;
2445                                 goto done;
2446                         }
2447                         SIVAL( *data, 0, printer->info_2->changeid );
2448                         status = WERR_OK;
2449                 }
2450                 else
2451                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2452         }
2453
2454         if (*needed > *out_size)
2455                 status = WERR_MORE_DATA;
2456         
2457 done:
2458         if ( !W_ERROR_IS_OK(status) ) 
2459         {
2460                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2461                 
2462                 /* reply this param doesn't exist */
2463                 
2464                 if ( *out_size ) {
2465                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2466                                 if ( printer ) 
2467                                         free_a_printer( &printer, 2 );
2468                                 return WERR_NOMEM;
2469                 } 
2470                 } 
2471                 else {
2472                         *data = NULL;
2473                 }
2474         }
2475         
2476         /* cleanup & exit */
2477
2478         if ( printer )
2479                 free_a_printer( &printer, 2 );
2480         
2481         return status;
2482 }
2483
2484 /*********************************************************
2485  Connect to the client machine.
2486 **********************************************************/
2487
2488 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, struct rpc_pipe_client **pp_pipe,
2489                         struct in_addr *client_ip, const char *remote_machine)
2490 {
2491         NTSTATUS ret;
2492         ZERO_STRUCTP(the_cli);
2493         
2494         if(cli_initialise(the_cli) == NULL) {
2495                 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2496                 return False;
2497         }
2498         
2499         if ( is_zero_ip(*client_ip) ) {
2500                 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2501                         DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2502                         cli_shutdown(the_cli);
2503                 return False;
2504                 }
2505
2506                 if (ismyip(the_cli->dest_ip)) {
2507                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2508                         cli_shutdown(the_cli);
2509                         return False;
2510                 }
2511         }
2512         else {
2513                 the_cli->dest_ip.s_addr = client_ip->s_addr;
2514                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2515                         inet_ntoa(*client_ip) ));
2516         }
2517
2518         if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2519                 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) ));
2520                 cli_shutdown(the_cli);
2521                 return False;
2522         }
2523   
2524         if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2525                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n", 
2526                         remote_machine));
2527                 cli_shutdown(the_cli);
2528                 return False;
2529         }
2530
2531         the_cli->protocol = PROTOCOL_NT1;
2532         cli_setup_signing_state(the_cli, lp_client_signing());
2533   
2534         if (!cli_negprot(the_cli)) {
2535                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2536                 cli_shutdown(the_cli);
2537                 return False;
2538         }
2539
2540         if (the_cli->protocol != PROTOCOL_NT1) {
2541                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2542                 cli_shutdown(the_cli);
2543                 return False;
2544         }
2545     
2546         /*
2547          * Do an anonymous session setup.
2548          */
2549     
2550         if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2551                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2552                 cli_shutdown(the_cli);
2553                 return False;
2554         }
2555     
2556         if (!(the_cli->sec_mode & 1)) {
2557                 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2558                 cli_shutdown(the_cli);
2559                 return False;
2560         }
2561     
2562         if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2563                 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) ));
2564                 cli_shutdown(the_cli);
2565                 return False;
2566         }
2567
2568         /*
2569          * Ok - we have an anonymous connection to the IPC$ share.
2570          * Now start the NT Domain stuff :-).
2571          */
2572
2573         *pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret);
2574         if(!*pp_pipe) {
2575                 DEBUG(0,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576                         remote_machine, nt_errstr(ret)));
2577                 cli_shutdown(the_cli);
2578                 return False;
2579         } 
2580
2581         return True;
2582 }
2583
2584 /***************************************************************************
2585  Connect to the client.
2586 ****************************************************************************/
2587
2588 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, 
2589                                         uint32 localprinter, uint32 type, 
2590                                         POLICY_HND *handle, struct in_addr *client_ip)
2591 {
2592         WERROR result;
2593
2594         /*
2595          * If it's the first connection, contact the client
2596          * and connect to the IPC$ share anonymously
2597          */
2598         if (smb_connections==0) {
2599                 struct cli_state notify_cli; /* print notify back-channel */
2600                 fstring unix_printer;
2601
2602                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2603
2604                 ZERO_STRUCT(notify_cli);
2605
2606                 if(!spoolss_connect_to_client(&notify_cli, &notify_cli_pipe, client_ip, unix_printer))
2607                         return False;
2608                         
2609                 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2610                 /* Tell the connections db we're now interested in printer
2611                  * notify messages. */
2612                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2613         }
2614
2615         /* 
2616          * Tell the specific printing tdb we want messages for this printer
2617          * by registering our PID.
2618          */
2619
2620         if (!print_notify_register_pid(snum))
2621                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2622
2623         smb_connections++;
2624
2625         result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter, 
2626                         type, handle);
2627                         
2628         if (!W_ERROR_IS_OK(result))
2629                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2630                         dos_errstr(result)));
2631
2632         return (W_ERROR_IS_OK(result)); 
2633 }
2634
2635 /********************************************************************
2636  * _spoolss_rffpcnex
2637  * ReplyFindFirstPrinterChangeNotifyEx
2638  *
2639  * before replying OK: status=0 a rpc call is made to the workstation
2640  * asking ReplyOpenPrinter 
2641  *
2642  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2643  * called from api_spoolss_rffpcnex
2644  ********************************************************************/
2645
2646 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2647 {
2648         POLICY_HND *handle = &q_u->handle;
2649         uint32 flags = q_u->flags;
2650         uint32 options = q_u->options;
2651         UNISTR2 *localmachine = &q_u->localmachine;
2652         uint32 printerlocal = q_u->printerlocal;
2653         int snum = -1;
2654         SPOOL_NOTIFY_OPTION *option = q_u->option;
2655         struct in_addr client_ip;
2656
2657         /* store the notify value in the printer struct */
2658
2659         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2660
2661         if (!Printer) {
2662                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2663                 return WERR_BADFID;
2664         }
2665
2666         Printer->notify.flags=flags;
2667         Printer->notify.options=options;
2668         Printer->notify.printerlocal=printerlocal;
2669
2670         if (Printer->notify.option)
2671                 free_spool_notify_option(&Printer->notify.option);
2672
2673         Printer->notify.option=dup_spool_notify_option(option);
2674
2675         unistr2_to_ascii(Printer->notify.localmachine, localmachine, 
2676                        sizeof(Printer->notify.localmachine)-1);
2677
2678         /* Connect to the client machine and send a ReplyOpenPrinter */
2679
2680         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2681                 snum = -1;
2682         else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2683                         !get_printer_snum(p, handle, &snum) )
2684                 return WERR_BADFID;
2685                 
2686         client_ip.s_addr = inet_addr(p->conn->client_address);
2687
2688         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2689                                         Printer->notify.printerlocal, 1,
2690                                         &Printer->notify.client_hnd, &client_ip))
2691                 return WERR_SERVER_UNAVAILABLE;
2692
2693         Printer->notify.client_connected=True;
2694
2695         return WERR_OK;
2696 }
2697
2698 /*******************************************************************
2699  * fill a notify_info_data with the servername
2700  ********************************************************************/
2701
2702 void spoolss_notify_server_name(int snum, 
2703                                        SPOOL_NOTIFY_INFO_DATA *data, 
2704                                        print_queue_struct *queue,
2705                                        NT_PRINTER_INFO_LEVEL *printer,
2706                                        TALLOC_CTX *mem_ctx) 
2707 {
2708         pstring temp;
2709         uint32 len;
2710
2711         len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2712
2713         data->notify_data.data.length = len;
2714         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2715
2716         if (!data->notify_data.data.string) {
2717                 data->notify_data.data.length = 0;
2718                 return;
2719         }
2720         
2721         memcpy(data->notify_data.data.string, temp, len);
2722 }
2723
2724 /*******************************************************************
2725  * fill a notify_info_data with the printername (not including the servername).
2726  ********************************************************************/
2727
2728 void spoolss_notify_printer_name(int snum, 
2729                                         SPOOL_NOTIFY_INFO_DATA *data, 
2730                                         print_queue_struct *queue,
2731                                         NT_PRINTER_INFO_LEVEL *printer,
2732                                         TALLOC_CTX *mem_ctx)
2733 {
2734         pstring temp;
2735         uint32 len;
2736                 
2737         /* the notify name should not contain the \\server\ part */
2738         char *p = strrchr(printer->info_2->printername, '\\');
2739
2740         if (!p) {
2741                 p = printer->info_2->printername;
2742         } else {
2743                 p++;
2744         }
2745
2746         len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2747
2748         data->notify_data.data.length = len;
2749         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2750         
2751         if (!data->notify_data.data.string) {
2752                 data->notify_data.data.length = 0;
2753                 return;
2754         }
2755         
2756         memcpy(data->notify_data.data.string, temp, len);
2757 }
2758
2759 /*******************************************************************
2760  * fill a notify_info_data with the servicename
2761  ********************************************************************/
2762
2763 void spoolss_notify_share_name(int snum, 
2764                                       SPOOL_NOTIFY_INFO_DATA *data, 
2765                                       print_queue_struct *queue,
2766                                       NT_PRINTER_INFO_LEVEL *printer,
2767                                       TALLOC_CTX *mem_ctx)
2768 {
2769         pstring temp;
2770         uint32 len;
2771
2772         len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2773
2774         data->notify_data.data.length = len;
2775         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2776         
2777         if (!data->notify_data.data.string) {
2778                 data->notify_data.data.length = 0;
2779                 return;
2780         }
2781         
2782         memcpy(data->notify_data.data.string, temp, len);
2783 }
2784
2785 /*******************************************************************
2786  * fill a notify_info_data with the port name
2787  ********************************************************************/
2788
2789 void spoolss_notify_port_name(int snum, 
2790                                      SPOOL_NOTIFY_INFO_DATA *data, 
2791                                      print_queue_struct *queue,
2792                                      NT_PRINTER_INFO_LEVEL *printer,
2793                                      TALLOC_CTX *mem_ctx)
2794 {
2795         pstring temp;
2796         uint32 len;
2797
2798         /* even if it's strange, that's consistant in all the code */
2799
2800         len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2801
2802         data->notify_data.data.length = len;
2803         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2804         
2805         if (!data->notify_data.data.string) {
2806                 data->notify_data.data.length = 0;
2807                 return;
2808         }
2809         
2810         memcpy(data->notify_data.data.string, temp, len);
2811 }
2812
2813 /*******************************************************************
2814  * fill a notify_info_data with the printername
2815  * but it doesn't exist, have to see what to do
2816  ********************************************************************/
2817
2818 void spoolss_notify_driver_name(int snum, 
2819                                        SPOOL_NOTIFY_INFO_DATA *data,
2820                                        print_queue_struct *queue,
2821                                        NT_PRINTER_INFO_LEVEL *printer,
2822                                        TALLOC_CTX *mem_ctx)
2823 {
2824         pstring temp;
2825         uint32 len;
2826
2827         len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2828
2829         data->notify_data.data.length = len;
2830         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2831         
2832         if (!data->notify_data.data.string) {
2833                 data->notify_data.data.length = 0;
2834                 return;
2835         }
2836         
2837         memcpy(data->notify_data.data.string, temp, len);
2838 }
2839
2840 /*******************************************************************
2841  * fill a notify_info_data with the comment
2842  ********************************************************************/
2843
2844 void spoolss_notify_comment(int snum, 
2845                                    SPOOL_NOTIFY_INFO_DATA *data,
2846                                    print_queue_struct *queue,
2847                                    NT_PRINTER_INFO_LEVEL *printer,
2848                                    TALLOC_CTX *mem_ctx)
2849 {
2850         pstring temp;
2851         uint32 len;
2852
2853         if (*printer->info_2->comment == '\0')
2854                 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2855         else
2856                 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2857
2858         data->notify_data.data.length = len;
2859         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2860         
2861         if (!data->notify_data.data.string) {
2862                 data->notify_data.data.length = 0;
2863                 return;
2864         }
2865         
2866         memcpy(data->notify_data.data.string, temp, len);
2867 }
2868
2869 /*******************************************************************
2870  * fill a notify_info_data with the comment
2871  * location = "Room 1, floor 2, building 3"
2872  ********************************************************************/
2873
2874 void spoolss_notify_location(int snum, 
2875                                     SPOOL_NOTIFY_INFO_DATA *data,
2876                                     print_queue_struct *queue,
2877                                     NT_PRINTER_INFO_LEVEL *printer,
2878                                     TALLOC_CTX *mem_ctx)
2879 {
2880         pstring temp;
2881         uint32 len;
2882
2883         len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2884
2885         data->notify_data.data.length = len;
2886         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2887         
2888         if (!data->notify_data.data.string) {
2889                 data->notify_data.data.length = 0;
2890                 return;
2891         }
2892         
2893         memcpy(data->notify_data.data.string, temp, len);
2894 }
2895
2896 /*******************************************************************
2897  * fill a notify_info_data with the device mode
2898  * jfm:xxxx don't to it for know but that's a real problem !!!
2899  ********************************************************************/
2900
2901 static void spoolss_notify_devmode(int snum, 
2902                                    SPOOL_NOTIFY_INFO_DATA *data,
2903                                    print_queue_struct *queue,
2904                                    NT_PRINTER_INFO_LEVEL *printer,
2905                                    TALLOC_CTX *mem_ctx)
2906 {
2907 }
2908
2909 /*******************************************************************
2910  * fill a notify_info_data with the separator file name
2911  ********************************************************************/
2912
2913 void spoolss_notify_sepfile(int snum, 
2914                                    SPOOL_NOTIFY_INFO_DATA *data, 
2915                                    print_queue_struct *queue,
2916                                    NT_PRINTER_INFO_LEVEL *printer,
2917                                    TALLOC_CTX *mem_ctx)
2918 {
2919         pstring temp;
2920         uint32 len;
2921
2922         len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2923
2924         data->notify_data.data.length = len;
2925         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2926         
2927         if (!data->notify_data.data.string) {
2928                 data->notify_data.data.length = 0;
2929                 return;
2930         }
2931         
2932         memcpy(data->notify_data.data.string, temp, len);
2933 }
2934
2935 /*******************************************************************
2936  * fill a notify_info_data with the print processor
2937  * jfm:xxxx return always winprint to indicate we don't do anything to it
2938  ********************************************************************/
2939
2940 void spoolss_notify_print_processor(int snum, 
2941                                            SPOOL_NOTIFY_INFO_DATA *data,
2942                                            print_queue_struct *queue,
2943                                            NT_PRINTER_INFO_LEVEL *printer,
2944                                            TALLOC_CTX *mem_ctx)
2945 {
2946         pstring temp;
2947         uint32 len;
2948
2949         len = rpcstr_push(temp,  printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2950
2951         data->notify_data.data.length = len;
2952         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2953         
2954         if (!data->notify_data.data.string) {
2955                 data->notify_data.data.length = 0;
2956                 return;
2957         }
2958         
2959         memcpy(data->notify_data.data.string, temp, len);
2960 }
2961
2962 /*******************************************************************
2963  * fill a notify_info_data with the print processor options
2964  * jfm:xxxx send an empty string
2965  ********************************************************************/
2966
2967 void spoolss_notify_parameters(int snum, 
2968                                       SPOOL_NOTIFY_INFO_DATA *data,
2969                                       print_queue_struct *queue,
2970                                       NT_PRINTER_INFO_LEVEL *printer,
2971                                       TALLOC_CTX *mem_ctx)
2972 {
2973         pstring temp;
2974         uint32 len;
2975
2976         len = rpcstr_push(temp,  printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2977
2978         data->notify_data.data.length = len;
2979         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2980         
2981         if (!data->notify_data.data.string) {
2982                 data->notify_data.data.length = 0;
2983                 return;
2984         }
2985         
2986         memcpy(data->notify_data.data.string, temp, len);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with the data type
2991  * jfm:xxxx always send RAW as data type
2992  ********************************************************************/
2993
2994 void spoolss_notify_datatype(int snum, 
2995                                     SPOOL_NOTIFY_INFO_DATA *data,
2996                                     print_queue_struct *queue,
2997                                     NT_PRINTER_INFO_LEVEL *printer,
2998                                     TALLOC_CTX *mem_ctx)
2999 {
3000         pstring temp;
3001         uint32 len;
3002
3003         len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3004
3005         data->notify_data.data.length = len;
3006         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3007         
3008         if (!data->notify_data.data.string) {
3009                 data->notify_data.data.length = 0;
3010                 return;
3011         }
3012         
3013         memcpy(data->notify_data.data.string, temp, len);
3014 }
3015
3016 /*******************************************************************
3017  * fill a notify_info_data with the security descriptor
3018  * jfm:xxxx send an null pointer to say no security desc
3019  * have to implement security before !
3020  ********************************************************************/
3021
3022 static void spoolss_notify_security_desc(int snum, 
3023                                          SPOOL_NOTIFY_INFO_DATA *data,
3024                                          print_queue_struct *queue,
3025                                          NT_PRINTER_INFO_LEVEL *printer,
3026                                          TALLOC_CTX *mem_ctx)
3027 {
3028         data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3029         data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3030 }
3031
3032 /*******************************************************************
3033  * fill a notify_info_data with the attributes
3034  * jfm:xxxx a samba printer is always shared
3035  ********************************************************************/
3036
3037 void spoolss_notify_attributes(int snum, 
3038                                       SPOOL_NOTIFY_INFO_DATA *data,
3039                                       print_queue_struct *queue,
3040                                       NT_PRINTER_INFO_LEVEL *printer,
3041                                       TALLOC_CTX *mem_ctx)
3042 {
3043         data->notify_data.value[0] = printer->info_2->attributes;
3044         data->notify_data.value[1] = 0;
3045 }
3046
3047 /*******************************************************************
3048  * fill a notify_info_data with the priority
3049  ********************************************************************/
3050
3051 static void spoolss_notify_priority(int snum, 
3052                                     SPOOL_NOTIFY_INFO_DATA *data,
3053                                     print_queue_struct *queue,
3054                                     NT_PRINTER_INFO_LEVEL *printer,
3055                                     TALLOC_CTX *mem_ctx)
3056 {
3057         data->notify_data.value[0] = printer->info_2->priority;
3058         data->notify_data.value[1] = 0;
3059 }
3060
3061 /*******************************************************************
3062  * fill a notify_info_data with the default priority
3063  ********************************************************************/
3064
3065 static void spoolss_notify_default_priority(int snum, 
3066                                             SPOOL_NOTIFY_INFO_DATA *data,
3067                                             print_queue_struct *queue,
3068                                             NT_PRINTER_INFO_LEVEL *printer,
3069                                             TALLOC_CTX *mem_ctx)
3070 {
3071         data->notify_data.value[0] = printer->info_2->default_priority;
3072         data->notify_data.value[1] = 0;
3073 }
3074
3075 /*******************************************************************
3076  * fill a notify_info_data with the start time
3077  ********************************************************************/
3078
3079 static void spoolss_notify_start_time(int snum, 
3080                                       SPOOL_NOTIFY_INFO_DATA *data,
3081                                       print_queue_struct *queue,
3082                                       NT_PRINTER_INFO_LEVEL *printer,
3083                                       TALLOC_CTX *mem_ctx)
3084 {
3085         data->notify_data.value[0] = printer->info_2->starttime;
3086         data->notify_data.value[1] = 0;
3087 }
3088
3089 /*******************************************************************
3090  * fill a notify_info_data with the until time
3091  ********************************************************************/
3092
3093 static void spoolss_notify_until_time(int snum, 
3094                                       SPOOL_NOTIFY_INFO_DATA *data,
3095                                       print_queue_struct *queue,
3096                                       NT_PRINTER_INFO_LEVEL *printer,
3097                                       TALLOC_CTX *mem_ctx)
3098 {
3099         data->notify_data.value[0] = printer->info_2->untiltime;
3100         data->notify_data.value[1] = 0;
3101 }
3102
3103 /*******************************************************************
3104  * fill a notify_info_data with the status
3105  ********************************************************************/
3106
3107 static void spoolss_notify_status(int snum, 
3108                                   SPOOL_NOTIFY_INFO_DATA *data,
3109                                   print_queue_struct *queue,
3110                                   NT_PRINTER_INFO_LEVEL *printer,
3111                                   TALLOC_CTX *mem_ctx)
3112 {
3113         print_status_struct status;
3114
3115         print_queue_length(snum, &status);
3116         data->notify_data.value[0]=(uint32) status.status;
3117         data->notify_data.value[1] = 0;
3118 }
3119
3120 /*******************************************************************
3121  * fill a notify_info_data with the number of jobs queued
3122  ********************************************************************/
3123
3124 void spoolss_notify_cjobs(int snum, 
3125                                  SPOOL_NOTIFY_INFO_DATA *data,
3126                                  print_queue_struct *queue,
3127                                  NT_PRINTER_INFO_LEVEL *printer, 
3128                                  TALLOC_CTX *mem_ctx)
3129 {
3130         data->notify_data.value[0] = print_queue_length(snum, NULL);
3131         data->notify_data.value[1] = 0;
3132 }
3133
3134 /*******************************************************************
3135  * fill a notify_info_data with the average ppm
3136  ********************************************************************/
3137
3138 static void spoolss_notify_average_ppm(int snum, 
3139                                        SPOOL_NOTIFY_INFO_DATA *data,
3140                                        print_queue_struct *queue,
3141                                        NT_PRINTER_INFO_LEVEL *printer,
3142                                        TALLOC_CTX *mem_ctx)
3143 {
3144         /* always respond 8 pages per minutes */
3145         /* a little hard ! */
3146         data->notify_data.value[0] = printer->info_2->averageppm;
3147         data->notify_data.value[1] = 0;
3148 }
3149
3150 /*******************************************************************
3151  * fill a notify_info_data with username
3152  ********************************************************************/
3153
3154 static void spoolss_notify_username(int snum, 
3155                                     SPOOL_NOTIFY_INFO_DATA *data,
3156                                     print_queue_struct *queue,
3157                                     NT_PRINTER_INFO_LEVEL *printer,
3158                                     TALLOC_CTX *mem_ctx)
3159 {
3160         pstring temp;
3161         uint32 len;
3162
3163         len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3164
3165         data->notify_data.data.length = len;
3166         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3167         
3168         if (!data->notify_data.data.string) {
3169                 data->notify_data.data.length = 0;
3170                 return;
3171         }
3172         
3173         memcpy(data->notify_data.data.string, temp, len);
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with job status
3178  ********************************************************************/
3179
3180 static void spoolss_notify_job_status(int snum, 
3181                                       SPOOL_NOTIFY_INFO_DATA *data,
3182                                       print_queue_struct *queue,
3183                                       NT_PRINTER_INFO_LEVEL *printer,
3184                                       TALLOC_CTX *mem_ctx)
3185 {
3186         data->notify_data.value[0]=nt_printj_status(queue->status);
3187         data->notify_data.value[1] = 0;
3188 }
3189
3190 /*******************************************************************
3191  * fill a notify_info_data with job name
3192  ********************************************************************/
3193
3194 static void spoolss_notify_job_name(int snum, 
3195                                     SPOOL_NOTIFY_INFO_DATA *data,
3196                                     print_queue_struct *queue,
3197                                     NT_PRINTER_INFO_LEVEL *printer,
3198                                     TALLOC_CTX *mem_ctx)
3199 {
3200         pstring temp;
3201         uint32 len;
3202
3203         len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3204
3205         data->notify_data.data.length = len;
3206         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3207         
3208         if (!data->notify_data.data.string) {
3209                 data->notify_data.data.length = 0;
3210                 return;
3211         }
3212         
3213         memcpy(data->notify_data.data.string, temp, len);
3214 }
3215
3216 /*******************************************************************
3217  * fill a notify_info_data with job status
3218  ********************************************************************/
3219
3220 static void spoolss_notify_job_status_string(int snum, 
3221                                              SPOOL_NOTIFY_INFO_DATA *data,
3222                                              print_queue_struct *queue,
3223                                              NT_PRINTER_INFO_LEVEL *printer, 
3224                                              TALLOC_CTX *mem_ctx)
3225 {
3226         /*
3227          * Now we're returning job status codes we just return a "" here. JRA.
3228          */
3229
3230         const char *p = "";
3231         pstring temp;
3232         uint32 len;
3233
3234 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3235         p = "unknown";
3236
3237         switch (queue->status) {
3238         case LPQ_QUEUED:
3239                 p = "Queued";
3240                 break;
3241         case LPQ_PAUSED:
3242                 p = "";    /* NT provides the paused string */
3243                 break;
3244         case LPQ_SPOOLING:
3245                 p = "Spooling";
3246                 break;
3247         case LPQ_PRINTING:
3248                 p = "Printing";
3249                 break;
3250         }
3251 #endif /* NO LONGER NEEDED. */
3252
3253         len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3254
3255         data->notify_data.data.length = len;
3256         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3257         
3258         if (!data->notify_data.data.string) {
3259                 data->notify_data.data.length = 0;
3260                 return;
3261         }
3262         
3263         memcpy(data->notify_data.data.string, temp, len);
3264 }
3265
3266 /*******************************************************************
3267  * fill a notify_info_data with job time
3268  ********************************************************************/
3269
3270 static void spoolss_notify_job_time(int snum, 
3271                                     SPOOL_NOTIFY_INFO_DATA *data,
3272                                     print_queue_struct *queue,
3273                                     NT_PRINTER_INFO_LEVEL *printer,
3274                                     TALLOC_CTX *mem_ctx)
3275 {
3276         data->notify_data.value[0]=0x0;
3277         data->notify_data.value[1]=0;
3278 }
3279
3280 /*******************************************************************
3281  * fill a notify_info_data with job size
3282  ********************************************************************/
3283
3284 static void spoolss_notify_job_size(int snum, 
3285                                     SPOOL_NOTIFY_INFO_DATA *data,
3286                                     print_queue_struct *queue,
3287                                     NT_PRINTER_INFO_LEVEL *printer,
3288                                     TALLOC_CTX *mem_ctx)
3289 {
3290         data->notify_data.value[0]=queue->size;
3291         data->notify_data.value[1]=0;
3292 }
3293
3294 /*******************************************************************
3295  * fill a notify_info_data with page info
3296  ********************************************************************/
3297 static void spoolss_notify_total_pages(int snum,
3298                                 SPOOL_NOTIFY_INFO_DATA *data,
3299                                 print_queue_struct *queue,
3300                                 NT_PRINTER_INFO_LEVEL *printer,
3301                                 TALLOC_CTX *mem_ctx)
3302 {
3303         data->notify_data.value[0]=queue->page_count;
3304         data->notify_data.value[1]=0;
3305 }
3306
3307 /*******************************************************************
3308  * fill a notify_info_data with pages printed info.
3309  ********************************************************************/
3310 static void spoolss_notify_pages_printed(int snum,
3311                                 SPOOL_NOTIFY_INFO_DATA *data,
3312                                 print_queue_struct *queue,
3313                                 NT_PRINTER_INFO_LEVEL *printer,
3314                                 TALLOC_CTX *mem_ctx)
3315 {
3316         data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
3317         data->notify_data.value[1]=0;
3318 }
3319
3320 /*******************************************************************
3321  Fill a notify_info_data with job position.
3322  ********************************************************************/
3323
3324 static void spoolss_notify_job_position(int snum, 
3325                                         SPOOL_NOTIFY_INFO_DATA *data,
3326                                         print_queue_struct *queue,
3327                                         NT_PRINTER_INFO_LEVEL *printer,
3328                                         TALLOC_CTX *mem_ctx)
3329 {
3330         data->notify_data.value[0]=queue->job;
3331         data->notify_data.value[1]=0;
3332 }
3333
3334 /*******************************************************************
3335  Fill a notify_info_data with submitted time.
3336  ********************************************************************/
3337
3338 static void spoolss_notify_submitted_time(int snum, 
3339                                           SPOOL_NOTIFY_INFO_DATA *data,
3340                                           print_queue_struct *queue,
3341                                           NT_PRINTER_INFO_LEVEL *printer,
3342                                           TALLOC_CTX *mem_ctx)
3343 {
3344         struct tm *t;
3345         uint32 len;
3346         SYSTEMTIME st;
3347         char *p;
3348
3349         t=gmtime(&queue->time);
3350
3351         len = sizeof(SYSTEMTIME);
3352
3353         data->notify_data.data.length = len;
3354         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3355
3356         if (!data->notify_data.data.string) {
3357                 data->notify_data.data.length = 0;
3358                 return;
3359         }
3360         
3361         make_systemtime(&st, t);
3362
3363         /*
3364          * Systemtime must be linearized as a set of UINT16's. 
3365          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3366          */
3367
3368         p = (char *)data->notify_data.data.string;
3369         SSVAL(p, 0, st.year);
3370         SSVAL(p, 2, st.month);
3371         SSVAL(p, 4, st.dayofweek);
3372         SSVAL(p, 6, st.day);
3373         SSVAL(p, 8, st.hour);
3374         SSVAL(p, 10, st.minute);
3375         SSVAL(p, 12, st.second);
3376         SSVAL(p, 14, st.milliseconds);
3377 }
3378
3379 struct s_notify_info_data_table
3380 {
3381         uint16 type;
3382         uint16 field;
3383         const char *name;
3384         uint32 size;
3385         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3386                     print_queue_struct *queue,
3387                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3388 };
3389
3390 /* A table describing the various print notification constants and
3391    whether the notification data is a pointer to a variable sized
3392    buffer, a one value uint32 or a two value uint32. */
3393
3394 static const struct s_notify_info_data_table notify_info_data_table[] =
3395 {
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_STRING,   spoolss_notify_server_name },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_STRING,   spoolss_notify_printer_name },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_STRING,   spoolss_notify_share_name },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_STRING,   spoolss_notify_port_name },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_STRING,   spoolss_notify_driver_name },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_STRING,   spoolss_notify_comment },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_STRING,   spoolss_notify_location },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_POINTER,   spoolss_notify_devmode },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_STRING,   spoolss_notify_sepfile },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_STRING,   spoolss_notify_print_processor },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_STRING,   spoolss_notify_parameters },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_STRING,   spoolss_notify_datatype },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC,   spoolss_notify_security_desc },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_ONE_VALUE, spoolss_notify_priority },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_ONE_VALUE, spoolss_notify_status },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_POINTER,   NULL },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_POINTER,   NULL },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_POINTER,   NULL },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_POINTER,   NULL },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_POINTER,   NULL },
3422 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_STRING,   spoolss_notify_printer_name },
3423 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_STRING,   spoolss_notify_server_name },
3424 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_STRING,   spoolss_notify_port_name },
3425 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_STRING,   spoolss_notify_username },
3426 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_STRING,   spoolss_notify_username },
3427 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_STRING,   spoolss_notify_datatype },
3428 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_STRING,   spoolss_notify_print_processor },
3429 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_STRING,   spoolss_notify_parameters },
3430 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_STRING,   spoolss_notify_driver_name },
3431 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_POINTER,   spoolss_notify_devmode },
3432 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3433 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_STRING,   spoolss_notify_job_status_string },
3434 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_POINTER,   NULL },
3435 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_STRING,   spoolss_notify_job_name },
3436 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_ONE_VALUE, spoolss_notify_priority },
3437 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3438 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_POINTER,   spoolss_notify_submitted_time },
3439 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3440 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3441 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3442 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3443 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3444 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3445 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3446 };
3447
3448 /*******************************************************************
3449  Return the size of info_data structure.
3450 ********************************************************************/
3451
3452 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3453 {
3454         int i=0;
3455
3456         for (i = 0; i < sizeof(notify_info_data_table); i++) 
3457         {
3458                 if ( (notify_info_data_table[i].type == type)
3459                         && (notify_info_data_table[i].field == field) ) 
3460                 {
3461                         switch(notify_info_data_table[i].size) 
3462                         {
3463                         case NOTIFY_ONE_VALUE:
3464                         case NOTIFY_TWO_VALUE:
3465                                 return 1;
3466                         case NOTIFY_STRING:
3467                                 return 2;
3468
3469                         /* The only pointer notify data I have seen on
3470                            the wire is the submitted time and this has
3471                            the notify size set to 4. -tpot */
3472
3473                         case NOTIFY_POINTER:
3474                                 return 4;
3475                                         
3476                                 case NOTIFY_SECDESC:
3477                                         return 5;
3478                         }
3479                 }
3480         }
3481
3482         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3483
3484         return 0;
3485 }
3486
3487 /*******************************************************************
3488  Return the type of notify_info_data.
3489 ********************************************************************/
3490
3491 static int type_of_notify_info_data(uint16 type, uint16 field)
3492 {
3493         int i=0;
3494
3495         for (i = 0; i < sizeof(notify_info_data_table); i++) {
3496                 if (notify_info_data_table[i].type == type &&
3497                     notify_info_data_table[i].field == field)
3498                         return notify_info_data_table[i].size;
3499         }
3500
3501         return False;
3502 }
3503
3504 /****************************************************************************
3505 ****************************************************************************/
3506
3507 static int search_notify(uint16 type, uint16 field, int *value)
3508 {       
3509         int i;
3510
3511         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3512                 if (notify_info_data_table[i].type == type &&
3513                     notify_info_data_table[i].field == field &&
3514                     notify_info_data_table[i].fn != NULL) {
3515                         *value = i;
3516                         return True;
3517                 }
3518         }
3519         
3520         return False;   
3521 }
3522
3523 /****************************************************************************
3524 ****************************************************************************/
3525
3526 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3527 {
3528         info_data->type     = type;
3529         info_data->field    = field;
3530         info_data->reserved = 0;
3531
3532         info_data->size     = size_of_notify_info_data(type, field);
3533         info_data->enc_type = type_of_notify_info_data(type, field);
3534
3535         info_data->id = id;
3536
3537 }
3538
3539
3540 /*******************************************************************
3541  *
3542  * fill a notify_info struct with info asked
3543  *
3544  ********************************************************************/
3545
3546 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3547                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3548                                           *option_type, uint32 id,
3549                                           TALLOC_CTX *mem_ctx) 
3550 {
3551         int field_num,j;
3552         uint16 type;
3553         uint16 field;
3554
3555         SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3556         NT_PRINTER_INFO_LEVEL *printer = NULL;
3557         print_queue_struct *queue=NULL;
3558
3559         type=option_type->type;
3560
3561         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3562                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3563                 option_type->count, lp_servicename(snum)));
3564         
3565         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3566                 return False;
3567