r11135: should fix seg fault in addprinter code reported by Marcin. Allocate memory...
[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;
1733
1734         switch (level) {
1735                 case 2:
1736                         /* allocate memory if needed.  Messy because 
1737                            convert_printer_info is used to update an existing 
1738                            printer or build a new one */
1739
1740                         if ( !printer->info_2 ) {
1741                                 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1742                                 if ( !printer->info_2 ) {
1743                                         DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1744                                         return False;
1745                                 }
1746                         }
1747
1748                         ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1749                         printer->info_2->setuptime = time(NULL);
1750
1751                         return ret;
1752         }
1753
1754         return False;
1755 }
1756
1757 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1758                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1759 {
1760         BOOL result = True;
1761
1762         switch (level) {
1763                 case 3:
1764                         printer->info_3=NULL;
1765                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1766                                 result = False;
1767                         break;
1768                 case 6:
1769                         printer->info_6=NULL;
1770                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1771                                 result = False;
1772                         break;
1773                 default:
1774                         break;
1775         }
1776
1777         return result;
1778 }
1779
1780 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1781                                 NT_DEVICEMODE **pp_nt_devmode)
1782 {
1783         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1784
1785         /*
1786          * Ensure nt_devmode is a valid pointer
1787          * as we will be overwriting it.
1788          */
1789                 
1790         if (nt_devmode == NULL) {
1791                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1792                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1793                         return False;
1794         }
1795
1796         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1797         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1798
1799         nt_devmode->specversion=devmode->specversion;
1800         nt_devmode->driverversion=devmode->driverversion;
1801         nt_devmode->size=devmode->size;
1802         nt_devmode->fields=devmode->fields;
1803         nt_devmode->orientation=devmode->orientation;
1804         nt_devmode->papersize=devmode->papersize;
1805         nt_devmode->paperlength=devmode->paperlength;
1806         nt_devmode->paperwidth=devmode->paperwidth;
1807         nt_devmode->scale=devmode->scale;
1808         nt_devmode->copies=devmode->copies;
1809         nt_devmode->defaultsource=devmode->defaultsource;
1810         nt_devmode->printquality=devmode->printquality;
1811         nt_devmode->color=devmode->color;
1812         nt_devmode->duplex=devmode->duplex;
1813         nt_devmode->yresolution=devmode->yresolution;
1814         nt_devmode->ttoption=devmode->ttoption;
1815         nt_devmode->collate=devmode->collate;
1816
1817         nt_devmode->logpixels=devmode->logpixels;
1818         nt_devmode->bitsperpel=devmode->bitsperpel;
1819         nt_devmode->pelswidth=devmode->pelswidth;
1820         nt_devmode->pelsheight=devmode->pelsheight;
1821         nt_devmode->displayflags=devmode->displayflags;
1822         nt_devmode->displayfrequency=devmode->displayfrequency;
1823         nt_devmode->icmmethod=devmode->icmmethod;
1824         nt_devmode->icmintent=devmode->icmintent;
1825         nt_devmode->mediatype=devmode->mediatype;
1826         nt_devmode->dithertype=devmode->dithertype;
1827         nt_devmode->reserved1=devmode->reserved1;
1828         nt_devmode->reserved2=devmode->reserved2;
1829         nt_devmode->panningwidth=devmode->panningwidth;
1830         nt_devmode->panningheight=devmode->panningheight;
1831
1832         /*
1833          * Only change private and driverextra if the incoming devmode
1834          * has a new one. JRA.
1835          */
1836
1837         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1838                 SAFE_FREE(nt_devmode->nt_dev_private);
1839                 nt_devmode->driverextra=devmode->driverextra;
1840                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1841                         return False;
1842                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1843         }
1844
1845         *pp_nt_devmode = nt_devmode;
1846
1847         return True;
1848 }
1849
1850 /********************************************************************
1851  * _spoolss_enddocprinter_internal.
1852  ********************************************************************/
1853
1854 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1855 {
1856         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1857         int snum;
1858
1859         if (!Printer) {
1860                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1861                 return WERR_BADFID;
1862         }
1863         
1864         if (!get_printer_snum(p, handle, &snum))
1865                 return WERR_BADFID;
1866
1867         Printer->document_started=False;
1868         print_job_end(snum, Printer->jobid,True);
1869         /* error codes unhandled so far ... */
1870
1871         return WERR_OK;
1872 }
1873
1874 /********************************************************************
1875  * api_spoolss_closeprinter
1876  ********************************************************************/
1877
1878 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1879 {
1880         POLICY_HND *handle = &q_u->handle;
1881
1882         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1883
1884         if (Printer && Printer->document_started)
1885                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1886
1887         if (!close_printer_handle(p, handle))
1888                 return WERR_BADFID;     
1889                 
1890         /* clear the returned printer handle.  Observed behavior 
1891            from Win2k server.  Don't think this really matters.
1892            Previous code just copied the value of the closed
1893            handle.    --jerry */
1894
1895         memset(&r_u->handle, '\0', sizeof(r_u->handle));
1896
1897         return WERR_OK;
1898 }
1899
1900 /********************************************************************
1901  * api_spoolss_deleteprinter
1902
1903  ********************************************************************/
1904
1905 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1906 {
1907         POLICY_HND *handle = &q_u->handle;
1908         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1909         WERROR result;
1910
1911         if (Printer && Printer->document_started)
1912                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1913
1914         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1915
1916         result = delete_printer_handle(p, handle);
1917
1918         update_c_setprinter(False);
1919
1920         return result;
1921 }
1922
1923 /*******************************************************************
1924  * static function to lookup the version id corresponding to an
1925  * long architecture string
1926  ******************************************************************/
1927
1928 static int get_version_id (char * arch)
1929 {
1930         int i;
1931         struct table_node archi_table[]= {
1932  
1933                 {"Windows 4.0",          "WIN40",       0 },
1934                 {"Windows NT x86",       "W32X86",      2 },
1935                 {"Windows NT R4000",     "W32MIPS",     2 },    
1936                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
1937                 {"Windows NT PowerPC",   "W32PPC",      2 },
1938                 {"Windows IA64",         "IA64",        3 },
1939                 {"Windows x64",          "x64",         3 },
1940                 {NULL,                   "",            -1 }
1941         };
1942  
1943         for (i=0; archi_table[i].long_archi != NULL; i++)
1944         {
1945                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1946                         return (archi_table[i].version);
1947         }
1948         
1949         return -1;
1950 }
1951
1952 /********************************************************************
1953  * _spoolss_deleteprinterdriver
1954  ********************************************************************/
1955
1956 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1957 {
1958         fstring                         driver;
1959         fstring                         arch;
1960         NT_PRINTER_DRIVER_INFO_LEVEL    info;
1961         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
1962         int                             version;
1963         struct current_user             user;
1964         WERROR                          status;
1965         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1966         
1967         get_current_user(&user, p);
1968          
1969         unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1970         unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
1971         
1972         /* check that we have a valid driver name first */
1973         
1974         if ((version=get_version_id(arch)) == -1) 
1975                 return WERR_INVALID_ENVIRONMENT;
1976                                 
1977         ZERO_STRUCT(info);
1978         ZERO_STRUCT(info_win2k);
1979         
1980         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) 
1981         {
1982                 /* try for Win2k driver if "Windows NT x86" */
1983                 
1984                 if ( version == 2 ) {
1985                         version = 3;
1986                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1987                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1988                                 goto done;
1989                         }
1990                 }
1991                 /* otherwise it was a failure */
1992                 else {
1993                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1994                         goto done;
1995                 }
1996                 
1997         }
1998         
1999         if (printer_driver_in_use(info.info_3)) {
2000                 status = WERR_PRINTER_DRIVER_IN_USE;
2001                 goto done;
2002         }
2003         
2004         if ( version == 2 )
2005         {               
2006                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2007                 {
2008                         /* if we get to here, we now have 2 driver info structures to remove */
2009                         /* remove the Win2k driver first*/
2010                 
2011                         status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2012                         free_a_printer_driver( info_win2k, 3 );
2013                 
2014                         /* this should not have failed---if it did, report to client */
2015                         if ( !W_ERROR_IS_OK(status_win2k) )
2016                         {
2017                                 status = status_win2k;
2018                                 goto done;
2019                         }
2020                 }
2021         }
2022         
2023         status = delete_printer_driver(info.info_3, &user, version, False);
2024         
2025         /* if at least one of the deletes succeeded return OK */
2026         
2027         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2028                 status = WERR_OK;
2029         
2030 done:
2031         free_a_printer_driver( info, 3 );
2032
2033         return status;
2034 }
2035
2036 /********************************************************************
2037  * spoolss_deleteprinterdriverex
2038  ********************************************************************/
2039
2040 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2041 {
2042         fstring                         driver;
2043         fstring                         arch;
2044         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2045         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2046         int                             version;
2047         uint32                          flags = q_u->delete_flags;
2048         BOOL                            delete_files;
2049         struct current_user             user;
2050         WERROR                          status;
2051         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2052         
2053         get_current_user(&user, p);
2054         
2055         unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2056         unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
2057
2058         /* check that we have a valid driver name first */
2059         if ((version=get_version_id(arch)) == -1) {
2060                 /* this is what NT returns */
2061                 return WERR_INVALID_ENVIRONMENT;
2062         }
2063         
2064         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2065                 version = q_u->version;
2066                 
2067         ZERO_STRUCT(info);
2068         ZERO_STRUCT(info_win2k);
2069                 
2070         status = get_a_printer_driver(&info, 3, driver, arch, version);
2071         
2072         if ( !W_ERROR_IS_OK(status) ) 
2073         {
2074                 /* 
2075                  * if the client asked for a specific version, 
2076                  * or this is something other than Windows NT x86,
2077                  * then we've failed 
2078                  */
2079                 
2080                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2081                         goto done;
2082                         
2083                 /* try for Win2k driver if "Windows NT x86" */
2084                 
2085                 version = 3;
2086                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2087                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2088                         goto done;
2089                 }
2090         }
2091                 
2092         if ( printer_driver_in_use(info.info_3) ) {
2093                 status = WERR_PRINTER_DRIVER_IN_USE;
2094                 goto done;
2095         }
2096         
2097         /* 
2098          * we have a couple of cases to consider. 
2099          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2100          *     then the delete should fail if **any** files overlap with 
2101          *     other drivers 
2102          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2103          *     non-overlapping files 
2104          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2105          *     is set, the do not delete any files
2106          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2107          */
2108         
2109         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2110         
2111         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2112                 
2113         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2114                 /* no idea of the correct error here */
2115                 status = WERR_ACCESS_DENIED;    
2116                 goto done;
2117         }
2118
2119                         
2120         /* also check for W32X86/3 if necessary; maybe we already have? */
2121                 
2122         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2123                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3))) 
2124                 {
2125                         
2126                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2127                                 /* no idea of the correct error here */
2128                                 free_a_printer_driver( info_win2k, 3 );
2129                                 status = WERR_ACCESS_DENIED;    
2130                                 goto done;
2131                         }
2132                 
2133                         /* if we get to here, we now have 2 driver info structures to remove */
2134                         /* remove the Win2k driver first*/
2135                 
2136                         status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2137                         free_a_printer_driver( info_win2k, 3 );
2138                                 
2139                         /* this should not have failed---if it did, report to client */
2140                                 
2141                         if ( !W_ERROR_IS_OK(status_win2k) )
2142                                 goto done;
2143                 }
2144         }
2145
2146         status = delete_printer_driver(info.info_3, &user, version, delete_files);
2147
2148         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2149                 status = WERR_OK;
2150 done:
2151         free_a_printer_driver( info, 3 );
2152         
2153         return status;
2154 }
2155
2156
2157 /****************************************************************************
2158  Internal routine for retreiving printerdata
2159  ***************************************************************************/
2160
2161 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, 
2162                                   const char *key, const char *value, uint32 *type, uint8 **data, 
2163                                   uint32 *needed, uint32 in_size  )
2164 {
2165         REGISTRY_VALUE          *val;
2166         uint32                  size;
2167         int                     data_len;
2168         
2169         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2170                 return WERR_BADFILE;
2171         
2172         *type = regval_type( val );
2173
2174         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2175
2176         size = regval_size( val );
2177         
2178         /* copy the min(in_size, len) */
2179         
2180         if ( in_size ) {
2181                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2182                 
2183                 /* special case for 0 length values */
2184                 if ( data_len ) {
2185                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2186                                 return WERR_NOMEM;
2187                 }
2188                 else {
2189                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2190                                 return WERR_NOMEM;
2191                 }
2192         }
2193         else
2194                 *data = NULL;
2195
2196         *needed = size;
2197         
2198         DEBUG(5,("get_printer_dataex: copy done\n"));
2199
2200         return WERR_OK;
2201 }
2202
2203 /****************************************************************************
2204  Internal routine for removing printerdata
2205  ***************************************************************************/
2206
2207 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2208 {
2209         return delete_printer_data( printer->info_2, key, value );
2210 }
2211
2212 /****************************************************************************
2213  Internal routine for storing printerdata
2214  ***************************************************************************/
2215
2216 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value, 
2217                                   uint32 type, uint8 *data, int real_len  )
2218 {
2219         /* the registry objects enforce uniqueness based on value name */
2220
2221         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2222 }
2223
2224 /********************************************************************
2225  GetPrinterData on a printer server Handle.
2226 ********************************************************************/
2227
2228 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2229 {               
2230         int i;
2231         
2232         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2233                 
2234         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2235                 *type = REG_DWORD;
2236                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2237                         return WERR_NOMEM;
2238                 *needed = 0x4;
2239                 return WERR_OK;
2240         }
2241
2242         if (!StrCaseCmp(value, "BeepEnabled")) {
2243                 *type = REG_DWORD;
2244                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2245                         return WERR_NOMEM;
2246                 SIVAL(*data, 0, 0x00);
2247                 *needed = 0x4;                  
2248                 return WERR_OK;
2249         }
2250
2251         if (!StrCaseCmp(value, "EventLog")) {
2252                 *type = REG_DWORD;
2253                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2254                         return WERR_NOMEM;
2255                 /* formally was 0x1b */
2256                 SIVAL(*data, 0, 0x0);
2257                 *needed = 0x4;                  
2258                 return WERR_OK;
2259         }
2260
2261         if (!StrCaseCmp(value, "NetPopup")) {
2262                 *type = REG_DWORD;
2263                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2264                         return WERR_NOMEM;
2265                 SIVAL(*data, 0, 0x00);
2266                 *needed = 0x4;
2267                 return WERR_OK;
2268         }
2269
2270         if (!StrCaseCmp(value, "MajorVersion")) {
2271                 *type = REG_DWORD;
2272                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2273                         return WERR_NOMEM;
2274
2275                 /* Windows NT 4.0 seems to not allow uploading of drivers
2276                    to a server that reports 0x3 as the MajorVersion.
2277                    need to investigate more how Win2k gets around this .
2278                    -- jerry */
2279
2280                 if ( RA_WINNT == get_remote_arch() )
2281                         SIVAL(*data, 0, 2);
2282                 else
2283                         SIVAL(*data, 0, 3);
2284                 
2285                 *needed = 0x4;
2286                 return WERR_OK;
2287         }
2288
2289         if (!StrCaseCmp(value, "MinorVersion")) {
2290                 *type = REG_DWORD;
2291                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2292                         return WERR_NOMEM;
2293                 SIVAL(*data, 0, 0);
2294                 *needed = 0x4;
2295                 return WERR_OK;
2296         }
2297
2298         /* REG_BINARY
2299          *  uint32 size          = 0x114
2300          *  uint32 major         = 5
2301          *  uint32 minor         = [0|1]
2302          *  uint32 build         = [2195|2600]
2303          *  extra unicode string = e.g. "Service Pack 3"
2304          */
2305         if (!StrCaseCmp(value, "OSVersion")) {
2306                 *type = REG_BINARY;
2307                 *needed = 0x114;
2308
2309                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2310                         return WERR_NOMEM;
2311
2312                 SIVAL(*data, 0, *needed);       /* size */
2313                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2314                 SIVAL(*data, 8, 0);
2315                 SIVAL(*data, 12, 2195);         /* build */
2316                 
2317                 /* leave extra string empty */
2318                 
2319                 return WERR_OK;
2320         }
2321
2322
2323         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2324                 const char *string="C:\\PRINTERS";
2325                 *type = REG_SZ;
2326                 *needed = 2*(strlen(string)+1);         
2327                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2328                         return WERR_NOMEM;
2329                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2330                 
2331                 /* it's done by hand ready to go on the wire */
2332                 for (i=0; i<strlen(string); i++) {
2333                         (*data)[2*i]=string[i];
2334                         (*data)[2*i+1]='\0';
2335                 }                       
2336                 return WERR_OK;
2337         }
2338
2339         if (!StrCaseCmp(value, "Architecture")) {                       
2340                 const char *string="Windows NT x86";
2341                 *type = REG_SZ;
2342                 *needed = 2*(strlen(string)+1); 
2343                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2344                         return WERR_NOMEM;
2345                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2346                 for (i=0; i<strlen(string); i++) {
2347                         (*data)[2*i]=string[i];
2348                         (*data)[2*i+1]='\0';
2349                 }                       
2350                 return WERR_OK;
2351         }
2352
2353         if (!StrCaseCmp(value, "DsPresent")) {
2354                 *type = REG_DWORD;
2355                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2356                         return WERR_NOMEM;
2357
2358                 /* only show the publish check box if we are a 
2359                    memeber of a AD domain */
2360
2361                 if ( lp_security() == SEC_ADS )
2362                         SIVAL(*data, 0, 0x01);
2363                 else
2364                         SIVAL(*data, 0, 0x00);
2365
2366                 *needed = 0x4;
2367                 return WERR_OK;
2368         }
2369
2370         if (!StrCaseCmp(value, "DNSMachineName")) {                     
2371                 pstring hostname;
2372                 
2373                 if (!get_mydnsfullname(hostname))
2374                         return WERR_BADFILE;
2375                 *type = REG_SZ;
2376                 *needed = 2*(strlen(hostname)+1);       
2377                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2378                         return WERR_NOMEM;
2379                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2380                 for (i=0; i<strlen(hostname); i++) {
2381                         (*data)[2*i]=hostname[i];
2382                         (*data)[2*i+1]='\0';
2383                 }                       
2384                 return WERR_OK;
2385         }
2386
2387
2388         return WERR_BADFILE;
2389 }
2390
2391 /********************************************************************
2392  * spoolss_getprinterdata
2393  ********************************************************************/
2394
2395 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2396 {
2397         POLICY_HND      *handle = &q_u->handle;
2398         UNISTR2         *valuename = &q_u->valuename;
2399         uint32          in_size = q_u->size;
2400         uint32          *type = &r_u->type;
2401         uint32          *out_size = &r_u->size;
2402         uint8           **data = &r_u->data;
2403         uint32          *needed = &r_u->needed;
2404         WERROR          status;
2405         fstring         value;
2406         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2407         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2408         int             snum = 0;
2409         
2410         /*
2411          * Reminder: when it's a string, the length is in BYTES
2412          * even if UNICODE is negociated.
2413          *
2414          * JFM, 4/19/1999
2415          */
2416
2417         *out_size = in_size;
2418
2419         /* in case of problem, return some default values */
2420         
2421         *needed = 0;
2422         *type   = 0;
2423         
2424         DEBUG(4,("_spoolss_getprinterdata\n"));
2425         
2426         if ( !Printer ) {
2427                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2428                 status = WERR_BADFID;
2429                 goto done;
2430         }
2431         
2432         unistr2_to_ascii(value, valuename, sizeof(value)-1);
2433         
2434         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2435                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2436         else
2437         {
2438                 if ( !get_printer_snum(p,handle, &snum) ) {
2439                         status = WERR_BADFID;
2440                         goto done;
2441                 }
2442
2443                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2444                 if ( !W_ERROR_IS_OK(status) )
2445                         goto done;
2446
2447                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2448
2449                 if ( strequal(value, "ChangeId") ) {
2450                         *type = REG_DWORD;
2451                         *needed = sizeof(uint32);
2452                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2453                                 status = WERR_NOMEM;
2454                                 goto done;
2455                         }
2456                         SIVAL( *data, 0, printer->info_2->changeid );
2457                         status = WERR_OK;
2458                 }
2459                 else
2460                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2461         }
2462
2463         if (*needed > *out_size)
2464                 status = WERR_MORE_DATA;
2465         
2466 done:
2467         if ( !W_ERROR_IS_OK(status) ) 
2468         {
2469                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2470                 
2471                 /* reply this param doesn't exist */
2472                 
2473                 if ( *out_size ) {
2474                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2475                                 if ( printer ) 
2476                                         free_a_printer( &printer, 2 );
2477                                 return WERR_NOMEM;
2478                 } 
2479                 } 
2480                 else {
2481                         *data = NULL;
2482                 }
2483         }
2484         
2485         /* cleanup & exit */
2486
2487         if ( printer )
2488                 free_a_printer( &printer, 2 );
2489         
2490         return status;
2491 }
2492
2493 /*********************************************************
2494  Connect to the client machine.
2495 **********************************************************/
2496
2497 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, struct rpc_pipe_client **pp_pipe,
2498                         struct in_addr *client_ip, const char *remote_machine)
2499 {
2500         NTSTATUS ret;
2501         ZERO_STRUCTP(the_cli);
2502         
2503         if(cli_initialise(the_cli) == NULL) {
2504                 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2505                 return False;
2506         }
2507         
2508         if ( is_zero_ip(*client_ip) ) {
2509                 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2510                         DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2511                         cli_shutdown(the_cli);
2512                 return False;
2513                 }
2514
2515                 if (ismyip(the_cli->dest_ip)) {
2516                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2517                         cli_shutdown(the_cli);
2518                         return False;
2519                 }
2520         }
2521         else {
2522                 the_cli->dest_ip.s_addr = client_ip->s_addr;
2523                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2524                         inet_ntoa(*client_ip) ));
2525         }
2526
2527         if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2528                 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) ));
2529                 cli_shutdown(the_cli);
2530                 return False;
2531         }
2532   
2533         if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2534                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n", 
2535                         remote_machine));
2536                 cli_shutdown(the_cli);
2537                 return False;
2538         }
2539
2540         the_cli->protocol = PROTOCOL_NT1;
2541         cli_setup_signing_state(the_cli, lp_client_signing());
2542   
2543         if (!cli_negprot(the_cli)) {
2544                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2545                 cli_shutdown(the_cli);
2546                 return False;
2547         }
2548
2549         if (the_cli->protocol != PROTOCOL_NT1) {
2550                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2551                 cli_shutdown(the_cli);
2552                 return False;
2553         }
2554     
2555         /*
2556          * Do an anonymous session setup.
2557          */
2558     
2559         if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2560                 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2561                 cli_shutdown(the_cli);
2562                 return False;
2563         }
2564     
2565         if (!(the_cli->sec_mode & 1)) {
2566                 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2567                 cli_shutdown(the_cli);
2568                 return False;
2569         }
2570     
2571         if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2572                 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) ));
2573                 cli_shutdown(the_cli);
2574                 return False;
2575         }
2576
2577         /*
2578          * Ok - we have an anonymous connection to the IPC$ share.
2579          * Now start the NT Domain stuff :-).
2580          */
2581
2582         *pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret);
2583         if(!*pp_pipe) {
2584                 DEBUG(0,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2585                         remote_machine, nt_errstr(ret)));
2586                 cli_shutdown(the_cli);
2587                 return False;
2588         } 
2589
2590         return True;
2591 }
2592
2593 /***************************************************************************
2594  Connect to the client.
2595 ****************************************************************************/
2596
2597 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, 
2598                                         uint32 localprinter, uint32 type, 
2599                                         POLICY_HND *handle, struct in_addr *client_ip)
2600 {
2601         WERROR result;
2602
2603         /*
2604          * If it's the first connection, contact the client
2605          * and connect to the IPC$ share anonymously
2606          */
2607         if (smb_connections==0) {
2608                 struct cli_state notify_cli; /* print notify back-channel */
2609                 fstring unix_printer;
2610
2611                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2612
2613                 ZERO_STRUCT(notify_cli);
2614
2615                 if(!spoolss_connect_to_client(&notify_cli, &notify_cli_pipe, client_ip, unix_printer))
2616                         return False;
2617                         
2618                 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2619                 /* Tell the connections db we're now interested in printer
2620                  * notify messages. */
2621                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2622         }
2623
2624         /* 
2625          * Tell the specific printing tdb we want messages for this printer
2626          * by registering our PID.
2627          */
2628
2629         if (!print_notify_register_pid(snum))
2630                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2631
2632         smb_connections++;
2633
2634         result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter, 
2635                         type, handle);
2636                         
2637         if (!W_ERROR_IS_OK(result))
2638                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2639                         dos_errstr(result)));
2640
2641         return (W_ERROR_IS_OK(result)); 
2642 }
2643
2644 /********************************************************************
2645  * _spoolss_rffpcnex
2646  * ReplyFindFirstPrinterChangeNotifyEx
2647  *
2648  * before replying OK: status=0 a rpc call is made to the workstation
2649  * asking ReplyOpenPrinter 
2650  *
2651  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2652  * called from api_spoolss_rffpcnex
2653  ********************************************************************/
2654
2655 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2656 {
2657         POLICY_HND *handle = &q_u->handle;
2658         uint32 flags = q_u->flags;
2659         uint32 options = q_u->options;
2660         UNISTR2 *localmachine = &q_u->localmachine;
2661         uint32 printerlocal = q_u->printerlocal;
2662         int snum = -1;
2663         SPOOL_NOTIFY_OPTION *option = q_u->option;
2664         struct in_addr client_ip;
2665
2666         /* store the notify value in the printer struct */
2667
2668         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2669
2670         if (!Printer) {
2671                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2672                 return WERR_BADFID;
2673         }
2674
2675         Printer->notify.flags=flags;
2676         Printer->notify.options=options;
2677         Printer->notify.printerlocal=printerlocal;
2678
2679         if (Printer->notify.option)
2680                 free_spool_notify_option(&Printer->notify.option);
2681
2682         Printer->notify.option=dup_spool_notify_option(option);
2683
2684         unistr2_to_ascii(Printer->notify.localmachine, localmachine, 
2685                        sizeof(Printer->notify.localmachine)-1);
2686
2687         /* Connect to the client machine and send a ReplyOpenPrinter */
2688
2689         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2690                 snum = -1;
2691         else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2692                         !get_printer_snum(p, handle, &snum) )
2693                 return WERR_BADFID;
2694                 
2695         client_ip.s_addr = inet_addr(p->conn->client_address);
2696
2697         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2698                                         Printer->notify.printerlocal, 1,
2699                                         &Printer->notify.client_hnd, &client_ip))
2700                 return WERR_SERVER_UNAVAILABLE;
2701
2702         Printer->notify.client_connected=True;
2703
2704         return WERR_OK;
2705 }
2706
2707 /*******************************************************************
2708  * fill a notify_info_data with the servername
2709  ********************************************************************/
2710
2711 void spoolss_notify_server_name(int snum, 
2712                                        SPOOL_NOTIFY_INFO_DATA *data, 
2713                                        print_queue_struct *queue,
2714                                        NT_PRINTER_INFO_LEVEL *printer,
2715                                        TALLOC_CTX *mem_ctx) 
2716 {
2717         pstring temp;
2718         uint32 len;
2719
2720         len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2721
2722         data->notify_data.data.length = len;
2723         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2724
2725         if (!data->notify_data.data.string) {
2726                 data->notify_data.data.length = 0;
2727                 return;
2728         }
2729         
2730         memcpy(data->notify_data.data.string, temp, len);
2731 }
2732
2733 /*******************************************************************
2734  * fill a notify_info_data with the printername (not including the servername).
2735  ********************************************************************/
2736
2737 void spoolss_notify_printer_name(int snum, 
2738                                         SPOOL_NOTIFY_INFO_DATA *data, 
2739                                         print_queue_struct *queue,
2740                                         NT_PRINTER_INFO_LEVEL *printer,
2741                                         TALLOC_CTX *mem_ctx)
2742 {
2743         pstring temp;
2744         uint32 len;
2745                 
2746         /* the notify name should not contain the \\server\ part */
2747         char *p = strrchr(printer->info_2->printername, '\\');
2748
2749         if (!p) {
2750                 p = printer->info_2->printername;
2751         } else {
2752                 p++;
2753         }
2754
2755         len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2756
2757         data->notify_data.data.length = len;
2758         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2759         
2760         if (!data->notify_data.data.string) {
2761                 data->notify_data.data.length = 0;
2762                 return;
2763         }
2764         
2765         memcpy(data->notify_data.data.string, temp, len);
2766 }
2767
2768 /*******************************************************************
2769  * fill a notify_info_data with the servicename
2770  ********************************************************************/
2771
2772 void spoolss_notify_share_name(int snum, 
2773                                       SPOOL_NOTIFY_INFO_DATA *data, 
2774                                       print_queue_struct *queue,
2775                                       NT_PRINTER_INFO_LEVEL *printer,
2776                                       TALLOC_CTX *mem_ctx)
2777 {
2778         pstring temp;
2779         uint32 len;
2780
2781         len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2782
2783         data->notify_data.data.length = len;
2784         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2785         
2786         if (!data->notify_data.data.string) {
2787                 data->notify_data.data.length = 0;
2788                 return;
2789         }
2790         
2791         memcpy(data->notify_data.data.string, temp, len);
2792 }
2793
2794 /*******************************************************************
2795  * fill a notify_info_data with the port name
2796  ********************************************************************/
2797
2798 void spoolss_notify_port_name(int snum, 
2799                                      SPOOL_NOTIFY_INFO_DATA *data, 
2800                                      print_queue_struct *queue,
2801                                      NT_PRINTER_INFO_LEVEL *printer,
2802                                      TALLOC_CTX *mem_ctx)
2803 {
2804         pstring temp;
2805         uint32 len;
2806
2807         /* even if it's strange, that's consistant in all the code */
2808
2809         len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2810
2811         data->notify_data.data.length = len;
2812         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2813         
2814         if (!data->notify_data.data.string) {
2815                 data->notify_data.data.length = 0;
2816                 return;
2817         }
2818         
2819         memcpy(data->notify_data.data.string, temp, len);
2820 }
2821
2822 /*******************************************************************
2823  * fill a notify_info_data with the printername
2824  * but it doesn't exist, have to see what to do
2825  ********************************************************************/
2826
2827 void spoolss_notify_driver_name(int snum, 
2828                                        SPOOL_NOTIFY_INFO_DATA *data,
2829                                        print_queue_struct *queue,
2830                                        NT_PRINTER_INFO_LEVEL *printer,
2831                                        TALLOC_CTX *mem_ctx)
2832 {
2833         pstring temp;
2834         uint32 len;
2835
2836         len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2837
2838         data->notify_data.data.length = len;
2839         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2840         
2841         if (!data->notify_data.data.string) {
2842                 data->notify_data.data.length = 0;
2843                 return;
2844         }
2845         
2846         memcpy(data->notify_data.data.string, temp, len);
2847 }
2848
2849 /*******************************************************************
2850  * fill a notify_info_data with the comment
2851  ********************************************************************/
2852
2853 void spoolss_notify_comment(int snum, 
2854                                    SPOOL_NOTIFY_INFO_DATA *data,
2855                                    print_queue_struct *queue,
2856                                    NT_PRINTER_INFO_LEVEL *printer,
2857                                    TALLOC_CTX *mem_ctx)
2858 {
2859         pstring temp;
2860         uint32 len;
2861
2862         if (*printer->info_2->comment == '\0')
2863                 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2864         else
2865                 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2866
2867         data->notify_data.data.length = len;
2868         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2869         
2870         if (!data->notify_data.data.string) {
2871                 data->notify_data.data.length = 0;
2872                 return;
2873         }
2874         
2875         memcpy(data->notify_data.data.string, temp, len);
2876 }
2877
2878 /*******************************************************************
2879  * fill a notify_info_data with the comment
2880  * location = "Room 1, floor 2, building 3"
2881  ********************************************************************/
2882
2883 void spoolss_notify_location(int snum, 
2884                                     SPOOL_NOTIFY_INFO_DATA *data,
2885                                     print_queue_struct *queue,
2886                                     NT_PRINTER_INFO_LEVEL *printer,
2887                                     TALLOC_CTX *mem_ctx)
2888 {
2889         pstring temp;
2890         uint32 len;
2891
2892         len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2893
2894         data->notify_data.data.length = len;
2895         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2896         
2897         if (!data->notify_data.data.string) {
2898                 data->notify_data.data.length = 0;
2899                 return;
2900         }
2901         
2902         memcpy(data->notify_data.data.string, temp, len);
2903 }
2904
2905 /*******************************************************************
2906  * fill a notify_info_data with the device mode
2907  * jfm:xxxx don't to it for know but that's a real problem !!!
2908  ********************************************************************/
2909
2910 static void spoolss_notify_devmode(int snum, 
2911                                    SPOOL_NOTIFY_INFO_DATA *data,
2912                                    print_queue_struct *queue,
2913                                    NT_PRINTER_INFO_LEVEL *printer,
2914                                    TALLOC_CTX *mem_ctx)
2915 {
2916 }
2917
2918 /*******************************************************************
2919  * fill a notify_info_data with the separator file name
2920  ********************************************************************/
2921
2922 void spoolss_notify_sepfile(int snum, 
2923                                    SPOOL_NOTIFY_INFO_DATA *data, 
2924                                    print_queue_struct *queue,
2925                                    NT_PRINTER_INFO_LEVEL *printer,
2926                                    TALLOC_CTX *mem_ctx)
2927 {
2928         pstring temp;
2929         uint32 len;
2930
2931         len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2932
2933         data->notify_data.data.length = len;
2934         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2935         
2936         if (!data->notify_data.data.string) {
2937                 data->notify_data.data.length = 0;
2938                 return;
2939         }
2940         
2941         memcpy(data->notify_data.data.string, temp, len);
2942 }
2943
2944 /*******************************************************************
2945  * fill a notify_info_data with the print processor
2946  * jfm:xxxx return always winprint to indicate we don't do anything to it
2947  ********************************************************************/
2948
2949 void spoolss_notify_print_processor(int snum, 
2950                                            SPOOL_NOTIFY_INFO_DATA *data,
2951                                            print_queue_struct *queue,
2952                                            NT_PRINTER_INFO_LEVEL *printer,
2953                                            TALLOC_CTX *mem_ctx)
2954 {
2955         pstring temp;
2956         uint32 len;
2957
2958         len = rpcstr_push(temp,  printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2959
2960         data->notify_data.data.length = len;
2961         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2962         
2963         if (!data->notify_data.data.string) {
2964                 data->notify_data.data.length = 0;
2965                 return;
2966         }
2967         
2968         memcpy(data->notify_data.data.string, temp, len);
2969 }
2970
2971 /*******************************************************************
2972  * fill a notify_info_data with the print processor options
2973  * jfm:xxxx send an empty string
2974  ********************************************************************/
2975
2976 void spoolss_notify_parameters(int snum, 
2977                                       SPOOL_NOTIFY_INFO_DATA *data,
2978                                       print_queue_struct *queue,
2979                                       NT_PRINTER_INFO_LEVEL *printer,
2980                                       TALLOC_CTX *mem_ctx)
2981 {
2982         pstring temp;
2983         uint32 len;
2984
2985         len = rpcstr_push(temp,  printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2986
2987         data->notify_data.data.length = len;
2988         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2989         
2990         if (!data->notify_data.data.string) {
2991                 data->notify_data.data.length = 0;
2992                 return;
2993         }
2994         
2995         memcpy(data->notify_data.data.string, temp, len);
2996 }
2997
2998 /*******************************************************************
2999  * fill a notify_info_data with the data type
3000  * jfm:xxxx always send RAW as data type
3001  ********************************************************************/
3002
3003 void spoolss_notify_datatype(int snum, 
3004                                     SPOOL_NOTIFY_INFO_DATA *data,
3005                                     print_queue_struct *queue,
3006                                     NT_PRINTER_INFO_LEVEL *printer,
3007                                     TALLOC_CTX *mem_ctx)
3008 {
3009         pstring temp;
3010         uint32 len;
3011
3012         len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3013
3014         data->notify_data.data.length = len;
3015         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3016         
3017         if (!data->notify_data.data.string) {
3018                 data->notify_data.data.length = 0;
3019                 return;
3020         }
3021         
3022         memcpy(data->notify_data.data.string, temp, len);
3023 }
3024
3025 /*******************************************************************
3026  * fill a notify_info_data with the security descriptor
3027  * jfm:xxxx send an null pointer to say no security desc
3028  * have to implement security before !
3029  ********************************************************************/
3030
3031 static void spoolss_notify_security_desc(int snum, 
3032                                          SPOOL_NOTIFY_INFO_DATA *data,
3033                                          print_queue_struct *queue,
3034                                          NT_PRINTER_INFO_LEVEL *printer,
3035                                          TALLOC_CTX *mem_ctx)
3036 {
3037         data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3038         data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3039 }
3040
3041 /*******************************************************************
3042  * fill a notify_info_data with the attributes
3043  * jfm:xxxx a samba printer is always shared
3044  ********************************************************************/
3045
3046 void spoolss_notify_attributes(int snum, 
3047                                       SPOOL_NOTIFY_INFO_DATA *data,
3048                                       print_queue_struct *queue,
3049                                       NT_PRINTER_INFO_LEVEL *printer,
3050                                       TALLOC_CTX *mem_ctx)
3051 {
3052         data->notify_data.value[0] = printer->info_2->attributes;
3053         data->notify_data.value[1] = 0;
3054 }
3055
3056 /*******************************************************************
3057  * fill a notify_info_data with the priority
3058  ********************************************************************/
3059
3060 static void spoolss_notify_priority(int snum, 
3061                                     SPOOL_NOTIFY_INFO_DATA *data,
3062                                     print_queue_struct *queue,
3063                                     NT_PRINTER_INFO_LEVEL *printer,
3064                                     TALLOC_CTX *mem_ctx)
3065 {
3066         data->notify_data.value[0] = printer->info_2->priority;
3067         data->notify_data.value[1] = 0;
3068 }
3069
3070 /*******************************************************************
3071  * fill a notify_info_data with the default priority
3072  ********************************************************************/
3073
3074 static void spoolss_notify_default_priority(int snum, 
3075                                             SPOOL_NOTIFY_INFO_DATA *data,
3076                                             print_queue_struct *queue,
3077                                             NT_PRINTER_INFO_LEVEL *printer,
3078                                             TALLOC_CTX *mem_ctx)
3079 {
3080         data->notify_data.value[0] = printer->info_2->default_priority;
3081         data->notify_data.value[1] = 0;
3082 }
3083
3084 /*******************************************************************
3085  * fill a notify_info_data with the start time
3086  ********************************************************************/
3087
3088 static void spoolss_notify_start_time(int snum, 
3089                                       SPOOL_NOTIFY_INFO_DATA *data,
3090                                       print_queue_struct *queue,
3091                                       NT_PRINTER_INFO_LEVEL *printer,
3092                                       TALLOC_CTX *mem_ctx)
3093 {
3094         data->notify_data.value[0] = printer->info_2->starttime;
3095         data->notify_data.value[1] = 0;
3096 }
3097
3098 /*******************************************************************
3099  * fill a notify_info_data with the until time
3100  ********************************************************************/
3101
3102 static void spoolss_notify_until_time(int snum, 
3103                                       SPOOL_NOTIFY_INFO_DATA *data,
3104                                       print_queue_struct *queue,
3105                                       NT_PRINTER_INFO_LEVEL *printer,
3106                                       TALLOC_CTX *mem_ctx)
3107 {
3108         data->notify_data.value[0] = printer->info_2->untiltime;
3109         data->notify_data.value[1] = 0;
3110 }
3111
3112 /*******************************************************************
3113  * fill a notify_info_data with the status
3114  ********************************************************************/