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