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