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