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