69ecf5cc776df6d7cd3eba6f94cf098cb67dd616
[ira/wip.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.
8  *  Copyright (C) Gerald Carter                2000-2001.
9  *  Copyright (C) Tim Potter                        2001.
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 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
33 #endif
34
35 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
36 #define PRINTER_HANDLE_IS_PRINTER       0
37 #define PRINTER_HANDLE_IS_PRINTSERVER   1
38
39 struct table_node {
40         char    *long_archi;
41         char    *short_archi;
42         int     version;
43 };
44
45
46 /* structure to store the printer handles */
47 /* and a reference to what it's pointing to */
48 /* and the notify info asked about */
49 /* that's the central struct */
50 typedef struct _Printer{
51         BOOL document_started;
52         BOOL page_started;
53     int jobid; /* jobid in printing backend */
54         BOOL printer_type;
55         union {
56                 fstring handlename;
57                 fstring printerservername;
58         } dev;
59         uint32 type;
60         uint32 access;
61         struct {
62                 uint32 flags;
63                 uint32 options;
64                 fstring localmachine;
65                 uint32 printerlocal;
66                 SPOOL_NOTIFY_OPTION *option;
67                 POLICY_HND client_hnd;
68                 uint32 client_connected;
69         } notify;
70         struct {
71                 fstring machine;
72                 fstring user;
73         } client;
74 } Printer_entry;
75
76 typedef struct _counter_printer_0 {
77         ubi_dlNode Next;
78         ubi_dlNode Prev;
79         
80         int snum;
81         uint32 counter;
82 } counter_printer_0;
83
84 static ubi_dlList counter_list;
85
86 static struct cli_state cli;
87 static uint32 smb_connections=0;
88
89 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
90
91 /* translate between internal status numbers and NT status numbers */
92 static int nt_printj_status(int v)
93 {
94         switch (v) {
95         case LPQ_QUEUED:
96                 return 0;
97         case LPQ_PAUSED:
98                 return JOB_STATUS_PAUSED;
99         case LPQ_SPOOLING:
100                 return JOB_STATUS_SPOOLING;
101         case LPQ_PRINTING:
102                 return JOB_STATUS_PRINTING;
103         case LPQ_ERROR:
104                 return JOB_STATUS_ERROR;
105         case LPQ_DELETING:
106                 return JOB_STATUS_DELETING;
107         case LPQ_OFFLINE:
108                 return JOB_STATUS_OFFLINE;
109         case LPQ_PAPEROUT:
110                 return JOB_STATUS_PAPEROUT;
111         case LPQ_PRINTED:
112                 return JOB_STATUS_PRINTED;
113         case LPQ_DELETED:
114                 return JOB_STATUS_DELETED;
115         case LPQ_BLOCKED:
116                 return JOB_STATUS_BLOCKED;
117         case LPQ_USER_INTERVENTION:
118                 return JOB_STATUS_USER_INTERVENTION;
119         }
120         return 0;
121 }
122
123 static int nt_printq_status(int v)
124 {
125         switch (v) {
126         case LPQ_PAUSED:
127                 return PRINTER_STATUS_PAUSED;
128         case LPQ_QUEUED:
129         case LPQ_SPOOLING:
130         case LPQ_PRINTING:
131                 return 0;
132         }
133         return 0;
134 }
135
136 /****************************************************************************
137  Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
138 ****************************************************************************/
139
140 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
141 {
142         if (*pp == NULL)
143                 return;
144
145         SAFE_FREE((*pp)->ctr.type);
146         SAFE_FREE(*pp);
147 }
148
149 /***************************************************************************
150  Disconnect from the client
151 ****************************************************************************/
152
153 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
154 {
155         WERROR status;
156
157         /* weird if the test succeds !!! */
158         if (smb_connections==0) {
159                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
160                 return;
161         }
162
163         if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
164                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
165
166         /* if it's the last connection, deconnect the IPC$ share */
167         if (smb_connections==1) {
168                 if(!spoolss_disconnect_from_client(&cli))
169                         return;
170
171                 message_deregister(MSG_PRINTER_NOTIFY);
172         }
173
174         smb_connections--;
175 }
176
177 /****************************************************************************
178  Functions to free a printer entry datastruct.
179 ****************************************************************************/
180
181 static void free_printer_entry(void *ptr)
182 {
183         Printer_entry *Printer = (Printer_entry *)ptr;
184
185         if (Printer->notify.client_connected==True)
186                 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
187
188         Printer->notify.flags=0;
189         Printer->notify.options=0;
190         Printer->notify.localmachine[0]='\0';
191         Printer->notify.printerlocal=0;
192         free_spool_notify_option(&Printer->notify.option);
193         Printer->notify.option=NULL;
194         Printer->notify.client_connected=False;
195
196         SAFE_FREE(Printer);
197 }
198
199 /****************************************************************************
200  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
201 ****************************************************************************/
202
203 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
204 {
205         SPOOL_NOTIFY_OPTION *new_sp = NULL;
206
207         if (!sp)
208                 return NULL;
209
210         new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
211         if (!new_sp)
212                 return NULL;
213
214         *new_sp = *sp;
215
216         if (sp->ctr.count) {
217                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
218
219                 if (!new_sp->ctr.type) {
220                         SAFE_FREE(new_sp);
221                         return NULL;
222                 }
223         }
224
225         return new_sp;
226 }
227
228 /****************************************************************************
229   find printer index by handle
230 ****************************************************************************/
231
232 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
233 {
234         Printer_entry *find_printer = NULL;
235
236         if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
237                 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
238                 return NULL;
239         }
240
241         return find_printer;
242 }
243
244 /****************************************************************************
245   close printer index by handle
246 ****************************************************************************/
247
248 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
249 {
250         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
251
252         if (!Printer) {
253                 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
254                 return False;
255         }
256
257         close_policy_hnd(p, hnd);
258
259         return True;
260 }       
261
262 /****************************************************************************
263   delete a printer given a handle
264 ****************************************************************************/
265 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
266 {
267         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
268
269         if (!Printer) {
270                 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
271                 return WERR_BADFID;
272         }
273
274         if (del_a_printer(Printer->dev.handlename) != 0) {
275                 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
276                 return WERR_BADFID;
277         }
278
279         /* Check calling user has permission to delete printer.  Note that
280            since we set the snum parameter to -1 only administrators can
281            delete the printer.  This stops people with the Full Control
282            permission from deleting the printer. */
283
284         if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
285                 DEBUG(3, ("printer delete denied by security descriptor\n"));
286                 return WERR_ACCESS_DENIED;
287         }
288
289         if (*lp_deleteprinter_cmd()) {
290
291                 char *cmd = lp_deleteprinter_cmd();
292                 pstring command;
293                 int ret;
294                 int i;
295
296                 /* Printer->dev.handlename equals portname equals sharename */
297                 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
298                                         Printer->dev.handlename);
299
300                 DEBUG(10,("Running [%s]\n", command));
301                 ret = smbrun(command, NULL);
302                 if (ret != 0) {
303                         return WERR_BADFID; /* What to return here? */
304                 }
305                 DEBUGADD(10,("returned [%d]\n", ret));
306
307                 /* Send SIGHUP to process group... is there a better way? */
308                 kill(0, SIGHUP);
309
310                 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
311                         lp_killservice( i );
312                         return WERR_OK;
313                 } else
314                         return WERR_ACCESS_DENIED;
315         }
316
317         return WERR_OK;
318 }
319
320 /****************************************************************************
321   return the snum of a printer corresponding to an handle
322 ****************************************************************************/
323 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
324 {
325         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
326                 
327         if (!Printer) {
328                 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
329                 return False;
330         }
331         
332         switch (Printer->printer_type) {
333         case PRINTER_HANDLE_IS_PRINTER:         
334                 DEBUG(4,("short name:%s\n", Printer->dev.handlename));                  
335                 *number = print_queue_snum(Printer->dev.handlename);
336                 return (*number != -1);
337         case PRINTER_HANDLE_IS_PRINTSERVER:
338                 return False;
339         default:
340                 return False;
341         }
342 }
343
344 /****************************************************************************
345   set printer handle type.
346 ****************************************************************************/
347 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
348 {
349         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
350
351         if (!Printer) {
352                 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
353                 return False;
354         }
355
356         DEBUG(4,("Setting printer access=%x\n", access_required));
357         Printer->access = access_required;
358         return True;            
359 }
360
361 /****************************************************************************
362  Set printer handle type.
363  Check if it's \\server or \\server\printer
364 ****************************************************************************/
365
366 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
367 {
368         DEBUG(3,("Setting printer type=%s\n", handlename));
369
370         if ( strlen(handlename) < 3 ) {
371                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
372                 return False;
373         }
374
375         /* it's a print server */
376         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
377                 DEBUGADD(4,("Printer is a print server\n"));
378                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;          
379         }
380         /* it's a printer */
381         else {
382                 DEBUGADD(4,("Printer is a printer\n"));
383                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
384         }
385
386         return True;
387 }
388
389 /****************************************************************************
390  Set printer handle name.
391 ****************************************************************************/
392
393 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
394 {
395         NT_PRINTER_INFO_LEVEL *printer = NULL;
396         int snum;
397         int n_services=lp_numservices();
398         char *aprinter;
399         BOOL found=False;
400         
401         DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
402
403         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
404                 ZERO_STRUCT(Printer->dev.printerservername);
405                 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
406                 return True;
407         }
408
409         if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
410                 return False;
411         
412         if (*handlename=='\\') {
413                 aprinter=strchr_m(handlename+2, '\\');
414                 aprinter++;
415         }
416         else {
417                 aprinter=handlename;
418         }
419
420         DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
421
422         /*
423          * store the Samba share name in it
424          * in back we have the long printer name
425          * need to iterate all the snum and do a
426          * get_a_printer each time to find the printer
427          * faster to do it here than later.
428          */
429
430         for (snum=0;snum<n_services && found==False;snum++) {
431                 char *printername;
432         
433                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
434                         continue;
435                 
436                 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
437
438                 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
439                         continue;
440
441                 printername=strchr_m(printer->info_2->printername+2, '\\');
442                 printername++;
443
444                 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
445                                 printer->info_2->printername, aprinter ));
446
447                 if ( strlen(printername) != strlen(aprinter) ) {
448                         free_a_printer(&printer, 2);
449                         continue;
450                 }
451                 
452                 if ( strncasecmp(printername, aprinter, strlen(aprinter)))  {
453                         free_a_printer(&printer, 2);
454                         continue;
455                 }
456                 
457                 found=True;
458         }
459
460         /*
461          * if we haven't found a printer with the given handlename
462          * then it can be a share name as you can open both \\server\printer and
463          * \\server\share
464          */
465
466         /*
467          * we still check if the printer description file exists as NT won't be happy
468          * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
469          */
470
471         if (found==False) {
472                 DEBUGADD(5,("Printer not found, checking for share now\n"));
473         
474                 for (snum=0;snum<n_services && found==False;snum++) {
475         
476                         if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
477                                 continue;
478                 
479                         DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
480
481                         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
482                                 continue;
483
484                         DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
485                                         printer->info_2->printername, aprinter ));
486
487                         if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
488                                 free_a_printer(&printer, 2);
489                                 continue;
490                         }
491                 
492                         if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter)))  {
493                                 free_a_printer(&printer, 2);
494                                 continue;
495                         }
496                 
497                         found=True;
498                 }
499         }
500                 
501         if (found==False) {
502                 DEBUGADD(4,("Printer not found\n"));
503                 return False;
504         }
505         
506         snum--;
507         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
508                         printer->info_2->printername, lp_servicename(snum),snum));
509
510         ZERO_STRUCT(Printer->dev.handlename);
511         strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
512         
513         free_a_printer(&printer, 2);
514
515         return True;
516 }
517
518 /****************************************************************************
519   find first available printer slot. creates a printer handle for you.
520  ****************************************************************************/
521
522 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
523 {
524         Printer_entry *new_printer;
525
526         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
527
528         if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
529                 return False;
530
531         ZERO_STRUCTP(new_printer);
532         
533         new_printer->notify.option=NULL;
534                                 
535         if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
536                 SAFE_FREE(new_printer);
537                 return False;
538         }
539
540         if (!set_printer_hnd_printertype(new_printer, name)) {
541                 close_printer_handle(p, hnd);
542                 return False;
543         }
544         
545         if (!set_printer_hnd_name(new_printer, name)) {
546                 close_printer_handle(p, hnd);
547                 return False;
548         }
549
550         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
551
552         return True;
553 }
554
555 /********************************************************************
556  Return True is the handle is a print server.
557  ********************************************************************/
558
559 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
560 {
561         Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
562
563         if (!Printer)
564                 return False;
565                 
566         if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
567                 return False;
568         
569         return True;
570 }
571
572 /****************************************************************************
573  allocate more memory for a BUFFER.
574 ****************************************************************************/
575 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
576 {
577         prs_struct *ps;
578         uint32 extra_space;
579         uint32 old_offset;
580         
581         ps= &buffer->prs;
582
583         /* damn, I'm doing the reverse operation of prs_grow() :) */
584         if (buffer_size < prs_data_size(ps))
585                 extra_space=0;
586         else    
587                 extra_space = buffer_size - prs_data_size(ps);
588
589         /*
590          * save the offset and move to the end of the buffer
591          * prs_grow() checks the extra_space against the offset
592          */
593         old_offset=prs_offset(ps);      
594         prs_set_offset(ps, prs_data_size(ps));
595         
596         if (!prs_grow(ps, extra_space))
597                 return False;
598
599         prs_set_offset(ps, old_offset);
600
601         buffer->string_at_end=prs_data_size(ps);
602
603         return True;
604 }
605
606 /***************************************************************************
607  receive the notify message
608 ****************************************************************************/
609
610 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
611 {
612         fstring printer;
613         WERROR status;
614         struct pipes_struct *p;
615         struct policy *pol;
616         struct handle_list *hl;
617
618         *printer = '\0';
619         fstrcpy(printer,buf);
620
621         if (len == 0) {
622                 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
623                 return;
624         }
625
626         DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
627
628         /*
629          * We need to enumerate all printers. The handle list is shared
630          * across pipes of the same name, so just find the first open
631          * spoolss pipe.
632          */
633
634         hl = NULL;      
635         for ( p = get_first_internal_pipe(); p; get_next_internal_pipe(p)) {
636                 if (strequal(p->name, "spoolss")) {
637                         hl = p->pipe_handles;
638                         break;
639                 }
640         }
641
642         if (!hl) {
643                 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
644                 return;
645         }
646
647         /* Iterate the printer list on this pipe. */
648         for (pol = hl->Policy; pol; pol = pol->next ) {
649                 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
650
651                 if (!find_printer)
652                         continue;
653
654                 /*
655                  * if the entry is the given printer or if it's a printerserver
656                  * we send the message
657                  */
658
659                 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
660                         if (strcmp(find_printer->dev.handlename, printer))
661                                 continue;
662
663                 if (find_printer->notify.client_connected==True)
664                         cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
665         }
666 }
667
668 /***************************************************************************
669  send a notify event
670 ****************************************************************************/
671 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
672 {
673         fstring printer;
674
675         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
676
677         if (!Printer) {
678                 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
679                 return False;
680         }
681
682         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
683                 fstrcpy(printer, Printer->dev.handlename);
684         else
685                 fstrcpy(printer, "");
686
687         /*srv_spoolss_receive_message(printer);*/
688         DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
689
690         broadcast_printer_notify(printer);
691
692         return True;
693 }       
694
695 /********************************************************************
696  * spoolss_open_printer
697  *
698  * called from the spoolss dispatcher
699  ********************************************************************/
700
701 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
702 {
703 #if 0
704         WERROR result = WERR_OK;
705 #endif
706
707         UNISTR2 *printername = NULL;
708         PRINTER_DEFAULT *printer_default = &q_u->printer_default;
709 /*      uint32 user_switch = q_u->user_switch; - notused */
710 /*      SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
711         POLICY_HND *handle = &r_u->handle;
712
713         fstring name;
714         int snum;
715         struct current_user user;
716
717         if (q_u->printername_ptr != 0)
718                 printername = &q_u->printername;
719
720         if (printername == NULL)
721                 return WERR_INVALID_PRINTER_NAME;
722
723         /* some sanity check because you can open a printer or a print server */
724         /* aka: \\server\printer or \\server */
725         unistr2_to_ascii(name, printername, sizeof(name)-1);
726
727         DEBUGADD(3,("checking name: %s\n",name));
728
729         if (!open_printer_hnd(p, handle, name))
730                 return WERR_INVALID_PRINTER_NAME;
731         
732 /*
733         if (printer_default->datatype_ptr != NULL)
734         {
735                 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
736                 set_printer_hnd_datatype(handle, datatype);
737         }
738         else
739                 set_printer_hnd_datatype(handle, "");
740 */
741         
742         if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
743                 close_printer_handle(p, handle);
744                 return WERR_ACCESS_DENIED;
745         }
746                 
747         /*
748            First case: the user is opening the print server:
749
750            Disallow MS AddPrinterWizard if parameter disables it. A Win2k
751            client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
752
753            Then both Win2k and WinNT clients try an OpenPrinterEx with
754            SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
755            or if the user is listed in the smb.conf printer admin parameter.
756
757            Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
758            client view printer folder, but does not show the MSAPW.
759
760            Note: this test needs code to check access rights here too. Jeremy
761            could you look at this?
762            
763            
764            Second case: the user is opening a printer:
765            NT doesn't let us connect to a printer if the connecting user
766            doesn't have print permission.
767
768         */
769
770         get_current_user(&user, p);
771
772         if (handle_is_printserver(p, handle)) {
773                 if (printer_default->access_required == 0) {
774                         return WERR_OK;
775                 }
776                 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
777
778                         /* Printserver handles use global struct... */
779                         snum = -1;
780
781                         if (!lp_ms_add_printer_wizard()) {
782                                 close_printer_handle(p, handle);
783                                 return WERR_ACCESS_DENIED;
784                         }
785                         else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
786                                 return WERR_OK;
787                         } 
788                         else {
789                                 close_printer_handle(p, handle);
790                                 return WERR_ACCESS_DENIED;
791                         }
792                 }
793         }
794         else
795         {
796                 /* NT doesn't let us connect to a printer if the connecting user
797                    doesn't have print permission.  */
798
799                 if (!get_printer_snum(p, handle, &snum))
800                         return WERR_BADFID;
801
802                 /* map an empty access mask to the minimum access mask */
803                 if (printer_default->access_required == 0x0)
804                         printer_default->access_required = PRINTER_ACCESS_USE;
805                 
806
807                 /*
808                  * If we are not serving the printer driver for this printer,
809                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
810                  * will keep NT clients happy  --jerry  
811                  */
812                  
813                 if (lp_use_client_driver(snum) 
814                         && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
815                 {
816                         printer_default->access_required = PRINTER_ACCESS_USE;
817                 }
818
819                 if (!print_access_check(&user, snum, printer_default->access_required)) {
820                         DEBUG(3, ("access DENIED for printer open\n"));
821                         close_printer_handle(p, handle);
822                         return WERR_ACCESS_DENIED;
823                 }
824
825                 /*
826                  * If we have a default device pointer in the
827                  * printer_default struct, then we need to get
828                  * the printer info from the tdb and if there is
829                  * no default devicemode there then we do a *SET*
830                  * here ! This is insanity.... JRA.
831                  */
832
833                 /*
834                  * If the openprinterex rpc call contains a devmode,
835                  * it's a per-user one. This per-user devmode is derivated
836                  * from the global devmode. Openprinterex() contains a per-user 
837                  * devmode for when you do EMF printing and spooling.
838                  * In the EMF case, the NT workstation is only doing half the job
839                  * of rendering the page. The other half is done by running the printer
840                  * driver on the server.
841                  * The EMF file doesn't contain the page description (paper size, orientation, ...).
842                  * The EMF file only contains what is to be printed on the page.
843                  * So in order for the server to know how to print, the NT client sends
844                  * a devicemode attached to the openprinterex call.
845                  * But this devicemode is short lived, it's only valid for the current print job.
846                  *
847                  * If Samba would have supported EMF spooling, this devicemode would
848                  * have been attached to the handle, to sent it to the driver to correctly
849                  * rasterize the EMF file.
850                  *
851                  * As Samba only supports RAW spooling, we only receive a ready-to-print file,
852                  * we just act as a pass-thru between windows and the printer.
853                  *
854                  * In order to know that Samba supports only RAW spooling, NT has to call
855                  * getprinter() at level 2 (attribute field) or NT has to call startdoc()
856                  * and until NT sends a RAW job, we refuse it.
857                  *
858                  * But to call getprinter() or startdoc(), you first need a valid handle,
859                  * and to get an handle you have to call openprintex(). Hence why you have
860                  * a devicemode in the openprinterex() call.
861                  *
862                  *
863                  * Differences between NT4 and NT 2000.
864                  * NT4:
865                  * ---
866                  * On NT4, you only have a global devicemode. This global devicemode can be changed
867                  * by the administrator (or by a user with enough privs). Everytime a user
868                  * wants to print, the devicemode is resetted to the default. In Word, everytime
869                  * you print, the printer's characteristics are always reset to the global devicemode.
870                  *
871                  * NT 2000:
872                  * -------
873                  * In W2K, there is the notion of per-user devicemode. The first time you use
874                  * a printer, a per-user devicemode is build from the global devicemode.
875                  * If you change your per-user devicemode, it is saved in the registry, under the
876                  * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
877                  * printer preferences available.
878                  *
879                  * To change the per-user devicemode: it's the "Printing Preferences ..." button
880                  * on the General Tab of the printer properties windows.
881                  *
882                  * To change the global devicemode: it's the "Printing Defaults..." button
883                  * on the Advanced Tab of the printer properties window.
884                  *
885                  * JFM.
886                  */
887
888
889
890 #if 0
891                 if (printer_default->devmode_cont.devmode != NULL) {
892                         result = printer_write_default_dev( snum, printer_default);
893                         if (result != 0) {
894                                 close_printer_handle(p, handle);
895                                 return result;
896                         }
897                 }
898 #endif
899         }
900
901         return WERR_OK;
902 }
903
904 /****************************************************************************
905 ****************************************************************************/
906 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
907                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
908 {
909         BOOL ret = True;
910
911         switch (level) {
912                 case 2:
913                         ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
914                         break;
915                 default:
916                         break;
917         }
918
919         return ret;
920 }
921
922 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
923                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
924 {
925         BOOL result = True;
926
927         switch (level) {
928                 case 3:
929                         printer->info_3=NULL;
930                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
931                                 result = False;
932                         break;
933                 case 6:
934                         printer->info_6=NULL;
935                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
936                                 result = False;
937                         break;
938                 default:
939                         break;
940         }
941
942         return result;
943 }
944
945 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
946                                 NT_DEVICEMODE **pp_nt_devmode)
947 {
948         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
949
950         /*
951          * Ensure nt_devmode is a valid pointer
952          * as we will be overwriting it.
953          */
954                 
955         if (nt_devmode == NULL) {
956                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
957                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
958                         return False;
959         }
960
961         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
962         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
963
964         nt_devmode->specversion=devmode->specversion;
965         nt_devmode->driverversion=devmode->driverversion;
966         nt_devmode->size=devmode->size;
967         nt_devmode->fields=devmode->fields;
968         nt_devmode->orientation=devmode->orientation;
969         nt_devmode->papersize=devmode->papersize;
970         nt_devmode->paperlength=devmode->paperlength;
971         nt_devmode->paperwidth=devmode->paperwidth;
972         nt_devmode->scale=devmode->scale;
973         nt_devmode->copies=devmode->copies;
974         nt_devmode->defaultsource=devmode->defaultsource;
975         nt_devmode->printquality=devmode->printquality;
976         nt_devmode->color=devmode->color;
977         nt_devmode->duplex=devmode->duplex;
978         nt_devmode->yresolution=devmode->yresolution;
979         nt_devmode->ttoption=devmode->ttoption;
980         nt_devmode->collate=devmode->collate;
981
982         nt_devmode->logpixels=devmode->logpixels;
983         nt_devmode->bitsperpel=devmode->bitsperpel;
984         nt_devmode->pelswidth=devmode->pelswidth;
985         nt_devmode->pelsheight=devmode->pelsheight;
986         nt_devmode->displayflags=devmode->displayflags;
987         nt_devmode->displayfrequency=devmode->displayfrequency;
988         nt_devmode->icmmethod=devmode->icmmethod;
989         nt_devmode->icmintent=devmode->icmintent;
990         nt_devmode->mediatype=devmode->mediatype;
991         nt_devmode->dithertype=devmode->dithertype;
992         nt_devmode->reserved1=devmode->reserved1;
993         nt_devmode->reserved2=devmode->reserved2;
994         nt_devmode->panningwidth=devmode->panningwidth;
995         nt_devmode->panningheight=devmode->panningheight;
996
997         /*
998          * Only change private and driverextra if the incoming devmode
999          * has a new one. JRA.
1000          */
1001
1002         if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1003                 SAFE_FREE(nt_devmode->private);
1004                 nt_devmode->driverextra=devmode->driverextra;
1005                 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1006                         return False;
1007                 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1008         }
1009
1010         *pp_nt_devmode = nt_devmode;
1011
1012         return True;
1013 }
1014
1015 /********************************************************************
1016  * _spoolss_enddocprinter_internal.
1017  ********************************************************************/
1018
1019 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1020 {
1021         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1022         
1023         if (!Printer) {
1024                 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1025                 return WERR_BADFID;
1026         }
1027         
1028         Printer->document_started=False;
1029         print_job_end(Printer->jobid,True);
1030         /* error codes unhandled so far ... */
1031
1032         return WERR_OK;
1033 }
1034
1035 /********************************************************************
1036  * api_spoolss_closeprinter
1037  ********************************************************************/
1038
1039 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1040 {
1041         POLICY_HND *handle = &q_u->handle;
1042
1043         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1044
1045         if (Printer && Printer->document_started)
1046                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1047
1048         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1049
1050         if (!close_printer_handle(p, handle))
1051                 return WERR_BADFID;     
1052                 
1053         return WERR_OK;
1054 }
1055
1056 /********************************************************************
1057  * api_spoolss_deleteprinter
1058
1059  ********************************************************************/
1060
1061 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1062 {
1063         POLICY_HND *handle = &q_u->handle;
1064         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1065         WERROR result;
1066
1067         if (Printer && Printer->document_started)
1068                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1069
1070         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1071
1072         result = delete_printer_handle(p, handle);
1073
1074         if (W_ERROR_IS_OK(result)) {
1075                 srv_spoolss_sendnotify(p, handle);
1076         }
1077                 
1078         return result;
1079 }
1080
1081 /*******************************************************************
1082  * static function to lookup the version id corresponding to an
1083  * long architecture string
1084  ******************************************************************/
1085 static int get_version_id (char * arch)
1086 {
1087         int i;
1088         struct table_node archi_table[]= {
1089  
1090                 {"Windows 4.0",          "WIN40",       0 },
1091                 {"Windows NT x86",       "W32X86",      2 },
1092                 {"Windows NT R4000",     "W32MIPS",     2 },    
1093                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
1094                 {"Windows NT PowerPC",   "W32PPC",      2 },
1095                 {NULL,                   "",            -1 }
1096         };
1097  
1098         for (i=0; archi_table[i].long_archi != NULL; i++)
1099         {
1100                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1101                         return (archi_table[i].version);
1102         }
1103         
1104         return -1;
1105 }
1106
1107 /********************************************************************
1108  * _spoolss_deleteprinterdriver
1109  *
1110  * We currently delete the driver for the architecture only.
1111  * This can leave the driver for other archtectures.  However,
1112  * since every printer associates a "Windows NT x86" driver name
1113  * and we cannot delete that one while it is in use, **and** since
1114  * it is impossible to assign a driver to a Samba printer without
1115  * having the "Windows NT x86" driver installed,...
1116  * 
1117  * ....we should not get into trouble here.  
1118  *
1119  *                                                      --jerry
1120  ********************************************************************/
1121
1122 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, 
1123                                     SPOOL_R_DELETEPRINTERDRIVER *r_u)
1124 {
1125         fstring                         driver;
1126         fstring                         arch;
1127         NT_PRINTER_DRIVER_INFO_LEVEL    info;
1128         int                             version;
1129          
1130         unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1131         unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
1132         
1133         /* check that we have a valid driver name first */
1134         if ((version=get_version_id(arch)) == -1) {
1135                 /* this is what NT returns */
1136                 return WERR_INVALID_ENVIRONMENT;
1137         }
1138                 
1139         ZERO_STRUCT(info);
1140         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1141                 return WERR_UNKNOWN_PRINTER_DRIVER;
1142         }
1143         
1144
1145         if (printer_driver_in_use(arch, driver))
1146         {
1147                 return WERR_PRINTER_DRIVER_IN_USE;
1148         }
1149
1150         return delete_printer_driver(info.info_3);       
1151 }
1152
1153
1154 /********************************************************************
1155  GetPrinterData on a printer server Handle.
1156 ********************************************************************/
1157 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1158 {               
1159         int i;
1160         
1161         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1162                 
1163         if (!strcmp(value, "BeepEnabled")) {
1164                 *type = 0x4;
1165                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1166                         return False;
1167                 SIVAL(*data, 0, 0x01);
1168                 *needed = 0x4;                  
1169                 return True;
1170         }
1171
1172         if (!strcmp(value, "EventLog")) {
1173                 *type = 0x4;
1174                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1175                         return False;
1176                 SIVAL(*data, 0, 0x1B);
1177                 *needed = 0x4;                  
1178                 return True;
1179         }
1180
1181         if (!strcmp(value, "NetPopup")) {
1182                 *type = 0x4;
1183                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1184                         return False;
1185                 SIVAL(*data, 0, 0x01);
1186                 *needed = 0x4;
1187                 return True;
1188         }
1189
1190         if (!strcmp(value, "MajorVersion")) {
1191                 *type = 0x4;
1192                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1193                         return False;
1194                 SIVAL(*data, 0, 0x02);
1195                 *needed = 0x4;
1196                 return True;
1197         }
1198
1199    if (!strcmp(value, "DefaultSpoolDirectory")) {
1200                 pstring string="You are using a Samba server";
1201                 *type = 0x1;                    
1202                 *needed = 2*(strlen(string)+1);         
1203                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1204                         return False;
1205                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1206                 
1207                 /* it's done by hand ready to go on the wire */
1208                 for (i=0; i<strlen(string); i++) {
1209                         (*data)[2*i]=string[i];
1210                         (*data)[2*i+1]='\0';
1211                 }                       
1212                 return True;
1213         }
1214
1215         if (!strcmp(value, "Architecture")) {                   
1216                 pstring string="Windows NT x86";
1217                 *type = 0x1;                    
1218                 *needed = 2*(strlen(string)+1); 
1219                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1220                         return False;
1221                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1222                 for (i=0; i<strlen(string); i++) {
1223                         (*data)[2*i]=string[i];
1224                         (*data)[2*i+1]='\0';
1225                 }                       
1226                 return True;
1227         }
1228         
1229         return False;
1230 }
1231
1232 /********************************************************************
1233  GetPrinterData on a printer Handle.
1234 ********************************************************************/
1235 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1236                                 fstring value, uint32 *type,
1237                                 uint8 **data, uint32 *needed, uint32 in_size )
1238 {
1239         NT_PRINTER_INFO_LEVEL *printer = NULL;
1240         int snum=0;
1241         uint8 *idata=NULL;
1242         uint32 len;
1243         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1244         
1245         DEBUG(5,("getprinterdata_printer\n"));
1246
1247         if (!Printer) {
1248                 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1249                 return False;
1250         }
1251
1252         if(!get_printer_snum(p, handle, &snum))
1253                 return False;
1254
1255         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1256                 return False;
1257
1258         if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1259                 free_a_printer(&printer, 2);
1260                 return False;
1261         }
1262
1263         free_a_printer(&printer, 2);
1264
1265         DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1266
1267         if (in_size) {
1268                 if((*data  = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1269                         return False;
1270                 }
1271
1272                 memset(*data, 0, in_size *sizeof(uint8));
1273                 /* copy the min(in_size, len) */
1274                 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1275         } else {
1276                 *data = NULL;
1277         }
1278
1279         *needed = len;
1280         
1281         DEBUG(5,("getprinterdata_printer:copy done\n"));
1282                         
1283         SAFE_FREE(idata);
1284         
1285         return True;
1286 }       
1287
1288 /********************************************************************
1289  * spoolss_getprinterdata
1290  ********************************************************************/
1291
1292 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1293 {
1294         POLICY_HND *handle = &q_u->handle;
1295         UNISTR2 *valuename = &q_u->valuename;
1296         uint32 in_size = q_u->size;
1297         uint32 *type = &r_u->type;
1298         uint32 *out_size = &r_u->size;
1299         uint8 **data = &r_u->data;
1300         uint32 *needed = &r_u->needed;
1301
1302         fstring value;
1303         BOOL found=False;
1304         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1305         
1306         /*
1307          * Reminder: when it's a string, the length is in BYTES
1308          * even if UNICODE is negociated.
1309          *
1310          * JFM, 4/19/1999
1311          */
1312
1313         *out_size=in_size;
1314
1315         /* in case of problem, return some default values */
1316         *needed=0;
1317         *type=0;
1318         
1319         DEBUG(4,("_spoolss_getprinterdata\n"));
1320         
1321         if (!Printer) {
1322                 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1323                         return WERR_NOMEM;
1324                 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1325                 return WERR_BADFID;
1326         }
1327         
1328         unistr2_to_ascii(value, valuename, sizeof(value)-1);
1329         
1330         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1331                 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1332         else
1333                 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1334
1335         if (found==False) {
1336                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1337                 /* reply this param doesn't exist */
1338                 if (*out_size) {
1339                         if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1340                                 return WERR_NOMEM;
1341                 } else {
1342                         *data = NULL;
1343                 }
1344
1345                 return WERR_INVALID_PARAM;
1346         }
1347         
1348         if (*needed > *out_size)
1349                 return WERR_STATUS_MORE_ENTRIES;
1350         else 
1351                 return WERR_OK;
1352 }
1353
1354 /***************************************************************************
1355  connect to the client
1356 ****************************************************************************/
1357 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1358 {
1359         WERROR status;
1360
1361         /*
1362          * If it's the first connection, contact the client
1363          * and connect to the IPC$ share anonumously
1364          */
1365         if (smb_connections==0) {
1366                 fstring unix_printer;
1367
1368                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1369
1370                 if(!spoolss_connect_to_client(&cli, unix_printer))
1371                         return False;
1372                 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1373
1374         }
1375
1376         smb_connections++;
1377
1378         if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1379                 return False;
1380
1381         return True;
1382 }
1383
1384 /********************************************************************
1385  * _spoolss_rffpcnex
1386  * ReplyFindFirstPrinterChangeNotifyEx
1387  *
1388  * jfmxxxx: before replying OK: status=0
1389  * should do a rpc call to the workstation asking ReplyOpenPrinter
1390  * have to code it, later.
1391  *
1392  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1393  * called from api_spoolss_rffpcnex
1394  ********************************************************************/
1395
1396 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1397 {
1398         POLICY_HND *handle = &q_u->handle;
1399         uint32 flags = q_u->flags;
1400         uint32 options = q_u->options;
1401         UNISTR2 *localmachine = &q_u->localmachine;
1402         uint32 printerlocal = q_u->printerlocal;
1403         SPOOL_NOTIFY_OPTION *option = q_u->option;
1404
1405         /* store the notify value in the printer struct */
1406
1407         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1408
1409         if (!Printer) {
1410                 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1411                 return WERR_BADFID;
1412         }
1413
1414         Printer->notify.flags=flags;
1415         Printer->notify.options=options;
1416         Printer->notify.printerlocal=printerlocal;
1417
1418         if (Printer->notify.option)
1419                 free_spool_notify_option(&Printer->notify.option);
1420
1421         Printer->notify.option=dup_spool_notify_option(option);
1422
1423         unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1424
1425         /* connect to the client machine and send a ReplyOpenPrinter */
1426         if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1427                                         Printer->notify.printerlocal, 1,
1428                                         &Printer->notify.client_hnd))
1429                 Printer->notify.client_connected=True;
1430
1431         return WERR_OK;
1432 }
1433
1434 /*******************************************************************
1435  * fill a notify_info_data with the servername
1436  ********************************************************************/
1437
1438 static void spoolss_notify_server_name(int snum, 
1439                                        SPOOL_NOTIFY_INFO_DATA *data, 
1440                                        print_queue_struct *queue,
1441                                        NT_PRINTER_INFO_LEVEL *printer,
1442                                        TALLOC_CTX *mem_ctx) 
1443 {
1444         pstring temp_name, temp;
1445         uint32 len;
1446
1447         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1448
1449         len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1450
1451         data->notify_data.data.length = len / 2;
1452         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1453
1454         if (!data->notify_data.data.string) {
1455                 data->notify_data.data.length = 0;
1456                 return;
1457         }
1458         
1459         memcpy(data->notify_data.data.string, temp, len);
1460 }
1461
1462 /*******************************************************************
1463  * fill a notify_info_data with the printername (not including the servername).
1464  ********************************************************************/
1465 static void spoolss_notify_printer_name(int snum, 
1466                                         SPOOL_NOTIFY_INFO_DATA *data, 
1467                                         print_queue_struct *queue,
1468                                         NT_PRINTER_INFO_LEVEL *printer,
1469                                         TALLOC_CTX *mem_ctx)
1470 {
1471         pstring temp;
1472         uint32 len;
1473                 
1474         /* the notify name should not contain the \\server\ part */
1475         char *p = strrchr_m(printer->info_2->printername, '\\');
1476
1477         if (!p) {
1478                 p = printer->info_2->printername;
1479         } else {
1480                 p++;
1481         }
1482
1483         len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1484         data->notify_data.data.length = len / 2;
1485         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1486         
1487         if (!data->notify_data.data.string) {
1488                 data->notify_data.data.length = 0;
1489                 return;
1490         }
1491         
1492         memcpy(data->notify_data.data.string, temp, len);
1493 }
1494
1495 /*******************************************************************
1496  * fill a notify_info_data with the servicename
1497  ********************************************************************/
1498 static void spoolss_notify_share_name(int snum, 
1499                                       SPOOL_NOTIFY_INFO_DATA *data, 
1500                                       print_queue_struct *queue,
1501                                       NT_PRINTER_INFO_LEVEL *printer,
1502                                       TALLOC_CTX *mem_ctx)
1503 {
1504         pstring temp;
1505         uint32 len;
1506
1507         len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1508
1509         data->notify_data.data.length = len / 2;
1510         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1511         
1512         if (!data->notify_data.data.string) {
1513                 data->notify_data.data.length = 0;
1514                 return;
1515         }
1516         
1517         memcpy(data->notify_data.data.string, temp, len);
1518 }
1519
1520 /*******************************************************************
1521  * fill a notify_info_data with the port name
1522  ********************************************************************/
1523 static void spoolss_notify_port_name(int snum, 
1524                                      SPOOL_NOTIFY_INFO_DATA *data, 
1525                                      print_queue_struct *queue,
1526                                      NT_PRINTER_INFO_LEVEL *printer,
1527                                      TALLOC_CTX *mem_ctx)
1528 {
1529         pstring temp;
1530         uint32 len;
1531
1532         /* even if it's strange, that's consistant in all the code */
1533
1534         len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1535
1536         data->notify_data.data.length = len / 2;
1537         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1538         
1539         if (!data->notify_data.data.string) {
1540                 data->notify_data.data.length = 0;
1541                 return;
1542         }
1543         
1544         memcpy(data->notify_data.data.string, temp, len);
1545 }
1546
1547 /*******************************************************************
1548  * fill a notify_info_data with the printername
1549  * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1550  * but it doesn't exist, have to see what to do
1551  ********************************************************************/
1552 static void spoolss_notify_driver_name(int snum, 
1553                                        SPOOL_NOTIFY_INFO_DATA *data,
1554                                        print_queue_struct *queue,
1555                                        NT_PRINTER_INFO_LEVEL *printer,
1556                                        TALLOC_CTX *mem_ctx)
1557 {
1558         pstring temp;
1559         uint32 len;
1560
1561         len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1562         data->notify_data.data.length = len / 2;
1563         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1564         
1565         if (!data->notify_data.data.string) {
1566                 data->notify_data.data.length = 0;
1567                 return;
1568         }
1569         
1570         memcpy(data->notify_data.data.string, temp, len);
1571 }
1572
1573 /*******************************************************************
1574  * fill a notify_info_data with the comment
1575  ********************************************************************/
1576 static void spoolss_notify_comment(int snum, 
1577                                    SPOOL_NOTIFY_INFO_DATA *data,
1578                                    print_queue_struct *queue,
1579                                    NT_PRINTER_INFO_LEVEL *printer,
1580                                    TALLOC_CTX *mem_ctx)
1581 {
1582         pstring temp;
1583         uint32 len;
1584
1585         if (*printer->info_2->comment == '\0')
1586                 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1587
1588         else
1589                 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1590
1591         data->notify_data.data.length = len / 2;
1592         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1593         
1594         if (!data->notify_data.data.string) {
1595                 data->notify_data.data.length = 0;
1596                 return;
1597         }
1598         
1599         memcpy(data->notify_data.data.string, temp, len);
1600 }
1601
1602 /*******************************************************************
1603  * fill a notify_info_data with the comment
1604  * jfm:xxxx incorrect, have to create a new smb.conf option
1605  * location = "Room 1, floor 2, building 3"
1606  ********************************************************************/
1607 static void spoolss_notify_location(int snum, 
1608                                     SPOOL_NOTIFY_INFO_DATA *data,
1609                                     print_queue_struct *queue,
1610                                     NT_PRINTER_INFO_LEVEL *printer,
1611                                     TALLOC_CTX *mem_ctx)
1612 {
1613         pstring temp;
1614         uint32 len;
1615
1616         len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1617
1618         data->notify_data.data.length = len / 2;
1619         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1620         
1621         if (!data->notify_data.data.string) {
1622                 data->notify_data.data.length = 0;
1623                 return;
1624         }
1625         
1626         memcpy(data->notify_data.data.string, temp, len);
1627 }
1628
1629 /*******************************************************************
1630  * fill a notify_info_data with the device mode
1631  * jfm:xxxx don't to it for know but that's a real problem !!!
1632  ********************************************************************/
1633 static void spoolss_notify_devmode(int snum, 
1634                                    SPOOL_NOTIFY_INFO_DATA *data,
1635                                    print_queue_struct *queue,
1636                                    NT_PRINTER_INFO_LEVEL *printer,
1637                                    TALLOC_CTX *mem_ctx)
1638 {
1639 }
1640
1641 /*******************************************************************
1642  * fill a notify_info_data with the separator file name
1643  * jfm:xxxx just return no file could add an option to smb.conf
1644  * separator file = "separator.txt"
1645  ********************************************************************/
1646 static void spoolss_notify_sepfile(int snum, 
1647                                    SPOOL_NOTIFY_INFO_DATA *data, 
1648                                    print_queue_struct *queue,
1649                                    NT_PRINTER_INFO_LEVEL *printer,
1650                                    TALLOC_CTX *mem_ctx)
1651 {
1652         pstring temp;
1653         uint32 len;
1654
1655         len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1656
1657         data->notify_data.data.length = len / 2;
1658         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1659         
1660         if (!data->notify_data.data.string) {
1661                 data->notify_data.data.length = 0;
1662                 return;
1663         }
1664         
1665         memcpy(data->notify_data.data.string, temp, len);
1666 }
1667
1668 /*******************************************************************
1669  * fill a notify_info_data with the print processor
1670  * jfm:xxxx return always winprint to indicate we don't do anything to it
1671  ********************************************************************/
1672 static void spoolss_notify_print_processor(int snum, 
1673                                            SPOOL_NOTIFY_INFO_DATA *data,
1674                                            print_queue_struct *queue,
1675                                            NT_PRINTER_INFO_LEVEL *printer,
1676                                            TALLOC_CTX *mem_ctx)
1677 {
1678         pstring temp;
1679         uint32 len;
1680
1681         len = rpcstr_push(temp,  printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1682
1683         data->notify_data.data.length = len / 2;
1684         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1685         
1686         if (!data->notify_data.data.string) {
1687                 data->notify_data.data.length = 0;
1688                 return;
1689         }
1690         
1691         memcpy(data->notify_data.data.string, temp, len);
1692 }
1693
1694 /*******************************************************************
1695  * fill a notify_info_data with the print processor options
1696  * jfm:xxxx send an empty string
1697  ********************************************************************/
1698 static void spoolss_notify_parameters(int snum, 
1699                                       SPOOL_NOTIFY_INFO_DATA *data,
1700                                       print_queue_struct *queue,
1701                                       NT_PRINTER_INFO_LEVEL *printer,
1702                                       TALLOC_CTX *mem_ctx)
1703 {
1704         pstring temp;
1705         uint32 len;
1706
1707         len = rpcstr_push(temp,  printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1708
1709         data->notify_data.data.length = len / 2;
1710         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1711         
1712         if (!data->notify_data.data.string) {
1713                 data->notify_data.data.length = 0;
1714                 return;
1715         }
1716         
1717         memcpy(data->notify_data.data.string, temp, len);
1718 }
1719
1720 /*******************************************************************
1721  * fill a notify_info_data with the data type
1722  * jfm:xxxx always send RAW as data type
1723  ********************************************************************/
1724 static void spoolss_notify_datatype(int snum, 
1725                                     SPOOL_NOTIFY_INFO_DATA *data,
1726                                     print_queue_struct *queue,
1727                                     NT_PRINTER_INFO_LEVEL *printer,
1728                                     TALLOC_CTX *mem_ctx)
1729 {
1730         pstring temp;
1731         uint32 len;
1732
1733         len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
1734
1735         data->notify_data.data.length = len / 2;
1736         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1737         
1738         if (!data->notify_data.data.string) {
1739                 data->notify_data.data.length = 0;
1740                 return;
1741         }
1742         
1743         memcpy(data->notify_data.data.string, temp, len);
1744 }
1745
1746 /*******************************************************************
1747  * fill a notify_info_data with the security descriptor
1748  * jfm:xxxx send an null pointer to say no security desc
1749  * have to implement security before !
1750  ********************************************************************/
1751 static void spoolss_notify_security_desc(int snum, 
1752                                          SPOOL_NOTIFY_INFO_DATA *data,
1753                                          print_queue_struct *queue,
1754                                          NT_PRINTER_INFO_LEVEL *printer,
1755                                          TALLOC_CTX *mem_ctx)
1756 {
1757         data->notify_data.data.length=0;
1758         data->notify_data.data.string = NULL;
1759 }
1760
1761 /*******************************************************************
1762  * fill a notify_info_data with the attributes
1763  * jfm:xxxx a samba printer is always shared
1764  ********************************************************************/
1765 static void spoolss_notify_attributes(int snum, 
1766                                       SPOOL_NOTIFY_INFO_DATA *data,
1767                                       print_queue_struct *queue,
1768                                       NT_PRINTER_INFO_LEVEL *printer,
1769                                       TALLOC_CTX *mem_ctx)
1770 {
1771         data->notify_data.value[0] = printer->info_2->attributes;
1772         data->notify_data.value[1] = 0;
1773 }
1774
1775 /*******************************************************************
1776  * fill a notify_info_data with the priority
1777  ********************************************************************/
1778 static void spoolss_notify_priority(int snum, 
1779                                     SPOOL_NOTIFY_INFO_DATA *data,
1780                                     print_queue_struct *queue,
1781                                     NT_PRINTER_INFO_LEVEL *printer,
1782                                     TALLOC_CTX *mem_ctx)
1783 {
1784         data->notify_data.value[0] = printer->info_2->priority;
1785         data->notify_data.value[1] = 0;
1786 }
1787
1788 /*******************************************************************
1789  * fill a notify_info_data with the default priority
1790  ********************************************************************/
1791 static void spoolss_notify_default_priority(int snum, 
1792                                             SPOOL_NOTIFY_INFO_DATA *data,
1793                                             print_queue_struct *queue,
1794                                             NT_PRINTER_INFO_LEVEL *printer,
1795                                             TALLOC_CTX *mem_ctx)
1796 {
1797         data->notify_data.value[0] = printer->info_2->default_priority;
1798         data->notify_data.value[1] = 0;
1799 }
1800
1801 /*******************************************************************
1802  * fill a notify_info_data with the start time
1803  ********************************************************************/
1804 static void spoolss_notify_start_time(int snum, 
1805                                       SPOOL_NOTIFY_INFO_DATA *data,
1806                                       print_queue_struct *queue,
1807                                       NT_PRINTER_INFO_LEVEL *printer,
1808                                       TALLOC_CTX *mem_ctx)
1809 {
1810         data->notify_data.value[0] = printer->info_2->starttime;
1811         data->notify_data.value[1] = 0;
1812 }
1813
1814 /*******************************************************************
1815  * fill a notify_info_data with the until time
1816  ********************************************************************/
1817 static void spoolss_notify_until_time(int snum, 
1818                                       SPOOL_NOTIFY_INFO_DATA *data,
1819                                       print_queue_struct *queue,
1820                                       NT_PRINTER_INFO_LEVEL *printer,
1821                                       TALLOC_CTX *mem_ctx)
1822 {
1823         data->notify_data.value[0] = printer->info_2->untiltime;
1824         data->notify_data.value[1] = 0;
1825 }
1826
1827 /*******************************************************************
1828  * fill a notify_info_data with the status
1829  ********************************************************************/
1830 static void spoolss_notify_status(int snum, 
1831                                   SPOOL_NOTIFY_INFO_DATA *data,
1832                                   print_queue_struct *queue,
1833                                   NT_PRINTER_INFO_LEVEL *printer,
1834                                   TALLOC_CTX *mem_ctx)
1835 {
1836         print_status_struct status;
1837
1838         print_queue_length(snum, &status);
1839         data->notify_data.value[0]=(uint32) status.status;
1840         data->notify_data.value[1] = 0;
1841 }
1842
1843 /*******************************************************************
1844  * fill a notify_info_data with the number of jobs queued
1845  ********************************************************************/
1846 static void spoolss_notify_cjobs(int snum, 
1847                                  SPOOL_NOTIFY_INFO_DATA *data,
1848                                  print_queue_struct *queue,
1849                                  NT_PRINTER_INFO_LEVEL *printer, 
1850                                  TALLOC_CTX *mem_ctx)
1851 {
1852         data->notify_data.value[0] = print_queue_length(snum, NULL);
1853         data->notify_data.value[1] = 0;
1854 }
1855
1856 /*******************************************************************
1857  * fill a notify_info_data with the average ppm
1858  ********************************************************************/
1859 static void spoolss_notify_average_ppm(int snum, 
1860                                        SPOOL_NOTIFY_INFO_DATA *data,
1861                                        print_queue_struct *queue,
1862                                        NT_PRINTER_INFO_LEVEL *printer,
1863                                        TALLOC_CTX *mem_ctx)
1864 {
1865         /* always respond 8 pages per minutes */
1866         /* a little hard ! */
1867         data->notify_data.value[0] = printer->info_2->averageppm;
1868         data->notify_data.value[1] = 0;
1869 }
1870
1871 /*******************************************************************
1872  * fill a notify_info_data with username
1873  ********************************************************************/
1874 static void spoolss_notify_username(int snum, 
1875                                     SPOOL_NOTIFY_INFO_DATA *data,
1876                                     print_queue_struct *queue,
1877                                     NT_PRINTER_INFO_LEVEL *printer,
1878                                     TALLOC_CTX *mem_ctx)
1879 {
1880         pstring temp;
1881         uint32 len;
1882
1883         len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
1884
1885
1886         data->notify_data.data.length = len / 2;
1887         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1888         
1889         if (!data->notify_data.data.string) {
1890                 data->notify_data.data.length = 0;
1891                 return;
1892         }
1893         
1894         memcpy(data->notify_data.data.string, temp, len);
1895 }
1896
1897 /*******************************************************************
1898  * fill a notify_info_data with job status
1899  ********************************************************************/
1900 static void spoolss_notify_job_status(int snum, 
1901                                       SPOOL_NOTIFY_INFO_DATA *data,
1902                                       print_queue_struct *queue,
1903                                       NT_PRINTER_INFO_LEVEL *printer,
1904                                       TALLOC_CTX *mem_ctx)
1905 {
1906         data->notify_data.value[0]=nt_printj_status(queue->status);
1907         data->notify_data.value[1] = 0;
1908 }
1909
1910 /*******************************************************************
1911  * fill a notify_info_data with job name
1912  ********************************************************************/
1913 static void spoolss_notify_job_name(int snum, 
1914                                     SPOOL_NOTIFY_INFO_DATA *data,
1915                                     print_queue_struct *queue,
1916                                     NT_PRINTER_INFO_LEVEL *printer,
1917                                     TALLOC_CTX *mem_ctx)
1918 {
1919         pstring temp;
1920         uint32 len;
1921
1922         len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
1923         
1924         data->notify_data.data.length = len / 2;
1925         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1926         
1927         if (!data->notify_data.data.string) {
1928                 data->notify_data.data.length = 0;
1929                 return;
1930         }
1931         
1932         memcpy(data->notify_data.data.string, temp, len);
1933 }
1934
1935 /*******************************************************************
1936  * fill a notify_info_data with job status
1937  ********************************************************************/
1938 static void spoolss_notify_job_status_string(int snum, 
1939                                              SPOOL_NOTIFY_INFO_DATA *data,
1940                                              print_queue_struct *queue,
1941                                              NT_PRINTER_INFO_LEVEL *printer, 
1942                                              TALLOC_CTX *mem_ctx)
1943 {
1944         /*
1945          * Now we're returning job status codes we just return a "" here. JRA.
1946          */
1947
1948         char *p = "";
1949         pstring temp;
1950         uint32 len;
1951
1952 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1953         p = "unknown";
1954
1955         switch (queue->status) {
1956         case LPQ_QUEUED:
1957                 p = "Queued";
1958                 break;
1959         case LPQ_PAUSED:
1960                 p = "";    /* NT provides the paused string */
1961                 break;
1962         case LPQ_SPOOLING:
1963                 p = "Spooling";
1964                 break;
1965         case LPQ_PRINTING:
1966                 p = "Printing";
1967                 break;
1968         }
1969 #endif /* NO LONGER NEEDED. */
1970
1971         len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
1972
1973         data->notify_data.data.length = len / 2;
1974         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1975         
1976         if (!data->notify_data.data.string) {
1977                 data->notify_data.data.length = 0;
1978                 return;
1979         }
1980         
1981         memcpy(data->notify_data.data.string, temp, len);
1982 }
1983
1984 /*******************************************************************
1985  * fill a notify_info_data with job time
1986  ********************************************************************/
1987 static void spoolss_notify_job_time(int snum, 
1988                                     SPOOL_NOTIFY_INFO_DATA *data,
1989                                     print_queue_struct *queue,
1990                                     NT_PRINTER_INFO_LEVEL *printer,
1991                                     TALLOC_CTX *mem_ctx)
1992 {
1993         data->notify_data.value[0]=0x0;
1994         data->notify_data.value[1]=0;
1995 }
1996
1997 /*******************************************************************
1998  * fill a notify_info_data with job size
1999  ********************************************************************/
2000 static void spoolss_notify_job_size(int snum, 
2001                                     SPOOL_NOTIFY_INFO_DATA *data,
2002                                     print_queue_struct *queue,
2003                                     NT_PRINTER_INFO_LEVEL *printer,
2004                                     TALLOC_CTX *mem_ctx)
2005 {
2006         data->notify_data.value[0]=queue->size;
2007         data->notify_data.value[1]=0;
2008 }
2009
2010 /*******************************************************************
2011  Fill a notify_info_data with job position.
2012  ********************************************************************/
2013
2014 static void spoolss_notify_job_position(int snum, 
2015                                         SPOOL_NOTIFY_INFO_DATA *data,
2016                                         print_queue_struct *queue,
2017                                         NT_PRINTER_INFO_LEVEL *printer,
2018                                         TALLOC_CTX *mem_ctx)
2019 {
2020         data->notify_data.value[0]=queue->job;
2021         data->notify_data.value[1]=0;
2022 }
2023
2024 /*******************************************************************
2025  Fill a notify_info_data with submitted time.
2026  ********************************************************************/
2027
2028 static void spoolss_notify_submitted_time(int snum, 
2029                                           SPOOL_NOTIFY_INFO_DATA *data,
2030                                           print_queue_struct *queue,
2031                                           NT_PRINTER_INFO_LEVEL *printer,
2032                                           TALLOC_CTX *mem_ctx)
2033 {
2034         struct tm *t;
2035         uint32 len;
2036         SYSTEMTIME st;
2037         char *p;
2038
2039         t=gmtime(&queue->time);
2040
2041         len = sizeof(SYSTEMTIME);
2042
2043         data->notify_data.data.length = len;
2044         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2045
2046         if (!data->notify_data.data.string) {
2047                 data->notify_data.data.length = 0;
2048                 return;
2049         }
2050         
2051         make_systemtime(&st, t);
2052
2053         /*
2054          * Systemtime must be linearized as a set of UINT16's. 
2055          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2056          */
2057
2058         p = (char *)data->notify_data.data.string;
2059         SSVAL(p, 0, st.year);
2060         SSVAL(p, 2, st.month);
2061         SSVAL(p, 4, st.dayofweek);
2062         SSVAL(p, 6, st.day);
2063         SSVAL(p, 8, st.hour);
2064         SSVAL(p, 10, st.minute);
2065         SSVAL(p, 12, st.second);
2066         SSVAL(p, 14, st.milliseconds);
2067 }
2068
2069 #define END 65535
2070
2071 struct s_notify_info_data_table
2072 {
2073         uint16 type;
2074         uint16 field;
2075         char *name;
2076         uint32 size;
2077         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2078                     print_queue_struct *queue,
2079                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2080 };
2081
2082 struct s_notify_info_data_table notify_info_data_table[] =
2083 {
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         POINTER,   spoolss_notify_server_name },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        POINTER,   spoolss_notify_printer_name },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          POINTER,   spoolss_notify_share_name },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           POINTER,   spoolss_notify_port_name },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         POINTER,   spoolss_notify_driver_name },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             POINTER,   spoolss_notify_comment },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            POINTER,   spoolss_notify_location },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             POINTER,   spoolss_notify_devmode },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             POINTER,   spoolss_notify_sepfile },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     POINTER,   spoolss_notify_print_processor },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          POINTER,   spoolss_notify_parameters },
2095 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            POINTER,   spoolss_notify_datatype },
2096 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER,   spoolss_notify_security_desc },
2097 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          ONE_VALUE, spoolss_notify_attributes },
2098 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            ONE_VALUE, spoolss_notify_priority },
2099 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    ONE_VALUE, spoolss_notify_default_priority },
2100 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          ONE_VALUE, spoolss_notify_start_time },
2101 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          ONE_VALUE, spoolss_notify_until_time },
2102 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              ONE_VALUE, spoolss_notify_status },
2103 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       POINTER,   NULL },
2104 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               ONE_VALUE, spoolss_notify_cjobs },
2105 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         ONE_VALUE, spoolss_notify_average_ppm },
2106 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         POINTER,   NULL },
2107 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       POINTER,   NULL },
2108 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         POINTER,   NULL },
2109 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       POINTER,   NULL },
2110 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            POINTER,   spoolss_notify_printer_name },
2111 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            POINTER,   spoolss_notify_server_name },
2112 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               POINTER,   spoolss_notify_port_name },
2113 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               POINTER,   spoolss_notify_username },
2114 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             POINTER,   spoolss_notify_username },
2115 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                POINTER,   spoolss_notify_datatype },
2116 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         POINTER,   spoolss_notify_print_processor },
2117 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              POINTER,   spoolss_notify_parameters },
2118 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             POINTER,   spoolss_notify_driver_name },
2119 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 POINTER,   spoolss_notify_devmode },
2120 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  ONE_VALUE, spoolss_notify_job_status },
2121 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           POINTER,   spoolss_notify_job_status_string },
2122 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     POINTER,   NULL },
2123 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                POINTER,   spoolss_notify_job_name },
2124 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                ONE_VALUE, spoolss_notify_priority },
2125 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                ONE_VALUE, spoolss_notify_job_position },
2126 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               POINTER,   spoolss_notify_submitted_time },
2127 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              ONE_VALUE, spoolss_notify_start_time },
2128 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              ONE_VALUE, spoolss_notify_until_time },
2129 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    ONE_VALUE, spoolss_notify_job_time },
2130 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             ONE_VALUE, NULL },
2131 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           ONE_VALUE, NULL },
2132 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             ONE_VALUE, spoolss_notify_job_size },
2133 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_BYTES_PRINTED,           "JOB_NOTIFY_BYTES_PRINTED",           ONE_VALUE, NULL },
2134 { END,                 END,                                "",                                   END,       NULL }
2135 };
2136
2137 /*******************************************************************
2138 return the size of info_data structure
2139 ********************************************************************/
2140 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2141 {
2142         int i=0;
2143
2144         while (notify_info_data_table[i].type != END)
2145         {
2146                 if ( (notify_info_data_table[i].type == type ) &&
2147                      (notify_info_data_table[i].field == field ) )
2148                 {
2149                         return (notify_info_data_table[i].size);
2150                 }
2151                 i++;
2152         }
2153         return (65535);
2154 }
2155
2156 /*******************************************************************
2157 return the type of notify_info_data
2158 ********************************************************************/
2159 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2160 {
2161         int i=0;
2162
2163         while (notify_info_data_table[i].type != END)
2164         {
2165                 if ( (notify_info_data_table[i].type == type ) &&
2166                      (notify_info_data_table[i].field == field ) )
2167                 {
2168                         if (notify_info_data_table[i].size == POINTER)
2169                         {
2170                                 return (False);
2171                         }
2172                         else
2173                         {
2174                                 return (True);
2175                         }
2176                 }
2177                 i++;
2178         }
2179         return (False);
2180 }
2181
2182 /****************************************************************************
2183 ****************************************************************************/
2184 static int search_notify(uint16 type, uint16 field, int *value)
2185 {       
2186         int j;
2187         BOOL found;
2188
2189         for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2190         {
2191                 if ( (notify_info_data_table[j].type  == type  ) &&
2192                      (notify_info_data_table[j].field == field ) )
2193                         found=True;
2194         }
2195         *value=--j;
2196
2197         if ( found && (notify_info_data_table[j].fn != NULL) )
2198                 return True;
2199         else
2200                 return False;   
2201 }
2202
2203 /****************************************************************************
2204 ****************************************************************************/
2205 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2206 {
2207         info_data->type     = type;
2208         info_data->field    = field;
2209         info_data->reserved = 0;
2210         info_data->id       = id;
2211         info_data->size     = size_of_notify_info_data(type, field);
2212         info_data->enc_type = type_of_notify_info_data(type, field);
2213 }
2214
2215
2216 /*******************************************************************
2217  *
2218  * fill a notify_info struct with info asked
2219  *
2220  ********************************************************************/
2221 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2222                                           snum, SPOOL_NOTIFY_OPTION_TYPE
2223                                           *option_type, uint32 id,
2224                                           TALLOC_CTX *mem_ctx) 
2225 {
2226         int field_num,j;
2227         uint16 type;
2228         uint16 field;
2229
2230         SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2231         NT_PRINTER_INFO_LEVEL *printer = NULL;
2232         print_queue_struct *queue=NULL;
2233
2234         type=option_type->type;
2235
2236         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2237                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2238                 option_type->count, lp_servicename(snum)));
2239         
2240         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2241                 return False;
2242
2243         for(field_num=0; field_num<option_type->count; field_num++) {
2244                 field = option_type->fields[field_num];
2245                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2246
2247                 if (!search_notify(type, field, &j) )
2248                         continue;
2249
2250                 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2251                         DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2252                         return False;
2253                 }
2254                 else info->data = tid;
2255
2256                 current_data=&info->data[info->count];
2257
2258                 construct_info_data(current_data, type, field, id);             
2259
2260                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
2261                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2262
2263                 notify_info_data_table[j].fn(snum, current_data, queue,
2264                                              printer, mem_ctx);
2265
2266                 info->count++;
2267         }
2268
2269         free_a_printer(&printer, 2);
2270         return True;
2271 }
2272
2273 /*******************************************************************
2274  *
2275  * fill a notify_info struct with info asked
2276  *
2277  ********************************************************************/
2278 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2279                                        SPOOL_NOTIFY_INFO *info,
2280                                        NT_PRINTER_INFO_LEVEL *printer,
2281                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
2282                                        *option_type, uint32 id,
2283                                        TALLOC_CTX *mem_ctx) 
2284 {
2285         int field_num,j;
2286         uint16 type;
2287         uint16 field;
2288
2289         SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2290         
2291         DEBUG(4,("construct_notify_jobs_info\n"));
2292         
2293         type = option_type->type;
2294
2295         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2296                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2297                 option_type->count));
2298
2299         for(field_num=0; field_num<option_type->count; field_num++) {
2300                 field = option_type->fields[field_num];
2301
2302                 if (!search_notify(type, field, &j) )
2303                         continue;
2304
2305                 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2306                         DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2307                         return False;
2308                 }
2309                 else info->data = tid;
2310
2311                 current_data=&(info->data[info->count]);
2312
2313                 construct_info_data(current_data, type, field, id);
2314                 notify_info_data_table[j].fn(snum, current_data, queue,
2315                                              printer, mem_ctx);
2316                 info->count++;
2317         }
2318
2319         return True;
2320 }
2321
2322 /*
2323  * JFM: The enumeration is not that simple, it's even non obvious.
2324  *
2325  * let's take an example: I want to monitor the PRINTER SERVER for
2326  * the printer's name and the number of jobs currently queued.
2327  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2328  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2329  *
2330  * I have 3 printers on the back of my server.
2331  *
2332  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2333  * structures.
2334  *   Number     Data                    Id
2335  *      1       printer 1 name          1
2336  *      2       printer 1 cjob          1
2337  *      3       printer 2 name          2
2338  *      4       printer 2 cjob          2
2339  *      5       printer 3 name          3
2340  *      6       printer 3 name          3
2341  *
2342  * that's the print server case, the printer case is even worse.
2343  */
2344
2345 /*******************************************************************
2346  *
2347  * enumerate all printers on the printserver
2348  * fill a notify_info struct with info asked
2349  *
2350  ********************************************************************/
2351
2352 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, 
2353                                       SPOOL_NOTIFY_INFO *info,
2354                                       TALLOC_CTX *mem_ctx)
2355 {
2356         int snum;
2357         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2358         int n_services=lp_numservices();
2359         int i;
2360         uint32 id;
2361         SPOOL_NOTIFY_OPTION *option;
2362         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2363
2364         DEBUG(4,("printserver_notify_info\n"));
2365         
2366         option=Printer->notify.option;
2367         id=1;
2368         info->version=2;
2369         info->data=NULL;
2370         info->count=0;
2371
2372         for (i=0; i<option->count; i++) {
2373                 option_type=&(option->ctr.type[i]);
2374                 
2375                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2376                         continue;
2377                 
2378                 for (snum=0; snum<n_services; snum++)
2379                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2380                                 if (construct_notify_printer_info
2381                                     (info, snum, option_type, id, mem_ctx))
2382                                         id++;
2383         }
2384                         
2385         /*
2386          * Debugging information, don't delete.
2387          */
2388         /*
2389         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2390         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2391         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2392         
2393         for (i=0; i<info->count; i++) {
2394                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2395                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2396                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2397         }
2398         */
2399         
2400         return WERR_OK;
2401 }
2402
2403 /*******************************************************************
2404  *
2405  * fill a notify_info struct with info asked
2406  *
2407  ********************************************************************/
2408 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2409                                   TALLOC_CTX *mem_ctx)
2410 {
2411         int snum;
2412         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2413         int i;
2414         uint32 id;
2415         SPOOL_NOTIFY_OPTION *option;
2416         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2417         int count,j;
2418         print_queue_struct *queue=NULL;
2419         print_status_struct status;
2420         
2421         DEBUG(4,("printer_notify_info\n"));
2422
2423         option=Printer->notify.option;
2424         id=0xffffffff;
2425         info->version=2;
2426         info->data=NULL;
2427         info->count=0;
2428
2429         get_printer_snum(p, hnd, &snum);
2430
2431         for (i=0; i<option->count; i++) {
2432                 option_type=&option->ctr.type[i];
2433                 
2434                 switch ( option_type->type ) {
2435                 case PRINTER_NOTIFY_TYPE:
2436                         if(construct_notify_printer_info(info, snum, 
2437                                                          option_type, id,
2438                                                          mem_ctx))  
2439                                 id--;
2440                         break;
2441                         
2442                 case JOB_NOTIFY_TYPE: {
2443                         NT_PRINTER_INFO_LEVEL *printer = NULL;
2444
2445                         count = print_queue_status(snum, &queue, &status);
2446
2447                         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, 
2448                                                          lp_servicename(snum))))
2449                                 goto done;
2450
2451                         for (j=0; j<count; j++) {
2452                                 construct_notify_jobs_info(&queue[j], info,
2453                                                            printer, snum,
2454                                                            option_type,
2455                                                            queue[j].job,
2456                                                            mem_ctx); 
2457                         }
2458
2459                         free_a_printer(&printer, 2);
2460                         
2461                 done:
2462                         SAFE_FREE(queue);
2463                         break;
2464                 }
2465                 }
2466         }
2467         
2468         /*
2469          * Debugging information, don't delete.
2470          */
2471         /*
2472         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2473         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2474         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2475         
2476         for (i=0; i<info->count; i++) {
2477                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2478                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2479                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2480         }
2481         */
2482         return WERR_OK;
2483 }
2484
2485 /********************************************************************
2486  * spoolss_rfnpcnex
2487  ********************************************************************/
2488
2489 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2490 {
2491         POLICY_HND *handle = &q_u->handle;
2492 /*      uint32 change = q_u->change; - notused. */
2493 /*      SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2494         SPOOL_NOTIFY_INFO *info = &r_u->info;
2495
2496         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2497         WERROR result = WERR_BADFID;
2498
2499         /* we always have a NOTIFY_INFO struct */
2500         r_u->info_ptr=0x1;
2501
2502         if (!Printer) {
2503                 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2504                          OUR_HANDLE(handle)));
2505                 goto done;
2506         }
2507
2508         DEBUG(4,("Printer type %x\n",Printer->printer_type));
2509
2510         /* jfm: the change value isn't used right now.
2511          *      we will honour it when
2512          *      a) we'll be able to send notification to the client
2513          *      b) we'll have a way to communicate between the spoolss process.
2514          *
2515          *      same thing for option->flags
2516          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2517          *      I don't have a global notification system, I'm sending back all the
2518          *      informations even when _NOTHING_ has changed.
2519          */
2520
2521         /* just ignore the SPOOL_NOTIFY_OPTION */
2522         
2523         switch (Printer->printer_type) {
2524                 case PRINTER_HANDLE_IS_PRINTSERVER:
2525                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
2526                         break;
2527                         
2528                 case PRINTER_HANDLE_IS_PRINTER:
2529                         result = printer_notify_info(p, handle, info, p->mem_ctx);
2530                         break;
2531         }
2532         
2533  done:
2534         return result;
2535 }
2536
2537 /********************************************************************
2538  * construct_printer_info_0
2539  * fill a printer_info_0 struct
2540  ********************************************************************/
2541 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2542 {
2543         pstring chaine;
2544         int count;
2545         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2546         counter_printer_0 *session_counter;
2547         uint32 global_counter;
2548         struct tm *t;
2549         time_t setuptime;
2550         print_status_struct status;
2551         
2552         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2553                 return False;
2554
2555         count = print_queue_length(snum, &status);
2556
2557         /* check if we already have a counter for this printer */       
2558         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2559
2560         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2561                 if (session_counter->snum == snum)
2562                         break;
2563         }
2564
2565         /* it's the first time, add it to the list */
2566         if (session_counter==NULL) {
2567                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2568                         free_a_printer(&ntprinter, 2);
2569                         return False;
2570                 }
2571                 ZERO_STRUCTP(session_counter);
2572                 session_counter->snum=snum;
2573                 session_counter->counter=0;
2574                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2575         }
2576         
2577         /* increment it */
2578         session_counter->counter++;
2579         
2580         /* JFM:
2581          * the global_counter should be stored in a TDB as it's common to all the clients
2582          * and should be zeroed on samba startup
2583          */
2584         global_counter=session_counter->counter;
2585         
2586         pstrcpy(chaine,ntprinter->info_2->printername);
2587
2588         init_unistr(&printer->printername, chaine);
2589         
2590         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2591         init_unistr(&printer->servername, chaine);
2592         
2593         printer->cjobs = count;
2594         printer->total_jobs = 0;
2595         printer->total_bytes = 0;
2596
2597         setuptime = (time_t)ntprinter->info_2->setuptime;
2598         t=gmtime(&setuptime);
2599
2600         printer->year = t->tm_year+1900;
2601         printer->month = t->tm_mon+1;
2602         printer->dayofweek = t->tm_wday;
2603         printer->day = t->tm_mday;
2604         printer->hour = t->tm_hour;
2605         printer->minute = t->tm_min;
2606         printer->second = t->tm_sec;
2607         printer->milliseconds = 0;
2608
2609         printer->global_counter = global_counter;
2610         printer->total_pages = 0;
2611         printer->major_version = 0x0004;        /* NT 4 */
2612         printer->build_version = 0x0565;        /* build 1381 */
2613         printer->unknown7 = 0x1;
2614         printer->unknown8 = 0x0;
2615         printer->unknown9 = 0x0;
2616         printer->session_counter = session_counter->counter;
2617         printer->unknown11 = 0x0;
2618         printer->printer_errors = 0x0;          /* number of print failure */
2619         printer->unknown13 = 0x0;
2620         printer->unknown14 = 0x1;
2621         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
2622         printer->unknown16 =  0x0;
2623         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2624         printer->unknown18 =  0x0;
2625         printer->status = nt_printq_status(status.status);
2626         printer->unknown20 =  0x0;
2627         printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2628         printer->unknown22 = 0x0;
2629         printer->unknown23 = 0x6;               /* 6  ???*/
2630         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
2631         printer->unknown25 = 0;
2632         printer->unknown26 = 0;
2633         printer->unknown27 = 0;
2634         printer->unknown28 = 0;
2635         printer->unknown29 = 0;
2636         
2637         free_a_printer(&ntprinter,2);
2638         return (True);  
2639 }
2640
2641 /********************************************************************
2642  * construct_printer_info_1
2643  * fill a printer_info_1 struct
2644  ********************************************************************/
2645 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2646 {
2647         pstring chaine;
2648         pstring chaine2;
2649         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2650
2651         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2652                 return False;
2653
2654         printer->flags=flags;
2655
2656         if (*ntprinter->info_2->comment == '\0') {
2657                 init_unistr(&printer->comment, lp_comment(snum));
2658                 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2659                         ntprinter->info_2->drivername, lp_comment(snum));
2660         }
2661         else {
2662                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2663                 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2664                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
2665         }
2666                 
2667         slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2668
2669         init_unistr(&printer->description, chaine);
2670         init_unistr(&printer->name, chaine2);   
2671         
2672         free_a_printer(&ntprinter,2);
2673
2674         return True;
2675 }
2676
2677 /****************************************************************************
2678  Free a DEVMODE struct.
2679 ****************************************************************************/
2680
2681 static void free_dev_mode(DEVICEMODE *dev)
2682 {
2683         if (dev == NULL)
2684                 return;
2685
2686         SAFE_FREE(dev->private);
2687         SAFE_FREE(dev); 
2688 }
2689
2690 /****************************************************************************
2691  Create a DEVMODE struct. Returns malloced memory.
2692 ****************************************************************************/
2693
2694 static DEVICEMODE *construct_dev_mode(int snum)
2695 {
2696         char adevice[32];
2697         char aform[32];
2698         NT_PRINTER_INFO_LEVEL *printer = NULL;
2699         NT_DEVICEMODE *ntdevmode = NULL;
2700         DEVICEMODE *devmode = NULL;
2701
2702         DEBUG(7,("construct_dev_mode\n"));
2703         
2704         DEBUGADD(8,("getting printer characteristics\n"));
2705
2706         if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2707                 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2708                 return NULL;
2709         }
2710
2711         ZERO_STRUCTP(devmode);  
2712
2713         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2714                 goto fail;
2715
2716         if (printer->info_2->devmode)
2717                 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2718
2719         if (ntdevmode == NULL)
2720                 goto fail;
2721
2722         DEBUGADD(8,("loading DEVICEMODE\n"));
2723
2724         slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2725         init_unistr(&devmode->devicename, adevice);
2726
2727         slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2728         init_unistr(&devmode->formname, aform);
2729
2730         devmode->specversion      = ntdevmode->specversion;
2731         devmode->driverversion    = ntdevmode->driverversion;
2732         devmode->size             = ntdevmode->size;
2733         devmode->driverextra      = ntdevmode->driverextra;
2734         devmode->fields           = ntdevmode->fields;
2735                                 
2736         devmode->orientation      = ntdevmode->orientation;     
2737         devmode->papersize        = ntdevmode->papersize;
2738         devmode->paperlength      = ntdevmode->paperlength;
2739         devmode->paperwidth       = ntdevmode->paperwidth;
2740         devmode->scale            = ntdevmode->scale;
2741         devmode->copies           = ntdevmode->copies;
2742         devmode->defaultsource    = ntdevmode->defaultsource;
2743         devmode->printquality     = ntdevmode->printquality;
2744         devmode->color            = ntdevmode->color;
2745         devmode->duplex           = ntdevmode->duplex;
2746         devmode->yresolution      = ntdevmode->yresolution;
2747         devmode->ttoption         = ntdevmode->ttoption;
2748         devmode->collate          = ntdevmode->collate;
2749         devmode->icmmethod        = ntdevmode->icmmethod;
2750         devmode->icmintent        = ntdevmode->icmintent;
2751         devmode->mediatype        = ntdevmode->mediatype;
2752         devmode->dithertype       = ntdevmode->dithertype;
2753
2754         if (ntdevmode->private != NULL) {
2755                 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2756                         goto fail;
2757         }
2758
2759         free_nt_devicemode(&ntdevmode);
2760         free_a_printer(&printer,2);
2761
2762         return devmode;
2763
2764   fail:
2765
2766         if (ntdevmode)
2767                 free_nt_devicemode(&ntdevmode);
2768         if (printer)
2769                 free_a_printer(&printer,2);
2770         free_dev_mode(devmode);
2771
2772         return NULL;
2773 }
2774
2775 /********************************************************************
2776  * construct_printer_info_2
2777  * fill a printer_info_2 struct
2778  ********************************************************************/
2779
2780 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2781 {
2782         int count;
2783         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2784
2785         print_status_struct status;
2786
2787         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2788                 return False;
2789                 
2790         count = print_queue_length(snum, &status);
2791
2792         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2793         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2794         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
2795         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
2796         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
2797
2798         if (*ntprinter->info_2->comment == '\0')
2799                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
2800         else
2801                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2802
2803         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
2804         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
2805         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2806         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
2807         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
2808
2809         printer->attributes = ntprinter->info_2->attributes;
2810
2811         printer->priority = ntprinter->info_2->priority;                                /* priority */  
2812         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
2813         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
2814         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
2815         printer->status = nt_printq_status(status.status);                      /* status */
2816         printer->cjobs = count;                                                 /* jobs */
2817         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
2818                         
2819         if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2820                 DEBUG(8, ("Returning NULL Devicemode!\n"));
2821         }
2822
2823         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2824                 /* steal the printer info sec_desc structure.  [badly done]. */
2825                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2826                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2827                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2828                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2829         }
2830         else {
2831                 printer->secdesc = NULL;
2832         }
2833
2834         free_a_printer(&ntprinter, 2);
2835         return True;
2836 }
2837
2838 /********************************************************************
2839  * construct_printer_info_3
2840  * fill a printer_info_3 struct
2841  ********************************************************************/
2842 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2843 {
2844         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2845         PRINTER_INFO_3 *printer = NULL;
2846
2847         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2848                 return False;
2849
2850         *pp_printer = NULL;
2851         if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2852                 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2853                 return False;
2854         }
2855
2856         ZERO_STRUCTP(printer);
2857         
2858         printer->flags = 4; /* These are the components of the SD we are returning. */
2859         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2860                 /* steal the printer info sec_desc structure.  [badly done]. */
2861                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2862
2863 #if 0
2864                 /*
2865                  * Set the flags for the components we are returning.
2866                  */
2867
2868                 if (printer->secdesc->owner_sid)
2869                         printer->flags |= OWNER_SECURITY_INFORMATION;
2870
2871                 if (printer->secdesc->grp_sid)
2872                         printer->flags |= GROUP_SECURITY_INFORMATION;
2873
2874                 if (printer->secdesc->dacl)
2875                         printer->flags |= DACL_SECURITY_INFORMATION;
2876
2877                 if (printer->secdesc->sacl)
2878                         printer->flags |= SACL_SECURITY_INFORMATION;
2879 #endif
2880
2881                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2882                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2883                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2884         }
2885
2886         free_a_printer(&ntprinter, 2);
2887
2888         *pp_printer = printer;
2889         return True;
2890 }
2891
2892 /********************************************************************
2893  * construct_printer_info_4
2894  * fill a printer_info_4 struct
2895  ********************************************************************/
2896
2897 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
2898 {
2899         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2900
2901         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2902                 return False;
2903                 
2904         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2905         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2906         printer->attributes = ntprinter->info_2->attributes;
2907
2908         free_a_printer(&ntprinter, 2);
2909         return True;
2910 }
2911
2912 /********************************************************************
2913  * construct_printer_info_5
2914  * fill a printer_info_5 struct
2915  ********************************************************************/
2916
2917 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
2918 {
2919         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2920
2921         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2922                 return False;
2923                 
2924         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2925         init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
2926         printer->attributes = ntprinter->info_2->attributes;
2927         printer->device_not_selected_timeout = 0x3a98;
2928         printer->transmission_retry_timeout = 0xafc8;
2929
2930         free_a_printer(&ntprinter, 2);
2931         return True;
2932 }
2933
2934
2935 /********************************************************************
2936  Spoolss_enumprinters.
2937 ********************************************************************/
2938 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2939 {
2940         int snum;
2941         int i;
2942         int n_services=lp_numservices();
2943         PRINTER_INFO_1 *tp, *printers=NULL;
2944         PRINTER_INFO_1 current_prt;
2945         
2946         DEBUG(4,("enum_all_printers_info_1\n"));        
2947
2948         for (snum=0; snum<n_services; snum++) {
2949                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2950                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2951                                 
2952                         if (construct_printer_info_1(flags, &current_prt, snum)) {
2953                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2954                                         DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2955                                         SAFE_FREE(printers);
2956                                         *returned=0;
2957                                         return WERR_NOMEM;
2958                                 }
2959                                 else printers = tp;
2960                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
2961                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2962                                 (*returned)++;
2963                         }
2964                 }
2965         }
2966                 
2967         /* check the required size. */  
2968         for (i=0; i<*returned; i++)
2969                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2970
2971         if (!alloc_buffer_size(buffer, *needed))
2972                 return WERR_INSUFFICIENT_BUFFER;
2973
2974         /* fill the buffer with the structures */
2975         for (i=0; i<*returned; i++)
2976                 smb_io_printer_info_1("", buffer, &printers[i], 0);     
2977
2978         /* clear memory */
2979         SAFE_FREE(printers);
2980
2981         if (*needed > offered) {
2982                 *returned=0;
2983                 return WERR_INSUFFICIENT_BUFFER;
2984         }
2985         else
2986                 return WERR_OK;
2987 }
2988
2989 /********************************************************************
2990  enum_all_printers_info_1_local.
2991 *********************************************************************/
2992 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2993 {
2994         DEBUG(4,("enum_all_printers_info_1_local\n"));  
2995         
2996         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2997 }
2998
2999 /********************************************************************
3000  enum_all_printers_info_1_name.
3001 *********************************************************************/
3002 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3003 {
3004         char *s = name;
3005         
3006         DEBUG(4,("enum_all_printers_info_1_name\n"));   
3007         
3008         if ((name[0] == '\\') && (name[1] == '\\'))
3009                 s = name + 2;
3010
3011         if (is_myname_or_ipaddr(s)) {
3012                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3013         }
3014         else
3015                 return WERR_INVALID_NAME;
3016 }
3017
3018 /********************************************************************
3019  enum_all_printers_info_1_remote.
3020 *********************************************************************/
3021 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3022 {
3023         PRINTER_INFO_1 *printer;
3024         fstring printername;
3025         fstring desc;
3026         fstring comment;
3027         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
3028
3029         /* JFM: currently it's more a place holder than anything else.
3030          * In the spooler world there is a notion of server registration.
3031          * the print servers are registring (sp ?) on the PDC (in the same domain)
3032          *
3033          * We should have a TDB here. The registration is done thru an undocumented RPC call.
3034          */
3035         
3036         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3037                 return WERR_NOMEM;
3038
3039         *returned=1;
3040         
3041         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());           
3042         slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3043         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3044
3045         init_unistr(&printer->description, desc);
3046         init_unistr(&printer->name, printername);       
3047         init_unistr(&printer->comment, comment);
3048         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3049                 
3050         /* check the required size. */  
3051         *needed += spoolss_size_printer_info_1(printer);
3052
3053         if (!alloc_buffer_size(buffer, *needed)) {
3054                 SAFE_FREE(printer);
3055                 return WERR_INSUFFICIENT_BUFFER;
3056         }
3057
3058         /* fill the buffer with the structures */
3059         smb_io_printer_info_1("", buffer, printer, 0);  
3060
3061         /* clear memory */
3062         SAFE_FREE(printer);
3063
3064         if (*needed > offered) {
3065                 *returned=0;
3066                 return WERR_INSUFFICIENT_BUFFER;
3067         }
3068         else
3069                 return WERR_OK;
3070 }
3071
3072 /********************************************************************
3073  enum_all_printers_info_1_network.
3074 *********************************************************************/
3075
3076 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3077 {
3078         DEBUG(4,("enum_all_printers_info_1_network\n"));        
3079         
3080         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3081 }
3082
3083 /********************************************************************
3084  * api_spoolss_enumprinters
3085  *
3086  * called from api_spoolss_enumprinters (see this to understand)
3087  ********************************************************************/
3088
3089 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3090 {
3091         int snum;
3092         int i;
3093         int n_services=lp_numservices();
3094         PRINTER_INFO_2 *tp, *printers=NULL;
3095         PRINTER_INFO_2 current_prt;
3096
3097         for (snum=0; snum<n_services; snum++) {
3098                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3099                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3100                                 
3101                         if (construct_printer_info_2(&current_prt, snum)) {
3102                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3103                                         DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3104                                         SAFE_FREE(printers);
3105                                         *returned = 0;
3106                                         return WERR_NOMEM;
3107                                 }
3108                                 else printers = tp;
3109                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
3110                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3111                                 (*returned)++;
3112                         }
3113                 }
3114         }
3115         
3116         /* check the required size. */  
3117         for (i=0; i<*returned; i++)
3118                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3119
3120         if (!alloc_buffer_size(buffer, *needed)) {
3121                 for (i=0; i<*returned; i++) {
3122                         free_devmode(printers[i].devmode);
3123                 }
3124                 SAFE_FREE(printers);
3125                 return WERR_INSUFFICIENT_BUFFER;
3126         }
3127
3128         /* fill the buffer with the structures */
3129         for (i=0; i<*returned; i++)
3130                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);   
3131         
3132         /* clear memory */
3133         for (i=0; i<*returned; i++) {
3134                 free_devmode(printers[i].devmode);
3135         }
3136         SAFE_FREE(printers);
3137
3138         if (*needed > offered) {
3139                 *returned=0;
3140                 return WERR_INSUFFICIENT_BUFFER;
3141         }
3142         else
3143                 return WERR_OK;
3144 }
3145
3146 /********************************************************************
3147  * handle enumeration of printers at level 1
3148  ********************************************************************/
3149 static WERROR enumprinters_level1( uint32 flags, fstring name,
3150                                  NEW_BUFFER *buffer, uint32 offered,
3151                                  uint32 *needed, uint32 *returned)
3152 {
3153         /* Not all the flags are equals */
3154
3155         if (flags & PRINTER_ENUM_LOCAL)
3156                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3157
3158         if (flags & PRINTER_ENUM_NAME)
3159                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3160
3161         if (flags & PRINTER_ENUM_REMOTE)
3162                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3163
3164         if (flags & PRINTER_ENUM_NETWORK)
3165                 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3166
3167         return WERR_OK; /* NT4sp5 does that */
3168 }
3169
3170 /********************************************************************
3171  * handle enumeration of printers at level 2
3172  ********************************************************************/
3173 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3174                                  NEW_BUFFER *buffer, uint32 offered,
3175                                  uint32 *needed, uint32 *returned)
3176 {
3177         char *s = servername;
3178
3179         if (flags & PRINTER_ENUM_LOCAL) {
3180                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3181         }
3182
3183         if (flags & PRINTER_ENUM_NAME) {
3184                 if ((servername[0] == '\\') && (servername[1] == '\\'))
3185                         s = servername + 2;
3186                 if (is_myname_or_ipaddr(s))
3187                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3188                 else
3189                         return WERR_INVALID_NAME;
3190         }
3191
3192         if (flags & PRINTER_ENUM_REMOTE)
3193                 return WERR_UNKNOWN_LEVEL;
3194
3195         return WERR_OK;
3196 }
3197
3198 /********************************************************************
3199  * handle enumeration of printers at level 5
3200  ********************************************************************/
3201 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3202                                  NEW_BUFFER *buffer, uint32 offered,
3203                                  uint32 *needed, uint32 *returned)
3204 {
3205 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3206         return WERR_OK;
3207 }
3208
3209 /********************************************************************
3210  * api_spoolss_enumprinters
3211  *
3212  * called from api_spoolss_enumprinters (see this to understand)
3213  ********************************************************************/
3214
3215 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3216 {
3217         uint32 flags = q_u->flags;
3218         UNISTR2 *servername = &q_u->servername;
3219         uint32 level = q_u->level;
3220         NEW_BUFFER *buffer = NULL;
3221         uint32 offered = q_u->offered;
3222         uint32 *needed = &r_u->needed;
3223         uint32 *returned = &r_u->returned;
3224
3225         fstring name;
3226         
3227         /* that's an [in out] buffer */
3228         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3229         buffer = r_u->buffer;
3230
3231         DEBUG(4,("_spoolss_enumprinters\n"));
3232
3233         *needed=0;
3234         *returned=0;
3235         
3236         /*
3237          * Level 1:
3238          *          flags==PRINTER_ENUM_NAME
3239          *           if name=="" then enumerates all printers
3240          *           if name!="" then enumerate the printer
3241          *          flags==PRINTER_ENUM_REMOTE
3242          *          name is NULL, enumerate printers
3243          * Level 2: name!="" enumerates printers, name can't be NULL
3244          * Level 3: doesn't exist
3245          * Level 4: does a local registry lookup
3246          * Level 5: same as Level 2
3247          */
3248
3249         unistr2_to_ascii(name, servername, sizeof(name)-1);
3250         strupper(name);
3251
3252         switch (level) {
3253         case 1:
3254                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3255         case 2:
3256                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3257         case 5:
3258                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3259         case 3:
3260         case 4:
3261                 break;
3262         }
3263         return WERR_UNKNOWN_LEVEL;
3264 }
3265
3266 /****************************************************************************
3267 ****************************************************************************/
3268 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3269 {
3270         PRINTER_INFO_0 *printer=NULL;
3271
3272         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3273                 return WERR_NOMEM;
3274
3275         construct_printer_info_0(printer, snum);
3276         
3277         /* check the required size. */  
3278         *needed += spoolss_size_printer_info_0(printer);
3279
3280         if (!alloc_buffer_size(buffer, *needed)) {
3281                 SAFE_FREE(printer);
3282                 return WERR_INSUFFICIENT_BUFFER;
3283         }
3284
3285         /* fill the buffer with the structures */
3286         smb_io_printer_info_0("", buffer, printer, 0);  
3287         
3288         /* clear memory */
3289         SAFE_FREE(printer);
3290
3291         if (*needed > offered) {
3292                 return WERR_INSUFFICIENT_BUFFER;
3293         }
3294
3295         return WERR_OK;
3296 }
3297
3298 /****************************************************************************
3299 ****************************************************************************/
3300 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3301 {
3302         PRINTER_INFO_1 *printer=NULL;
3303
3304         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3305                 return WERR_NOMEM;
3306
3307         construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3308         
3309         /* check the required size. */  
3310         *needed += spoolss_size_printer_info_1(printer);
3311
3312         if (!alloc_buffer_size(buffer, *needed)) {
3313                 SAFE_FREE(printer);
3314                 return WERR_INSUFFICIENT_BUFFER;
3315         }
3316
3317         /* fill the buffer with the structures */
3318         smb_io_printer_info_1("", buffer, printer, 0);  
3319         
3320         /* clear memory */
3321         SAFE_FREE(printer);
3322
3323         if (*needed > offered) {
3324                 return WERR_INSUFFICIENT_BUFFER;
3325         }
3326
3327         return WERR_OK; 
3328 }
3329
3330 /****************************************************************************
3331 ****************************************************************************/
3332 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3333 {
3334         PRINTER_INFO_2 *printer=NULL;
3335
3336         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3337                 return WERR_NOMEM;
3338         
3339         construct_printer_info_2(printer, snum);
3340         
3341         /* check the required size. */  
3342         *needed += spoolss_size_printer_info_2(printer);
3343
3344         if (!alloc_buffer_size(buffer, *needed)) {
3345                 free_printer_info_2(printer);
3346                 return WERR_INSUFFICIENT_BUFFER;
3347         }
3348
3349         /* fill the buffer with the structures */
3350         if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3351                 free_printer_info_2(printer);
3352                 return WERR_NOMEM;
3353         }
3354         
3355         /* clear memory */
3356         free_printer_info_2(printer);
3357
3358         if (*needed > offered) {
3359                 return WERR_INSUFFICIENT_BUFFER;
3360         }
3361
3362         return WERR_OK; 
3363 }
3364
3365 /****************************************************************************
3366 ****************************************************************************/
3367 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3368 {
3369         PRINTER_INFO_3 *printer=NULL;
3370
3371         if (!construct_printer_info_3(&printer, snum))
3372                 return WERR_NOMEM;
3373         
3374         /* check the required size. */  
3375         *needed += spoolss_size_printer_info_3(printer);
3376
3377         if (!alloc_buffer_size(buffer, *needed)) {
3378                 free_printer_info_3(printer);
3379                 return WERR_INSUFFICIENT_BUFFER;
3380         }
3381
3382         /* fill the buffer with the structures */
3383         smb_io_printer_info_3("", buffer, printer, 0);  
3384         
3385         /* clear memory */
3386         free_printer_info_3(printer);
3387         
3388         if (*needed > offered) {
3389                 return WERR_INSUFFICIENT_BUFFER;
3390         }
3391
3392         return WERR_OK; 
3393 }
3394
3395 /****************************************************************************
3396 ****************************************************************************/
3397 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3398 {
3399         PRINTER_INFO_4 *printer=NULL;
3400
3401         if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3402                 return WERR_NOMEM;
3403
3404         if (!construct_printer_info_4(printer, snum))
3405                 return WERR_NOMEM;
3406         
3407         /* check the required size. */  
3408         *needed += spoolss_size_printer_info_4(printer);
3409
3410         if (!alloc_buffer_size(buffer, *needed)) {
3411                 free_printer_info_4(printer);
3412                 return WERR_INSUFFICIENT_BUFFER;
3413         }
3414
3415         /* fill the buffer with the structures */
3416         smb_io_printer_info_4("", buffer, printer, 0);  
3417         
3418         /* clear memory */
3419         free_printer_info_4(printer);
3420         
3421         if (*needed > offered) {
3422                 return WERR_INSUFFICIENT_BUFFER;
3423         }
3424
3425         return WERR_OK; 
3426 }
3427
3428 /****************************************************************************
3429 ****************************************************************************/
3430 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3431 {
3432         PRINTER_INFO_5 *printer=NULL;
3433
3434         if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3435                 return WERR_NOMEM;
3436
3437         if (!construct_printer_info_5(printer, snum))
3438                 return WERR_NOMEM;
3439         
3440         /* check the required size. */  
3441         *needed += spoolss_size_printer_info_5(printer);
3442
3443         if (!alloc_buffer_size(buffer, *needed)) {
3444                 free_printer_info_5(printer);
3445                 return WERR_INSUFFICIENT_BUFFER;
3446         }
3447
3448         /* fill the buffer with the structures */
3449         smb_io_printer_info_5("", buffer, printer, 0);  
3450         
3451         /* clear memory */
3452         free_printer_info_5(printer);
3453         
3454         if (*needed > offered) {
3455                 return WERR_INSUFFICIENT_BUFFER;
3456         }
3457
3458         return WERR_OK; 
3459 }
3460
3461 /****************************************************************************
3462 ****************************************************************************/
3463
3464 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3465 {
3466         POLICY_HND *handle = &q_u->handle;
3467         uint32 level = q_u->level;
3468         NEW_BUFFER *buffer = NULL;
3469         uint32 offered = q_u->offered;
3470         uint32 *needed = &r_u->needed;
3471
3472         int snum;
3473
3474         /* that's an [in out] buffer */
3475         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3476         buffer = r_u->buffer;
3477
3478         *needed=0;
3479
3480         if (!get_printer_snum(p, handle, &snum))
3481                 return WERR_BADFID;
3482
3483         switch (level) {
3484         case 0:
3485                 return getprinter_level_0(snum, buffer, offered, needed);
3486         case 1:
3487                 return getprinter_level_1(snum, buffer, offered, needed);
3488         case 2:         
3489                 return getprinter_level_2(snum, buffer, offered, needed);
3490         case 3:         
3491                 return getprinter_level_3(snum, buffer, offered, needed);
3492         case 4:         
3493                 return getprinter_level_4(snum, buffer, offered, needed);
3494         case 5:         
3495                 return getprinter_level_5(snum, buffer, offered, needed);
3496         }
3497         return WERR_UNKNOWN_LEVEL;
3498 }       
3499                 
3500 /********************************************************************
3501  * fill a DRIVER_INFO_1 struct
3502  ********************************************************************/
3503 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3504 {
3505         init_unistr( &info->name, driver.info_3->name);
3506 }
3507
3508 /********************************************************************
3509  * construct_printer_driver_info_1
3510  ********************************************************************/
3511 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3512 {       
3513         NT_PRINTER_INFO_LEVEL *printer = NULL;
3514         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3515
3516         ZERO_STRUCT(driver);
3517
3518         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3519                 return WERR_INVALID_PRINTER_NAME;
3520
3521         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3522                 return WERR_UNKNOWN_PRINTER_DRIVER;
3523
3524         fill_printer_driver_info_1(info, driver, servername, architecture);
3525
3526         free_a_printer(&printer,2);
3527
3528         return WERR_OK;
3529 }
3530
3531 /********************************************************************
3532  * construct_printer_driver_info_2
3533  * fill a printer_info_2 struct
3534  ********************************************************************/
3535 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3536 {
3537         pstring temp;
3538
3539         info->version=driver.info_3->cversion;
3540
3541         init_unistr( &info->name, driver.info_3->name );
3542         init_unistr( &info->architecture, driver.info_3->environment );
3543
3544
3545     if (strlen(driver.info_3->driverpath)) {
3546                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3547                 init_unistr( &info->driverpath, temp );
3548     } else
3549         init_unistr( &info->driverpath, "" );
3550
3551         if (strlen(driver.info_3->datafile)) {
3552                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3553                 init_unistr( &info->datafile, temp );
3554         } else
3555                 init_unistr( &info->datafile, "" );
3556         
3557         if (strlen(driver.info_3->configfile)) {
3558                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3559                 init_unistr( &info->configfile, temp ); 
3560         } else
3561                 init_unistr( &info->configfile, "" );
3562 }
3563
3564 /********************************************************************
3565  * construct_printer_driver_info_2
3566  * fill a printer_info_2 struct
3567  ********************************************************************/
3568 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3569 {
3570         NT_PRINTER_INFO_LEVEL *printer = NULL;
3571         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3572
3573         ZERO_STRUCT(printer);
3574         ZERO_STRUCT(driver);
3575
3576         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3577                 return WERR_INVALID_PRINTER_NAME;
3578
3579         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3580                 return WERR_UNKNOWN_PRINTER_DRIVER;
3581
3582         fill_printer_driver_info_2(info, driver, servername);
3583
3584         free_a_printer(&printer,2);
3585
3586         return WERR_OK;
3587 }
3588
3589 /********************************************************************
3590  * copy a strings array and convert to UNICODE
3591  *
3592  * convert an array of ascii string to a UNICODE string
3593  ********************************************************************/
3594 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3595 {
3596         int i=0;
3597         int j=0;
3598         char *v;
3599         pstring line;
3600         uint16 *tuary;
3601
3602         DEBUG(6,("init_unistr_array\n"));
3603         *uni_array=NULL;
3604
3605         while (1) {
3606                 if (char_array == NULL)
3607                         v = "";
3608                 else {
3609                         v = char_array[i];
3610                         if (!v) v = ""; /* hack to handle null lists */
3611                 }
3612                 if (strlen(v) == 0) break;
3613                 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3614                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3615                 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3616                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
3617                         return;
3618                 }
3619                 else *uni_array = tuary;
3620                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3621                 i++;
3622         }
3623         
3624         if (*uni_array) {
3625                 (*uni_array)[j]=0x0000;
3626         }
3627         
3628         DEBUGADD(6,("last one:done\n"));
3629 }
3630
3631 /********************************************************************
3632  * construct_printer_info_3
3633  * fill a printer_info_3 struct
3634  ********************************************************************/
3635 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3636 {
3637         pstring temp;
3638
3639         ZERO_STRUCTP(info);
3640
3641         info->version=driver.info_3->cversion;
3642
3643         init_unistr( &info->name, driver.info_3->name );        
3644         init_unistr( &info->architecture, driver.info_3->environment );
3645
3646     if (strlen(driver.info_3->driverpath)) {
3647         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3648         init_unistr( &info->driverpath, temp );
3649     } else
3650         init_unistr( &info->driverpath, "" );
3651     
3652     if (strlen(driver.info_3->datafile)) {
3653         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3654         init_unistr( &info->datafile, temp );
3655     } else
3656         init_unistr( &info->datafile, "" );
3657
3658     if (strlen(driver.info_3->configfile)) {
3659         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3660         init_unistr( &info->configfile, temp ); 
3661     } else
3662         init_unistr( &info->configfile, "" );
3663
3664     if (strlen(driver.info_3->helpfile)) {