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