Partial conversion of SPOOLSS code to canonical format. More to follow.
[bbaumbach/samba-autobuild/.git] / source / 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_QUEUED:
94                 return 0;
95         case LPQ_PAUSED:
96                 return JOB_STATUS_PAUSED;
97         case LPQ_SPOOLING:
98                 return JOB_STATUS_SPOOLING;
99         case LPQ_PRINTING:
100                 return JOB_STATUS_PRINTING;
101         case LPQ_ERROR:
102                 return JOB_STATUS_ERROR;
103         case LPQ_DELETING:
104                 return JOB_STATUS_DELETING;
105         case LPQ_OFFLINE:
106                 return JOB_STATUS_OFFLINE;
107         case LPQ_PAPEROUT:
108                 return JOB_STATUS_PAPEROUT;
109         case LPQ_PRINTED:
110                 return JOB_STATUS_PRINTED;
111         case LPQ_DELETED:
112                 return JOB_STATUS_DELETED;
113         case LPQ_BLOCKED:
114                 return JOB_STATUS_BLOCKED;
115         case LPQ_USER_INTERVENTION:
116                 return JOB_STATUS_USER_INTERVENTION;
117         }
118         return 0;
119 }
120
121 static int nt_printq_status(int v)
122 {
123         switch (v) {
124         case LPQ_PAUSED:
125                 return PRINTER_STATUS_PAUSED;
126         case LPQ_QUEUED:
127         case LPQ_SPOOLING:
128         case LPQ_PRINTING:
129                 return 0;
130         }
131         return 0;
132 }
133
134 /****************************************************************************
135   initialise printer handle states...
136 ****************************************************************************/
137 void init_printer_hnd(void)
138 {
139         ubi_dlInitList(&Printer_list);
140         ubi_dlInitList(&counter_list);
141 }
142
143 /****************************************************************************
144  Return a user struct for a pipe user.
145 ****************************************************************************/
146
147 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
148 {
149         if (p->ntlmssp_auth_validated) {
150                 memcpy(user, &p->pipe_user, sizeof(struct current_user));
151         } else {
152                 extern struct current_user current_user;
153                 memcpy(user, &current_user, sizeof(struct current_user));
154         }
155
156         return user;
157 }
158
159 /****************************************************************************
160   create a unique printer handle
161 ****************************************************************************/
162 static void create_printer_hnd(POLICY_HND *hnd)
163 {
164         static uint32 prt_hnd_low  = 0;
165         static uint32 prt_hnd_high = 0;
166
167         if (hnd == NULL) return;
168
169         /* i severely doubt that prt_hnd_high will ever be non-zero... */
170         prt_hnd_low++;
171         if (prt_hnd_low == 0) prt_hnd_high++;
172
173         SIVAL(hnd->data, 0 , 0x0);          /* first bit must be null */
174         SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
175         SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
176         SIVAL(hnd->data, 12, time(NULL));   /* something random */
177         SIVAL(hnd->data, 16, sys_getpid());     /* something more random */
178 }
179
180 /****************************************************************************
181   find printer index by handle
182 ****************************************************************************/
183 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
184 {
185         Printer_entry *find_printer;
186
187         find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
188
189         for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
190
191                 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
192                         DEBUG(4,("Found printer handle \n"));
193                         /*dump_data(4, hnd->data, sizeof(hnd->data));*/
194                         return find_printer;
195                 }
196         }
197         
198         DEBUG(3,("Whoops, Printer handle not found: "));
199         /*dump_data(4, hnd->data, sizeof(hnd->data));*/
200         return NULL;
201 }
202
203 /****************************************************************************
204   clear an handle
205 ****************************************************************************/
206 static void clear_handle(POLICY_HND *hnd)
207 {
208         ZERO_STRUCTP(hnd);
209 }
210
211 /***************************************************************************
212  Disconnect from the client
213 ****************************************************************************/
214 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
215 {
216         uint32 status;
217
218         /* weird if the test succeds !!! */
219         if (smb_connections==0) {
220                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
221                 return False;
222         }
223
224         if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
225                 return False;
226
227         /* if it's the last connection, deconnect the IPC$ share */
228         if (smb_connections==1) {
229                 if(!spoolss_disconnect_from_client(&cli))
230                         return False;
231
232                 message_deregister(MSG_PRINTER_NOTIFY);
233         }
234
235         smb_connections--;
236
237         return True;
238 }
239
240 /****************************************************************************
241   close printer index by handle
242 ****************************************************************************/
243 static BOOL close_printer_handle(POLICY_HND *hnd)
244 {
245         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
246
247         if (!OPEN_HANDLE(Printer)) {
248                 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
249                 return False;
250         }
251
252         if (Printer->notify.client_connected==True)
253                 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
254                         return ERROR_INVALID_HANDLE;
255
256         Printer->open=False;
257         Printer->notify.flags=0;
258         Printer->notify.options=0;
259         Printer->notify.localmachine[0]='\0';
260         Printer->notify.printerlocal=0;
261         safe_free(Printer->notify.option);
262         Printer->notify.option=NULL;
263         Printer->notify.client_connected=False;
264
265         clear_handle(hnd);
266
267         ubi_dlRemThis(&Printer_list, Printer);
268
269         safe_free(Printer);
270
271         return True;
272 }       
273
274 /****************************************************************************
275   delete a printer given a handle
276 ****************************************************************************/
277 static uint32 delete_printer_handle(POLICY_HND *hnd)
278 {
279         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
280
281         if (!OPEN_HANDLE(Printer)) {
282                 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
283                 return ERROR_INVALID_HANDLE;
284         }
285
286         if (del_a_printer(Printer->dev.handlename) != 0) {
287                 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
288                 return ERROR_INVALID_HANDLE;
289         }
290
291         /* Check calling user has permission to delete printer.  Note that
292            since we set the snum parameter to -1 only administrators can
293            delete the printer.  This stops people with the Full Control
294            permission from deleting the printer. */
295
296         if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
297                 DEBUG(3, ("printer delete denied by security descriptor\n"));
298                 return ERROR_ACCESS_DENIED;
299         }
300
301         if (*lp_deleteprinter_cmd()) {
302
303                 pid_t local_pid = sys_getpid();
304                 char *cmd = lp_deleteprinter_cmd();
305                 char *path;
306                 pstring tmp_file;
307                 pstring command;
308                 int ret;
309                 int i;
310
311                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
312                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
313                 else
314                         path = tmpdir();
315                 
316                 /* Printer->dev.handlename equals portname equals sharename */
317                 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
318                                         Printer->dev.handlename);
319                 dos_to_unix(command, True);  /* Convert printername to unix-codepage */
320         slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
321
322                 unlink(tmp_file);
323                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
324                 ret = smbrun(command, tmp_file, False);
325                 if (ret != 0) {
326                         unlink(tmp_file);
327                         return ERROR_INVALID_HANDLE; /* What to return here? */
328                 }
329                 DEBUGADD(10,("returned [%d]\n", ret));
330                 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
331                 unlink(tmp_file);
332
333                 /* Send SIGHUP to process group... is there a better way? */
334                 kill(0, SIGHUP);
335
336                 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
337                         lp_killservice( i );
338                         return ERROR_SUCCESS;
339                 } else
340                         return ERROR_ACCESS_DENIED;
341         }
342
343         return ERROR_SUCCESS;
344 }       
345
346 /****************************************************************************
347   return the snum of a printer corresponding to an handle
348 ****************************************************************************/
349 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
350 {
351         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
352                 
353         if (!OPEN_HANDLE(Printer)) {
354                 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
355                 return False;
356         }
357         
358         switch (Printer->printer_type) {
359         case PRINTER_HANDLE_IS_PRINTER:         
360                 DEBUG(4,("short name:%s\n", Printer->dev.handlename));                  
361                 *number = print_queue_snum(Printer->dev.handlename);
362                 return (*number != -1);
363         case PRINTER_HANDLE_IS_PRINTSERVER:
364                 return False;
365         default:
366                 return False;
367         }
368 }
369
370 /****************************************************************************
371   set printer handle type.
372 ****************************************************************************/
373 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
374 {
375         Printer_entry *Printer = find_printer_index_by_hnd(hnd);
376
377         if (!OPEN_HANDLE(Printer)) {
378                 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
379                 return False;
380         }
381
382         DEBUG(4,("Setting printer access=%x\n", access_required));
383         Printer->access = access_required;
384         return True;            
385 }
386
387 /****************************************************************************
388  Set printer handle type.
389  Check if it's \\server or \\server\printer
390 ****************************************************************************/
391
392 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
393 {
394         DEBUG(3,("Setting printer type=%s\n", handlename));
395
396         if ( strlen(handlename) < 3 ) {
397                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
398                 return False;
399         }
400
401         /* it's a print server */
402         if (!strchr(handlename+2, '\\')) {
403                 DEBUGADD(4,("Printer is a print server\n"));
404                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;          
405         }
406         /* it's a printer */
407         else {
408                 DEBUGADD(4,("Printer is a printer\n"));
409                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
410         }
411
412         return True;
413 }
414
415 /****************************************************************************
416  Set printer handle name.
417 ****************************************************************************/
418
419 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
420 {
421         NT_PRINTER_INFO_LEVEL *printer = NULL;
422         int snum;
423         int n_services=lp_numservices();
424         char *aprinter;
425         BOOL found=False;
426         
427         DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
428
429         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
430                 ZERO_STRUCT(Printer->dev.printerservername);
431                 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
432                 return True;
433         }
434
435         if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
436                 return False;
437         
438         aprinter=strchr(handlename+2, '\\');
439         aprinter++;
440
441         DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
442
443         /*
444          * store the Samba share name in it
445          * in back we have the long printer name
446          * need to iterate all the snum and do a
447          * get_a_printer each time to find the printer
448          * faster to do it here than later.
449          */
450
451         for (snum=0;snum<n_services && found==False;snum++) {
452                 char *printername;
453         
454                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
455                         continue;
456                 
457                 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
458
459                 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
460                         continue;
461
462                 printername=strchr(printer->info_2->printername+2, '\\');
463                 printername++;
464
465                 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
466                                 printer->info_2->printername, aprinter ));
467
468                 if ( strlen(printername) != strlen(aprinter) ) {
469                         free_a_printer(&printer, 2);
470                         continue;
471                 }
472                 
473                 if ( strncasecmp(printername, aprinter, strlen(aprinter)))  {
474                         free_a_printer(&printer, 2);
475                         continue;
476                 }
477                 
478                 found=True;
479         }
480
481         /*
482          * if we haven't found a printer with the given handlename
483          * then it can be a share name as you can open both \\server\printer and
484          * \\server\share
485          */
486
487         /*
488          * we still check if the printer description file exists as NT won't be happy
489          * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
490          */
491
492         if (found==False) {
493                 DEBUGADD(5,("Printer not found, checking for share now\n"));
494         
495                 for (snum=0;snum<n_services && found==False;snum++) {
496         
497                         if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
498                                 continue;
499                 
500                         DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
501
502                         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
503                                 continue;
504
505                         DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
506                                         printer->info_2->printername, aprinter ));
507
508                         if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
509                                 free_a_printer(&printer, 2);
510                                 continue;
511                         }
512                 
513                         if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter)))  {
514                                 free_a_printer(&printer, 2);
515                                 continue;
516                         }
517                 
518                         found=True;
519                 }
520         }
521                 
522         if (found==False) {
523                 DEBUGADD(4,("Printer not found\n"));
524                 return False;
525         }
526         
527         snum--;
528         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
529                         printer->info_2->printername, lp_servicename(snum),snum));
530
531         ZERO_STRUCT(Printer->dev.handlename);
532         strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
533         
534         free_a_printer(&printer, 2);
535
536         return True;
537 }
538
539 /****************************************************************************
540   find first available printer slot. creates a printer handle for you.
541  ****************************************************************************/
542
543 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
544 {
545         Printer_entry *new_printer;
546
547         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
548         clear_handle(hnd);
549         create_printer_hnd(hnd);
550
551         if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
552                 return False;
553
554         ZERO_STRUCTP(new_printer);
555         
556         new_printer->open = True;
557         new_printer->notify.option=NULL;
558                                 
559         memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
560         
561         ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
562
563         if (!set_printer_hnd_printertype(new_printer, name)) {
564                 close_printer_handle(hnd);
565                 return False;
566         }
567         
568         if (!set_printer_hnd_name(new_printer, name)) {
569                 close_printer_handle(hnd);
570                 return False;
571         }
572
573         DEBUG(5, ("%d printer handles active\n", 
574                   (int)ubi_dlCount(&Printer_list)));
575
576         return True;
577 }
578
579 /********************************************************************
580  Return True is the handle is a print server.
581  ********************************************************************/
582 static BOOL handle_is_printserver(const POLICY_HND *handle)
583 {
584         Printer_entry *Printer=find_printer_index_by_hnd(handle);
585
586         if (!OPEN_HANDLE(Printer))
587                 return False;
588                 
589         if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
590                 return False;
591         
592         return True;
593 }
594
595 /****************************************************************************
596  allocate more memory for a BUFFER.
597 ****************************************************************************/
598 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
599 {
600         prs_struct *ps;
601         uint32 extra_space;
602         uint32 old_offset;
603         
604         ps= &buffer->prs;
605
606         /* damn, I'm doing the reverse operation of prs_grow() :) */
607         if (buffer_size < prs_data_size(ps))
608                 extra_space=0;
609         else    
610                 extra_space = buffer_size - prs_data_size(ps);
611
612         /*
613          * save the offset and move to the end of the buffer
614          * prs_grow() checks the extra_space against the offset
615          */
616         old_offset=prs_offset(ps);      
617         prs_set_offset(ps, prs_data_size(ps));
618         
619         if (!prs_grow(ps, extra_space))
620                 return False;
621
622         prs_set_offset(ps, old_offset);
623
624         buffer->string_at_end=prs_data_size(ps);
625
626         return True;
627 }
628
629 /***************************************************************************
630  receive the notify message
631 ****************************************************************************/
632 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
633 {
634         fstring printer;
635         uint32 status;
636         Printer_entry *find_printer;
637
638         *printer = '\0';
639         fstrcpy(printer,buf);
640
641         if (len == 0) {
642                 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
643                 return;
644         }
645
646         DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
647
648         find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
649
650         /* Iterate the printer list. */
651         for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
652
653                 /*
654                  * if the entry is the given printer or if it's a printerserver
655                  * we send the message
656                  */
657
658                 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
659                         if (strcmp(find_printer->dev.handlename, printer))
660                                 continue;
661
662                 if (find_printer->notify.client_connected==True)
663                         cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
664
665         }
666 }
667
668 /***************************************************************************
669  send a notify event
670 ****************************************************************************/
671 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
672 {
673         fstring printer;
674
675         Printer_entry *Printer=find_printer_index_by_hnd(handle);
676
677         if (!OPEN_HANDLE(Printer)) {
678                 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
679                 return False;
680         }
681
682         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
683                 fstrcpy(printer, Printer->dev.handlename);
684         else
685                 fstrcpy(printer, "");
686
687         /*srv_spoolss_receive_message(printer);*/
688         DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
689
690         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
691
692         return True;
693 }       
694
695 /********************************************************************
696  * spoolss_open_printer
697  *
698  * called from the spoolss dispatcher
699  ********************************************************************/
700
701 uint32 _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
702 {
703 #if 0
704         uint32 result = NT_STATUS_NO_PROBLEMO;
705 #endif
706
707         UNISTR2 *printername = NULL;
708         PRINTER_DEFAULT *printer_default = &q_u->printer_default;
709 /*      uint32 user_switch = q_u->user_switch; - notused */
710 /*      SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
711         POLICY_HND *handle = &r_u->handle;
712
713         fstring name;
714         int snum;
715         struct current_user user;
716
717         if (q_u->printername_ptr != 0)
718                 printername = &q_u->printername;
719
720         if (printername == NULL)
721                 return ERROR_INVALID_PRINTER_NAME;
722
723         /* some sanity check because you can open a printer or a print server */
724         /* aka: \\server\printer or \\server */
725         unistr2_to_ascii(name, printername, sizeof(name)-1);
726
727         DEBUGADD(3,("checking name: %s\n",name));
728
729         if (!open_printer_hnd(handle, name))
730                 return ERROR_INVALID_PRINTER_NAME;
731         
732 /*
733         if (printer_default->datatype_ptr != NULL)
734         {
735                 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
736                 set_printer_hnd_datatype(handle, datatype);
737         }
738         else
739                 set_printer_hnd_datatype(handle, "");
740 */
741         
742         if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
743                 close_printer_handle(handle);
744                 return ERROR_ACCESS_DENIED;
745         }
746                 
747         /*
748            First case: the user is opening the print server:
749
750            Disallow MS AddPrinterWizard if parameter disables it. A Win2k
751            client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
752
753            Then both Win2k and WinNT clients try an OpenPrinterEx with
754            SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
755            or if the user is listed in the smb.conf printer admin parameter.
756
757            Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
758            client view printer folder, but does not show the MSAPW.
759
760            Note: this test needs code to check access rights here too. Jeremy
761            could you look at this?
762            
763            
764            Second case: the user is opening a printer:
765            NT doesn't let us connect to a printer if the connecting user
766            doesn't have print permission.
767
768         */
769
770         get_current_user(&user, p);
771
772         if (handle_is_printserver(handle)) {
773                 if (printer_default->access_required == 0) {
774                         return NT_STATUS_NO_PROBLEMO;
775                 }
776                 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
777
778                         if (!lp_ms_add_printer_wizard()) {
779                                 close_printer_handle(handle);
780                                 return ERROR_ACCESS_DENIED;
781                         }
782                         else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
783                                 return NT_STATUS_NO_PROBLEMO;
784                         } 
785                         else {
786                                 close_printer_handle(handle);
787                                 return ERROR_ACCESS_DENIED;
788                         }
789                 }
790         }
791         else
792         {
793                 /* NT doesn't let us connect to a printer if the connecting user
794                    doesn't have print permission.  */
795
796                 if (!get_printer_snum(handle, &snum))
797                         return ERROR_INVALID_HANDLE;
798
799                 /* map an empty access mask to the minimum access mask */
800                 if (printer_default->access_required == 0x0)
801                         printer_default->access_required = PRINTER_ACCESS_USE;
802
803                 if (!print_access_check(&user, snum, printer_default->access_required)) {
804                         DEBUG(3, ("access DENIED for printer open\n"));
805                         close_printer_handle(handle);
806                         return ERROR_ACCESS_DENIED;
807                 }
808
809                 /*
810                  * If we have a default device pointer in the
811                  * printer_default struct, then we need to get
812                  * the printer info from the tdb and if there is
813                  * no default devicemode there then we do a *SET*
814                  * here ! This is insanity.... JRA.
815                  */
816
817                 /*
818                  * If the openprinterex rpc call contains a devmode,
819                  * it's a per-user one. This per-user devmode is derivated
820                  * from the global devmode. Openprinterex() contains a per-user 
821                  * devmode for when you do EMF printing and spooling.
822                  * In the EMF case, the NT workstation is only doing half the job
823                  * of rendering the page. The other half is done by running the printer
824                  * driver on the server.
825                  * The EMF file doesn't contain the page description (paper size, orientation, ...).
826                  * The EMF file only contains what is to be printed on the page.
827                  * So in order for the server to know how to print, the NT client sends
828                  * a devicemode attached to the openprinterex call.
829                  * But this devicemode is short lived, it's only valid for the current print job.
830                  *
831                  * If Samba would have supported EMF spooling, this devicemode would
832                  * have been attached to the handle, to sent it to the driver to correctly
833                  * rasterize the EMF file.
834                  *
835                  * As Samba only supports RAW spooling, we only receive a ready-to-print file,
836                  * we just act as a pass-thru between windows and the printer.
837                  *
838                  * In order to know that Samba supports only RAW spooling, NT has to call
839                  * getprinter() at level 2 (attribute field) or NT has to call startdoc()
840                  * and until NT sends a RAW job, we refuse it.
841                  *
842                  * But to call getprinter() or startdoc(), you first need a valid handle,
843                  * and to get an handle you have to call openprintex(). Hence why you have
844                  * a devicemode in the openprinterex() call.
845                  *
846                  *
847                  * Differences between NT4 and NT 2000.
848                  * NT4:
849                  * ---
850                  * On NT4, you only have a global devicemode. This global devicemode can be changed
851                  * by the administrator (or by a user with enough privs). Everytime a user
852                  * wants to print, the devicemode is resetted to the default. In Word, everytime
853                  * you print, the printer's characteristics are always reset to the global devicemode.
854                  *
855                  * NT 2000:
856                  * -------
857                  * In W2K, there is the notion of per-user devicemode. The first time you use
858                  * a printer, a per-user devicemode is build from the global devicemode.
859                  * If you change your per-user devicemode, it is saved in the registry, under the
860                  * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
861                  * printer preferences available.
862                  *
863                  * To change the per-user devicemode: it's the "Printing Preferences ..." button
864                  * on the General Tab of the printer properties windows.
865                  *
866                  * To change the global devicemode: it's the "Printing Defaults..." button
867                  * on the Advanced Tab of the printer properties window.
868                  *
869                  * JFM.
870                  */
871
872
873
874 #if 0
875                 if (printer_default->devmode_cont.devmode != NULL) {
876                         result = printer_write_default_dev( snum, printer_default);
877                         if (result != 0) {
878                                 close_printer_handle(handle);
879                                 return result;
880                         }
881                 }
882 #endif
883         }
884
885         return NT_STATUS_NO_PROBLEMO;
886 }
887
888 /****************************************************************************
889 ****************************************************************************/
890 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
891                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
892 {
893         switch (level) {
894                 case 2:
895                         uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
896                         break;
897                 default:
898                         break;
899         }
900
901         return True;
902 }
903
904 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
905                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
906 {
907         switch (level) {
908                 case 3:
909                         printer->info_3=NULL;
910                         uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
911                         break;
912                 case 6:
913                         printer->info_6=NULL;
914                         uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
915                         break;
916                 default:
917                         break;
918         }
919
920         return True;
921 }
922
923 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
924                                 NT_DEVICEMODE **pp_nt_devmode)
925 {
926         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
927
928         /*
929          * Ensure nt_devmode is a valid pointer
930          * as we will be overwriting it.
931          */
932                 
933         if (nt_devmode == NULL) {
934                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
935                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
936                         return False;
937         }
938
939         unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
940         unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
941
942         nt_devmode->specversion=devmode->specversion;
943         nt_devmode->driverversion=devmode->driverversion;
944         nt_devmode->size=devmode->size;
945         nt_devmode->fields=devmode->fields;
946         nt_devmode->orientation=devmode->orientation;
947         nt_devmode->papersize=devmode->papersize;
948         nt_devmode->paperlength=devmode->paperlength;
949         nt_devmode->paperwidth=devmode->paperwidth;
950         nt_devmode->scale=devmode->scale;
951         nt_devmode->copies=devmode->copies;
952         nt_devmode->defaultsource=devmode->defaultsource;
953         nt_devmode->printquality=devmode->printquality;
954         nt_devmode->color=devmode->color;
955         nt_devmode->duplex=devmode->duplex;
956         nt_devmode->yresolution=devmode->yresolution;
957         nt_devmode->ttoption=devmode->ttoption;
958         nt_devmode->collate=devmode->collate;
959
960         nt_devmode->logpixels=devmode->logpixels;
961         nt_devmode->bitsperpel=devmode->bitsperpel;
962         nt_devmode->pelswidth=devmode->pelswidth;
963         nt_devmode->pelsheight=devmode->pelsheight;
964         nt_devmode->displayflags=devmode->displayflags;
965         nt_devmode->displayfrequency=devmode->displayfrequency;
966         nt_devmode->icmmethod=devmode->icmmethod;
967         nt_devmode->icmintent=devmode->icmintent;
968         nt_devmode->mediatype=devmode->mediatype;
969         nt_devmode->dithertype=devmode->dithertype;
970         nt_devmode->reserved1=devmode->reserved1;
971         nt_devmode->reserved2=devmode->reserved2;
972         nt_devmode->panningwidth=devmode->panningwidth;
973         nt_devmode->panningheight=devmode->panningheight;
974
975         /*
976          * Only change private and driverextra if the incoming devmode
977          * has a new one. JRA.
978          */
979
980         if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
981                 safe_free(nt_devmode->private);
982                 nt_devmode->driverextra=devmode->driverextra;
983                 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
984                         return False;
985                 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
986         }
987
988         *pp_nt_devmode = nt_devmode;
989
990         return True;
991 }
992
993 /********************************************************************
994  * api_spoolss_closeprinter
995  ********************************************************************/
996
997 uint32 _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
998 {
999         POLICY_HND *handle = &q_u->handle;
1000
1001         Printer_entry *Printer=find_printer_index_by_hnd(handle);
1002
1003         if (Printer && Printer->document_started)
1004                 _spoolss_enddocprinter(handle);          /* print job was not closed */
1005
1006         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1007
1008         if (!close_printer_handle(handle))
1009                 return ERROR_INVALID_HANDLE;    
1010                 
1011         return NT_STATUS_NO_PROBLEMO;
1012 }
1013
1014 /********************************************************************
1015  * api_spoolss_deleteprinter
1016
1017  ********************************************************************/
1018
1019 uint32 _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1020 {
1021         POLICY_HND *handle = &q_u->handle;
1022
1023         Printer_entry *Printer=find_printer_index_by_hnd(handle);
1024         uint32 result;
1025
1026         if (Printer && Printer->document_started)
1027                 _spoolss_enddocprinter(handle);  /* print job was not closed */
1028
1029         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1030
1031         result = delete_printer_handle(handle);
1032
1033         if (result == ERROR_SUCCESS) {
1034                 srv_spoolss_sendnotify(handle);
1035         }
1036                 
1037         return result;
1038 }
1039
1040 /********************************************************************
1041  GetPrinterData on a printer server Handle.
1042 ********************************************************************/
1043 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1044 {               
1045         int i;
1046         
1047         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1048                 
1049         if (!strcmp(value, "BeepEnabled")) {
1050                 *type = 0x4;
1051                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1052                         return False;
1053                 SIVAL(*data, 0, 0x01);
1054                 *needed = 0x4;                  
1055                 return True;
1056         }
1057
1058         if (!strcmp(value, "EventLog")) {
1059                 *type = 0x4;
1060                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1061                         return False;
1062                 SIVAL(*data, 0, 0x1B);
1063                 *needed = 0x4;                  
1064                 return True;
1065         }
1066
1067         if (!strcmp(value, "NetPopup")) {
1068                 *type = 0x4;
1069                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1070                         return False;
1071                 SIVAL(*data, 0, 0x01);
1072                 *needed = 0x4;
1073                 return True;
1074         }
1075
1076         if (!strcmp(value, "MajorVersion")) {
1077                 *type = 0x4;
1078                 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1079                         return False;
1080                 SIVAL(*data, 0, 0x02);
1081                 *needed = 0x4;
1082                 return True;
1083         }
1084
1085    if (!strcmp(value, "DefaultSpoolDirectory")) {
1086                 pstring string="You are using a Samba server";
1087                 *type = 0x1;                    
1088                 *needed = 2*(strlen(string)+1);         
1089                 if((*data  = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1090                         return False;
1091                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1092                 
1093                 /* it's done by hand ready to go on the wire */
1094                 for (i=0; i<strlen(string); i++) {
1095                         (*data)[2*i]=string[i];
1096                         (*data)[2*i+1]='\0';
1097                 }                       
1098                 return True;
1099         }
1100
1101         if (!strcmp(value, "Architecture")) {                   
1102                 pstring string="Windows NT x86";
1103                 *type = 0x1;                    
1104                 *needed = 2*(strlen(string)+1); 
1105                 if((*data  = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1106                         return False;
1107                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1108                 for (i=0; i<strlen(string); i++) {
1109                         (*data)[2*i]=string[i];
1110                         (*data)[2*i+1]='\0';
1111                 }                       
1112                 return True;
1113         }
1114         
1115         return False;
1116 }
1117
1118 /********************************************************************
1119  GetPrinterData on a printer Handle.
1120 ********************************************************************/
1121 static BOOL getprinterdata_printer(POLICY_HND *handle,
1122                                 fstring value, uint32 *type,
1123                                 uint8 **data, uint32 *needed, uint32 in_size )
1124 {
1125         NT_PRINTER_INFO_LEVEL *printer = NULL;
1126         int snum=0;
1127         uint8 *idata=NULL;
1128         uint32 len;
1129         Printer_entry *Printer = find_printer_index_by_hnd(handle);
1130         
1131         DEBUG(5,("getprinterdata_printer\n"));
1132
1133         if (!OPEN_HANDLE(Printer)) {
1134                 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1135                 return False;
1136         }
1137
1138         if(!get_printer_snum(handle, &snum))
1139                 return False;
1140
1141         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1142                 return False;
1143
1144         if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1145                 free_a_printer(&printer, 2);
1146                 return False;
1147         }
1148
1149         free_a_printer(&printer, 2);
1150
1151         DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1152
1153         if (in_size) {
1154                 if((*data  = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
1155                         return False;
1156                 }
1157
1158                 memset(*data, 0, in_size *sizeof(uint8));
1159                 /* copy the min(in_size, len) */
1160                 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1161         } else {
1162                 *data = NULL;
1163         }
1164
1165         *needed = len;
1166         
1167         DEBUG(5,("getprinterdata_printer:copy done\n"));
1168                         
1169         safe_free(idata);
1170         
1171         return True;
1172 }       
1173
1174 /********************************************************************
1175  * spoolss_getprinterdata
1176  ********************************************************************/
1177
1178 uint32 _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1179 {
1180         POLICY_HND *handle = &q_u->handle;
1181         UNISTR2 *valuename = &q_u->valuename;
1182         uint32 in_size = q_u->size;
1183         uint32 *type = &r_u->type;
1184         uint32 *out_size = &r_u->size;
1185         uint8 **data = &r_u->data;
1186         uint32 *needed = &r_u->needed;
1187
1188         fstring value;
1189         BOOL found=False;
1190         Printer_entry *Printer = find_printer_index_by_hnd(handle);
1191         
1192         /*
1193          * Reminder: when it's a string, the length is in BYTES
1194          * even if UNICODE is negociated.
1195          *
1196          * JFM, 4/19/1999
1197          */
1198
1199         *out_size=in_size;
1200
1201         /* in case of problem, return some default values */
1202         *needed=0;
1203         *type=0;
1204         
1205         DEBUG(4,("_spoolss_getprinterdata\n"));
1206         
1207         if (!OPEN_HANDLE(Printer)) {
1208                 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1209                         return ERROR_NOT_ENOUGH_MEMORY;
1210                 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1211                 return ERROR_INVALID_HANDLE;
1212         }
1213         
1214         unistr2_to_ascii(value, valuename, sizeof(value)-1);
1215         
1216         if (handle_is_printserver(handle))
1217                 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1218         else
1219                 found= getprinterdata_printer(handle, value, type, data, needed, *out_size);
1220
1221         if (found==False) {
1222                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1223                 /* reply this param doesn't exist */
1224                 if (*out_size) {
1225                         if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1226                                 return ERROR_NOT_ENOUGH_MEMORY;
1227                 } else {
1228                         *data = NULL;
1229                 }
1230
1231                 return ERROR_INVALID_PARAMETER;
1232         }
1233         
1234         if (*needed > *out_size)
1235                 return ERROR_MORE_DATA;
1236         else {
1237                 return NT_STATUS_NO_PROBLEMO;
1238     }
1239 }
1240
1241 /***************************************************************************
1242  connect to the client
1243 ****************************************************************************/
1244 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1245 {
1246         uint32 status;
1247
1248         /*
1249          * If it's the first connection, contact the client
1250          * and connect to the IPC$ share anonumously
1251          */
1252         if (smb_connections==0) {
1253                 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1254                         return False;
1255                 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1256
1257         }
1258
1259         smb_connections++;
1260
1261         if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1262                 return False;
1263
1264         return True;
1265 }
1266
1267 /********************************************************************
1268  * _spoolss_rffpcnex
1269  * ReplyFindFirstPrinterChangeNotifyEx
1270  *
1271  * jfmxxxx: before replying OK: status=0
1272  * should do a rpc call to the workstation asking ReplyOpenPrinter
1273  * have to code it, later.
1274  *
1275  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1276  * called from api_spoolss_rffpcnex
1277  ********************************************************************/
1278
1279 uint32 _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1280 {
1281         POLICY_HND *handle = &q_u->handle;
1282         uint32 flags = q_u->flags;
1283         uint32 options = q_u->options;
1284         UNISTR2 *localmachine = &q_u->localmachine;
1285         uint32 printerlocal = q_u->printerlocal;
1286         SPOOL_NOTIFY_OPTION *option = q_u->option;
1287
1288         /* store the notify value in the printer struct */
1289
1290         Printer_entry *Printer=find_printer_index_by_hnd(handle);
1291
1292         if (!OPEN_HANDLE(Printer)) {
1293                 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1294                 return ERROR_INVALID_HANDLE;
1295         }
1296
1297         Printer->notify.flags=flags;
1298         Printer->notify.options=options;
1299         Printer->notify.printerlocal=printerlocal;
1300         Printer->notify.option=option;
1301         unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1302
1303         /* connect to the client machine and send a ReplyOpenPrinter */
1304         if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1305                                         Printer->notify.printerlocal, 1,
1306                                         &Printer->notify.client_hnd))
1307                 Printer->notify.client_connected=True;
1308
1309         return NT_STATUS_NO_PROBLEMO;
1310 }
1311
1312 /*******************************************************************
1313  * fill a notify_info_data with the servername
1314  ********************************************************************/
1315
1316 static void spoolss_notify_server_name(int snum, 
1317                                        SPOOL_NOTIFY_INFO_DATA *data, 
1318                                        print_queue_struct *queue,
1319                                        NT_PRINTER_INFO_LEVEL *printer,
1320                                        TALLOC_CTX *mem_ctx) 
1321 {
1322         pstring temp_name, temp;
1323         uint32 len;
1324
1325         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1326
1327         len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1328
1329         data->notify_data.data.length = len / 2 - 1;
1330         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1331
1332         if (!data->notify_data.data.string) {
1333                 data->notify_data.data.length = 0;
1334                 return;
1335         }
1336         
1337         memcpy(data->notify_data.data.string, temp, len);
1338 }
1339
1340 /*******************************************************************
1341  * fill a notify_info_data with the printername (not including the servername).
1342  ********************************************************************/
1343 static void spoolss_notify_printer_name(int snum, 
1344                                         SPOOL_NOTIFY_INFO_DATA *data, 
1345                                         print_queue_struct *queue,
1346                                         NT_PRINTER_INFO_LEVEL *printer,
1347                                         TALLOC_CTX *mem_ctx)
1348 {
1349         pstring temp;
1350         uint32 len;
1351                 
1352         /* the notify name should not contain the \\server\ part */
1353         char *p = strrchr(printer->info_2->printername, '\\');
1354
1355         if (!p) {
1356                 p = printer->info_2->printername;
1357         } else {
1358                 p++;
1359         }
1360
1361         len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1362
1363         data->notify_data.data.length = len / 2 - 1;
1364         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1365         
1366         if (!data->notify_data.data.string) {
1367                 data->notify_data.data.length = 0;
1368                 return;
1369         }
1370         
1371         memcpy(data->notify_data.data.string, temp, len);
1372 }
1373
1374 /*******************************************************************
1375  * fill a notify_info_data with the servicename
1376  ********************************************************************/
1377 static void spoolss_notify_share_name(int snum, 
1378                                       SPOOL_NOTIFY_INFO_DATA *data, 
1379                                       print_queue_struct *queue,
1380                                       NT_PRINTER_INFO_LEVEL *printer,
1381                                       TALLOC_CTX *mem_ctx)
1382 {
1383         pstring temp;
1384         uint32 len;
1385
1386         len = (uint32)dos_PutUniCode(temp, lp_servicename(snum), 
1387                                      sizeof(temp) - 2, True);
1388
1389         data->notify_data.data.length = len / 2 - 1;
1390         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1391         
1392         if (!data->notify_data.data.string) {
1393                 data->notify_data.data.length = 0;
1394                 return;
1395         }
1396         
1397         memcpy(data->notify_data.data.string, temp, len);
1398 }
1399
1400 /*******************************************************************
1401  * fill a notify_info_data with the port name
1402  ********************************************************************/
1403 static void spoolss_notify_port_name(int snum, 
1404                                      SPOOL_NOTIFY_INFO_DATA *data, 
1405                                      print_queue_struct *queue,
1406                                      NT_PRINTER_INFO_LEVEL *printer,
1407                                      TALLOC_CTX *mem_ctx)
1408 {
1409         pstring temp;
1410         uint32 len;
1411
1412         /* even if it's strange, that's consistant in all the code */
1413
1414         len = (uint32)dos_PutUniCode(temp, printer->info_2->portname, 
1415                                      sizeof(temp) - 2, True);
1416
1417         data->notify_data.data.length = len / 2 - 1;
1418         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1419         
1420         if (!data->notify_data.data.string) {
1421                 data->notify_data.data.length = 0;
1422                 return;
1423         }
1424         
1425         memcpy(data->notify_data.data.string, temp, len);
1426 }
1427
1428 /*******************************************************************
1429  * fill a notify_info_data with the printername
1430  * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1431  * but it doesn't exist, have to see what to do
1432  ********************************************************************/
1433 static void spoolss_notify_driver_name(int snum, 
1434                                        SPOOL_NOTIFY_INFO_DATA *data,
1435                                        print_queue_struct *queue,
1436                                        NT_PRINTER_INFO_LEVEL *printer,
1437                                        TALLOC_CTX *mem_ctx)
1438 {
1439         pstring temp;
1440         uint32 len;
1441
1442         len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername, 
1443                                      sizeof(temp) - 2, True);
1444
1445         data->notify_data.data.length = len / 2 - 1;
1446         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1447         
1448         if (!data->notify_data.data.string) {
1449                 data->notify_data.data.length = 0;
1450                 return;
1451         }
1452         
1453         memcpy(data->notify_data.data.string, temp, len);
1454 }
1455
1456 /*******************************************************************
1457  * fill a notify_info_data with the comment
1458  ********************************************************************/
1459 static void spoolss_notify_comment(int snum, 
1460                                    SPOOL_NOTIFY_INFO_DATA *data,
1461                                    print_queue_struct *queue,
1462                                    NT_PRINTER_INFO_LEVEL *printer,
1463                                    TALLOC_CTX *mem_ctx)
1464 {
1465         pstring temp;
1466         uint32 len;
1467
1468         if (*printer->info_2->comment == '\0')
1469                 len = (uint32)dos_PutUniCode(temp, lp_comment(snum), 
1470                                              sizeof(temp) - 2, True);
1471         else
1472                 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment, 
1473                                              sizeof(temp) - 2, True);
1474
1475         data->notify_data.data.length = len / 2 - 1;
1476         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1477         
1478         if (!data->notify_data.data.string) {
1479                 data->notify_data.data.length = 0;
1480                 return;
1481         }
1482         
1483         memcpy(data->notify_data.data.string, temp, len);
1484 }
1485
1486 /*******************************************************************
1487  * fill a notify_info_data with the comment
1488  * jfm:xxxx incorrect, have to create a new smb.conf option
1489  * location = "Room 1, floor 2, building 3"
1490  ********************************************************************/
1491 static void spoolss_notify_location(int snum, 
1492                                     SPOOL_NOTIFY_INFO_DATA *data,
1493                                     print_queue_struct *queue,
1494                                     NT_PRINTER_INFO_LEVEL *printer,
1495                                     TALLOC_CTX *mem_ctx)
1496 {
1497         pstring temp;
1498         uint32 len;
1499
1500         len = (uint32)dos_PutUniCode(temp, printer->info_2->location, 
1501                                      sizeof(temp) - 2, True);
1502
1503         data->notify_data.data.length = len / 2 - 1;
1504         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1505         
1506         if (!data->notify_data.data.string) {
1507                 data->notify_data.data.length = 0;
1508                 return;
1509         }
1510         
1511         memcpy(data->notify_data.data.string, temp, len);
1512 }
1513
1514 /*******************************************************************
1515  * fill a notify_info_data with the device mode
1516  * jfm:xxxx don't to it for know but that's a real problem !!!
1517  ********************************************************************/
1518 static void spoolss_notify_devmode(int snum, 
1519                                    SPOOL_NOTIFY_INFO_DATA *data,
1520                                    print_queue_struct *queue,
1521                                    NT_PRINTER_INFO_LEVEL *printer,
1522                                    TALLOC_CTX *mem_ctx)
1523 {
1524 }
1525
1526 /*******************************************************************
1527  * fill a notify_info_data with the separator file name
1528  * jfm:xxxx just return no file could add an option to smb.conf
1529  * separator file = "separator.txt"
1530  ********************************************************************/
1531 static void spoolss_notify_sepfile(int snum, 
1532                                    SPOOL_NOTIFY_INFO_DATA *data, 
1533                                    print_queue_struct *queue,
1534                                    NT_PRINTER_INFO_LEVEL *printer,
1535                                    TALLOC_CTX *mem_ctx)
1536 {
1537         pstring temp;
1538         uint32 len;
1539
1540         len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile, 
1541                                      sizeof(temp) - 2, True);
1542
1543         data->notify_data.data.length = len / 2 - 1;
1544         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1545         
1546         if (!data->notify_data.data.string) {
1547                 data->notify_data.data.length = 0;
1548                 return;
1549         }
1550         
1551         memcpy(data->notify_data.data.string, temp, len);
1552 }
1553
1554 /*******************************************************************
1555  * fill a notify_info_data with the print processor
1556  * jfm:xxxx return always winprint to indicate we don't do anything to it
1557  ********************************************************************/
1558 static void spoolss_notify_print_processor(int snum, 
1559                                            SPOOL_NOTIFY_INFO_DATA *data,
1560                                            print_queue_struct *queue,
1561                                            NT_PRINTER_INFO_LEVEL *printer,
1562                                            TALLOC_CTX *mem_ctx)
1563 {
1564         pstring temp;
1565         uint32 len;
1566
1567         len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor, 
1568                                      sizeof(temp) - 2, True);
1569
1570         data->notify_data.data.length = len / 2 - 1;
1571         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1572         
1573         if (!data->notify_data.data.string) {
1574                 data->notify_data.data.length = 0;
1575                 return;
1576         }
1577         
1578         memcpy(data->notify_data.data.string, temp, len);
1579 }
1580
1581 /*******************************************************************
1582  * fill a notify_info_data with the print processor options
1583  * jfm:xxxx send an empty string
1584  ********************************************************************/
1585 static void spoolss_notify_parameters(int snum, 
1586                                       SPOOL_NOTIFY_INFO_DATA *data,
1587                                       print_queue_struct *queue,
1588                                       NT_PRINTER_INFO_LEVEL *printer,
1589                                       TALLOC_CTX *mem_ctx)
1590 {
1591         pstring temp;
1592         uint32 len;
1593
1594         len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters, 
1595                                      sizeof(temp) - 2, True);
1596
1597         data->notify_data.data.length = len / 2 - 1;
1598         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1599         
1600         if (!data->notify_data.data.string) {
1601                 data->notify_data.data.length = 0;
1602                 return;
1603         }
1604         
1605         memcpy(data->notify_data.data.string, temp, len);
1606 }
1607
1608 /*******************************************************************
1609  * fill a notify_info_data with the data type
1610  * jfm:xxxx always send RAW as data type
1611  ********************************************************************/
1612 static void spoolss_notify_datatype(int snum, 
1613                                     SPOOL_NOTIFY_INFO_DATA *data,
1614                                     print_queue_struct *queue,
1615                                     NT_PRINTER_INFO_LEVEL *printer,
1616                                     TALLOC_CTX *mem_ctx)
1617 {
1618         pstring temp;
1619         uint32 len;
1620
1621         len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype, 
1622                                      sizeof(pstring) - 2, True);
1623
1624         data->notify_data.data.length = len / 2 - 1;
1625         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1626         
1627         if (!data->notify_data.data.string) {
1628                 data->notify_data.data.length = 0;
1629                 return;
1630         }
1631         
1632         memcpy(data->notify_data.data.string, temp, len);
1633 }
1634
1635 /*******************************************************************
1636  * fill a notify_info_data with the security descriptor
1637  * jfm:xxxx send an null pointer to say no security desc
1638  * have to implement security before !
1639  ********************************************************************/
1640 static void spoolss_notify_security_desc(int snum, 
1641                                          SPOOL_NOTIFY_INFO_DATA *data,
1642                                          print_queue_struct *queue,
1643                                          NT_PRINTER_INFO_LEVEL *printer,
1644                                          TALLOC_CTX *mem_ctx)
1645 {
1646         data->notify_data.data.length=0;
1647         data->notify_data.data.string = NULL;
1648 }
1649
1650 /*******************************************************************
1651  * fill a notify_info_data with the attributes
1652  * jfm:xxxx a samba printer is always shared
1653  ********************************************************************/
1654 static void spoolss_notify_attributes(int snum, 
1655                                       SPOOL_NOTIFY_INFO_DATA *data,
1656                                       print_queue_struct *queue,
1657                                       NT_PRINTER_INFO_LEVEL *printer,
1658                                       TALLOC_CTX *mem_ctx)
1659 {
1660         data->notify_data.value[0] = printer->info_2->attributes;
1661 }
1662
1663 /*******************************************************************
1664  * fill a notify_info_data with the priority
1665  ********************************************************************/
1666 static void spoolss_notify_priority(int snum, 
1667                                     SPOOL_NOTIFY_INFO_DATA *data,
1668                                     print_queue_struct *queue,
1669                                     NT_PRINTER_INFO_LEVEL *printer,
1670                                     TALLOC_CTX *mem_ctx)
1671 {
1672         data->notify_data.value[0] = printer->info_2->priority;
1673 }
1674
1675 /*******************************************************************
1676  * fill a notify_info_data with the default priority
1677  ********************************************************************/
1678 static void spoolss_notify_default_priority(int snum, 
1679                                             SPOOL_NOTIFY_INFO_DATA *data,
1680                                             print_queue_struct *queue,
1681                                             NT_PRINTER_INFO_LEVEL *printer,
1682                                             TALLOC_CTX *mem_ctx)
1683 {
1684         data->notify_data.value[0] = printer->info_2->default_priority;
1685 }
1686
1687 /*******************************************************************
1688  * fill a notify_info_data with the start time
1689  ********************************************************************/
1690 static void spoolss_notify_start_time(int snum, 
1691                                       SPOOL_NOTIFY_INFO_DATA *data,
1692                                       print_queue_struct *queue,
1693                                       NT_PRINTER_INFO_LEVEL *printer,
1694                                       TALLOC_CTX *mem_ctx)
1695 {
1696         data->notify_data.value[0] = printer->info_2->starttime;
1697 }
1698
1699 /*******************************************************************
1700  * fill a notify_info_data with the until time
1701  ********************************************************************/
1702 static void spoolss_notify_until_time(int snum, 
1703                                       SPOOL_NOTIFY_INFO_DATA *data,
1704                                       print_queue_struct *queue,
1705                                       NT_PRINTER_INFO_LEVEL *printer,
1706                                       TALLOC_CTX *mem_ctx)
1707 {
1708         data->notify_data.value[0] = printer->info_2->untiltime;
1709 }
1710
1711 /*******************************************************************
1712  * fill a notify_info_data with the status
1713  ********************************************************************/
1714 static void spoolss_notify_status(int snum, 
1715                                   SPOOL_NOTIFY_INFO_DATA *data,
1716                                   print_queue_struct *queue,
1717                                   NT_PRINTER_INFO_LEVEL *printer,
1718                                   TALLOC_CTX *mem_ctx)
1719 {
1720         int count;
1721
1722         print_queue_struct *q=NULL;
1723         print_status_struct status;
1724
1725         memset(&status, 0, sizeof(status));
1726         count = print_queue_status(snum, &q, &status);
1727         data->notify_data.value[0]=(uint32) status.status;
1728         safe_free(q);
1729 }
1730
1731 /*******************************************************************
1732  * fill a notify_info_data with the number of jobs queued
1733  ********************************************************************/
1734 static void spoolss_notify_cjobs(int snum, 
1735                                  SPOOL_NOTIFY_INFO_DATA *data,
1736                                  print_queue_struct *queue,
1737                                  NT_PRINTER_INFO_LEVEL *printer, 
1738                                  TALLOC_CTX *mem_ctx)
1739 {
1740         print_queue_struct *q=NULL;
1741         print_status_struct status;
1742
1743         memset(&status, 0, sizeof(status));
1744         data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1745         safe_free(q);
1746 }
1747
1748 /*******************************************************************
1749  * fill a notify_info_data with the average ppm
1750  ********************************************************************/
1751 static void spoolss_notify_average_ppm(int snum, 
1752                                        SPOOL_NOTIFY_INFO_DATA *data,
1753                                        print_queue_struct *queue,
1754                                        NT_PRINTER_INFO_LEVEL *printer,
1755                                        TALLOC_CTX *mem_ctx)
1756 {
1757         /* always respond 8 pages per minutes */
1758         /* a little hard ! */
1759         data->notify_data.value[0] = printer->info_2->averageppm;
1760 }
1761
1762 /*******************************************************************
1763  * fill a notify_info_data with username
1764  ********************************************************************/
1765 static void spoolss_notify_username(int snum, 
1766                                     SPOOL_NOTIFY_INFO_DATA *data,
1767                                     print_queue_struct *queue,
1768                                     NT_PRINTER_INFO_LEVEL *printer,
1769                                     TALLOC_CTX *mem_ctx)
1770 {
1771         pstring temp;
1772         uint32 len;
1773
1774         len = (uint32)dos_PutUniCode(temp, queue->user, 
1775                                      sizeof(temp) - 2, True);
1776
1777         data->notify_data.data.length = len / 2 - 1;
1778         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1779         
1780         if (!data->notify_data.data.string) {
1781                 data->notify_data.data.length = 0;
1782                 return;
1783         }
1784         
1785         memcpy(data->notify_data.data.string, temp, len);
1786 }
1787
1788 /*******************************************************************
1789  * fill a notify_info_data with job status
1790  ********************************************************************/
1791 static void spoolss_notify_job_status(int snum, 
1792                                       SPOOL_NOTIFY_INFO_DATA *data,
1793                                       print_queue_struct *queue,
1794                                       NT_PRINTER_INFO_LEVEL *printer,
1795                                       TALLOC_CTX *mem_ctx)
1796 {
1797         data->notify_data.value[0]=nt_printj_status(queue->status);
1798 }
1799
1800 /*******************************************************************
1801  * fill a notify_info_data with job name
1802  ********************************************************************/
1803 static void spoolss_notify_job_name(int snum, 
1804                                     SPOOL_NOTIFY_INFO_DATA *data,
1805                                     print_queue_struct *queue,
1806                                     NT_PRINTER_INFO_LEVEL *printer,
1807                                     TALLOC_CTX *mem_ctx)
1808 {
1809         pstring temp;
1810         uint32 len;
1811
1812         len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2, 
1813                                      True);
1814
1815         data->notify_data.data.length = len / 2 - 1;
1816         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1817         
1818         if (!data->notify_data.data.string) {
1819                 data->notify_data.data.length = 0;
1820                 return;
1821         }
1822         
1823         memcpy(data->notify_data.data.string, temp, len);
1824 }
1825
1826 /*******************************************************************
1827  * fill a notify_info_data with job status
1828  ********************************************************************/
1829 static void spoolss_notify_job_status_string(int snum, 
1830                                              SPOOL_NOTIFY_INFO_DATA *data,
1831                                              print_queue_struct *queue,
1832                                              NT_PRINTER_INFO_LEVEL *printer, 
1833                                              TALLOC_CTX *mem_ctx)
1834 {
1835         /*
1836          * Now we're returning job status codes we just return a "" here. JRA.
1837          */
1838
1839         char *p = "";
1840         pstring temp;
1841         uint32 len;
1842
1843 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1844         p = "unknown";
1845
1846         switch (queue->status) {
1847         case LPQ_QUEUED:
1848                 p = "Queued";
1849                 break;
1850         case LPQ_PAUSED:
1851                 p = "";    /* NT provides the paused string */
1852                 break;
1853         case LPQ_SPOOLING:
1854                 p = "Spooling";
1855                 break;
1856         case LPQ_PRINTING:
1857                 p = "Printing";
1858                 break;
1859         }
1860 #endif /* NO LONGER NEEDED. */
1861
1862         len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1863
1864         data->notify_data.data.length = len / 2 - 1;
1865         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1866         
1867         if (!data->notify_data.data.string) {
1868                 data->notify_data.data.length = 0;
1869                 return;
1870         }
1871         
1872         memcpy(data->notify_data.data.string, temp, len);
1873 }
1874
1875 /*******************************************************************
1876  * fill a notify_info_data with job time
1877  ********************************************************************/
1878 static void spoolss_notify_job_time(int snum, 
1879                                     SPOOL_NOTIFY_INFO_DATA *data,
1880                                     print_queue_struct *queue,
1881                                     NT_PRINTER_INFO_LEVEL *printer,
1882                                     TALLOC_CTX *mem_ctx)
1883 {
1884         data->notify_data.value[0]=0x0;
1885 }
1886
1887 /*******************************************************************
1888  * fill a notify_info_data with job size
1889  ********************************************************************/
1890 static void spoolss_notify_job_size(int snum, 
1891                                     SPOOL_NOTIFY_INFO_DATA *data,
1892                                     print_queue_struct *queue,
1893                                     NT_PRINTER_INFO_LEVEL *printer,
1894                                     TALLOC_CTX *mem_ctx)
1895 {
1896         data->notify_data.value[0]=queue->size;
1897 }
1898
1899 /*******************************************************************
1900  * fill a notify_info_data with job position
1901  ********************************************************************/
1902 static void spoolss_notify_job_position(int snum, 
1903                                         SPOOL_NOTIFY_INFO_DATA *data,
1904                                         print_queue_struct *queue,
1905                                         NT_PRINTER_INFO_LEVEL *printer,
1906                                         TALLOC_CTX *mem_ctx)
1907 {
1908         data->notify_data.value[0]=queue->job;
1909 }
1910
1911 /*******************************************************************
1912  * fill a notify_info_data with submitted time
1913  ********************************************************************/
1914 static void spoolss_notify_submitted_time(int snum, 
1915                                           SPOOL_NOTIFY_INFO_DATA *data,
1916                                           print_queue_struct *queue,
1917                                           NT_PRINTER_INFO_LEVEL *printer,
1918                                           TALLOC_CTX *mem_ctx)
1919 {
1920         struct tm *t;
1921         uint32 len;
1922
1923         t=gmtime(&queue->time);
1924
1925         len = sizeof(SYSTEMTIME);
1926
1927         data->notify_data.data.length = len;
1928         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1929
1930         if (!data->notify_data.data.string) {
1931                 data->notify_data.data.length = 0;
1932                 return;
1933         }
1934         
1935         make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1936 }
1937
1938 #define END 65535
1939
1940 struct s_notify_info_data_table
1941 {
1942         uint16 type;
1943         uint16 field;
1944         char *name;
1945         uint32 size;
1946         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1947                     print_queue_struct *queue,
1948                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1949 };
1950
1951 struct s_notify_info_data_table notify_info_data_table[] =
1952 {
1953 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         POINTER,   spoolss_notify_server_name },
1954 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        POINTER,   spoolss_notify_printer_name },
1955 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          POINTER,   spoolss_notify_share_name },
1956 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           POINTER,   spoolss_notify_port_name },
1957 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         POINTER,   spoolss_notify_driver_name },
1958 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             POINTER,   spoolss_notify_comment },
1959 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            POINTER,   spoolss_notify_location },
1960 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             POINTER,   spoolss_notify_devmode },
1961 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             POINTER,   spoolss_notify_sepfile },
1962 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     POINTER,   spoolss_notify_print_processor },
1963 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          POINTER,   spoolss_notify_parameters },
1964 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            POINTER,   spoolss_notify_datatype },
1965 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER,   spoolss_notify_security_desc },
1966 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          ONE_VALUE, spoolss_notify_attributes },
1967 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            ONE_VALUE, spoolss_notify_priority },
1968 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    ONE_VALUE, spoolss_notify_default_priority },
1969 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          ONE_VALUE, spoolss_notify_start_time },
1970 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          ONE_VALUE, spoolss_notify_until_time },
1971 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              ONE_VALUE, spoolss_notify_status },
1972 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       POINTER,   NULL },
1973 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               ONE_VALUE, spoolss_notify_cjobs },
1974 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         ONE_VALUE, spoolss_notify_average_ppm },
1975 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         POINTER,   NULL },
1976 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       POINTER,   NULL },
1977 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         POINTER,   NULL },
1978 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       POINTER,   NULL },
1979 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            POINTER,   spoolss_notify_printer_name },
1980 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            POINTER,   spoolss_notify_server_name },
1981 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               POINTER,   spoolss_notify_port_name },
1982 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               POINTER,   spoolss_notify_username },
1983 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             POINTER,   spoolss_notify_username },
1984 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                POINTER,   spoolss_notify_datatype },
1985 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         POINTER,   spoolss_notify_print_processor },
1986 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              POINTER,   spoolss_notify_parameters },
1987 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             POINTER,   spoolss_notify_driver_name },
1988 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 POINTER,   spoolss_notify_devmode },
1989 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  ONE_VALUE, spoolss_notify_job_status },
1990 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           POINTER,   spoolss_notify_job_status_string },
1991 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     POINTER,   NULL },
1992 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                POINTER,   spoolss_notify_job_name },
1993 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                ONE_VALUE, spoolss_notify_priority },
1994 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                ONE_VALUE, spoolss_notify_job_position },
1995 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               POINTER,   spoolss_notify_submitted_time },
1996 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              ONE_VALUE, spoolss_notify_start_time },
1997 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              ONE_VALUE, spoolss_notify_until_time },
1998 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    ONE_VALUE, spoolss_notify_job_time },
1999 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             ONE_VALUE, NULL },
2000 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           ONE_VALUE, NULL },
2001 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             ONE_VALUE, spoolss_notify_job_size },
2002 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_BYTES_PRINTED,           "JOB_NOTIFY_BYTES_PRINTED",           ONE_VALUE, NULL },
2003 { END,                 END,                                "",                                   END,       NULL }
2004 };
2005
2006 /*******************************************************************
2007 return the size of info_data structure
2008 ********************************************************************/
2009 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2010 {
2011         int i=0;
2012
2013         while (notify_info_data_table[i].type != END)
2014         {
2015                 if ( (notify_info_data_table[i].type == type ) &&
2016                      (notify_info_data_table[i].field == field ) )
2017                 {
2018                         return (notify_info_data_table[i].size);
2019                 }
2020                 i++;
2021         }
2022         return (65535);
2023 }
2024
2025 /*******************************************************************
2026 return the type of notify_info_data
2027 ********************************************************************/
2028 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2029 {
2030         int i=0;
2031
2032         while (notify_info_data_table[i].type != END)
2033         {
2034                 if ( (notify_info_data_table[i].type == type ) &&
2035                      (notify_info_data_table[i].field == field ) )
2036                 {
2037                         if (notify_info_data_table[i].size == POINTER)
2038                         {
2039                                 return (False);
2040                         }
2041                         else
2042                         {
2043                                 return (True);
2044                         }
2045                 }
2046                 i++;
2047         }
2048         return (False);
2049 }
2050
2051 /****************************************************************************
2052 ****************************************************************************/
2053 static int search_notify(uint16 type, uint16 field, int *value)
2054 {       
2055         int j;
2056         BOOL found;
2057
2058         for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2059         {
2060                 if ( (notify_info_data_table[j].type  == type  ) &&
2061                      (notify_info_data_table[j].field == field ) )
2062                         found=True;
2063         }
2064         *value=--j;
2065
2066         if ( found && (notify_info_data_table[j].fn != NULL) )
2067                 return True;
2068         else
2069                 return False;   
2070 }
2071
2072 /****************************************************************************
2073 ****************************************************************************/
2074 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2075 {
2076         info_data->type     = type;
2077         info_data->field    = field;
2078         info_data->reserved = 0;
2079         info_data->id       = id;
2080         info_data->size     = size_of_notify_info_data(type, field);
2081         info_data->enc_type = type_of_notify_info_data(type, field);
2082 }
2083
2084
2085 /*******************************************************************
2086  *
2087  * fill a notify_info struct with info asked
2088  *
2089  ********************************************************************/
2090 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2091                                           snum, SPOOL_NOTIFY_OPTION_TYPE
2092                                           *option_type, uint32 id,
2093                                           TALLOC_CTX *mem_ctx) 
2094 {
2095         int field_num,j;
2096         uint16 type;
2097         uint16 field;
2098
2099         SPOOL_NOTIFY_INFO_DATA *current_data;
2100         NT_PRINTER_INFO_LEVEL *printer = NULL;
2101         print_queue_struct *queue=NULL;
2102         size_t realloc_size = 0;
2103         SPOOL_NOTIFY_INFO_DATA *info_data_ptr = NULL;
2104
2105         type=option_type->type;
2106
2107         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2108                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2109                 option_type->count, lp_servicename(snum)));
2110         
2111         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2112                 return False;
2113
2114         for(field_num=0; field_num<option_type->count; field_num++) {
2115                 field = option_type->fields[field_num];
2116                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2117
2118                 if (!search_notify(type, field, &j) )
2119                         continue;
2120                 
2121                 realloc_size = (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA);
2122                 if((info_data_ptr=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info_data_ptr, realloc_size)) == NULL) {
2123                         return False;
2124                 }
2125                 current_data=&info_data_ptr[info->count];
2126
2127                 construct_info_data(current_data, type, field, id);             
2128
2129                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
2130                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2131
2132                 notify_info_data_table[j].fn(snum, current_data, queue,
2133                                              printer, mem_ctx);
2134
2135                 info->count++;
2136         }
2137
2138         if (realloc_size)
2139                 info->data = talloc_memdup(mem_ctx, info_data_ptr, realloc_size);
2140         else
2141                 info->data = NULL;
2142
2143         safe_free(info_data_ptr);
2144         free_a_printer(&printer, 2);
2145         return True;
2146 }
2147
2148 /*******************************************************************
2149  *
2150  * fill a notify_info struct with info asked
2151  *
2152  ********************************************************************/
2153 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2154                                        SPOOL_NOTIFY_INFO *info,
2155                                        NT_PRINTER_INFO_LEVEL *printer,
2156                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
2157                                        *option_type, uint32 id,
2158                                        TALLOC_CTX *mem_ctx) 
2159 {
2160         int field_num,j;
2161         uint16 type;
2162         uint16 field;
2163
2164         SPOOL_NOTIFY_INFO_DATA *current_data;
2165         
2166         DEBUG(4,("construct_notify_jobs_info\n"));
2167         
2168         type = option_type->type;
2169
2170         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2171                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2172                 option_type->count));
2173
2174         for(field_num=0; field_num<option_type->count; field_num++) {
2175                 field = option_type->fields[field_num];
2176
2177                 if (!search_notify(type, field, &j) )
2178                         continue;
2179
2180                 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2181                         return False;
2182                 }
2183
2184                 current_data=&(info->data[info->count]);
2185
2186                 construct_info_data(current_data, type, field, id);
2187                 notify_info_data_table[j].fn(snum, current_data, queue,
2188                                              printer, mem_ctx);
2189                 info->count++;
2190         }
2191
2192         return True;
2193 }
2194
2195 /*
2196  * JFM: The enumeration is not that simple, it's even non obvious.
2197  *
2198  * let's take an example: I want to monitor the PRINTER SERVER for
2199  * the printer's name and the number of jobs currently queued.
2200  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2201  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2202  *
2203  * I have 3 printers on the back of my server.
2204  *
2205  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2206  * structures.
2207  *   Number     Data                    Id
2208  *      1       printer 1 name          1
2209  *      2       printer 1 cjob          1
2210  *      3       printer 2 name          2
2211  *      4       printer 2 cjob          2
2212  *      5       printer 3 name          3
2213  *      6       printer 3 name          3
2214  *
2215  * that's the print server case, the printer case is even worse.
2216  */
2217
2218
2219
2220 /*******************************************************************
2221  *
2222  * enumerate all printers on the printserver
2223  * fill a notify_info struct with info asked
2224  *
2225  ********************************************************************/
2226 static uint32 printserver_notify_info(const POLICY_HND *hnd, 
2227                                       SPOOL_NOTIFY_INFO *info,
2228                                       TALLOC_CTX *mem_ctx)
2229 {
2230         int snum;
2231         Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2232         int n_services=lp_numservices();
2233         int i;
2234         uint32 id;
2235         SPOOL_NOTIFY_OPTION *option;
2236         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2237
2238         DEBUG(4,("printserver_notify_info\n"));
2239         
2240         option=Printer->notify.option;
2241         id=1;
2242         info->version=2;
2243         info->data=NULL;
2244         info->count=0;
2245
2246         for (i=0; i<option->count; i++) {
2247                 option_type=&(option->ctr.type[i]);
2248                 
2249                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2250                         continue;
2251                 
2252                 for (snum=0; snum<n_services; snum++)
2253                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2254                                 if (construct_notify_printer_info
2255                                     (info, snum, option_type, id, mem_ctx))
2256                                         id++;
2257         }
2258                         
2259         /*
2260          * Debugging information, don't delete.
2261          */
2262         /*
2263         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2264         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2265         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2266         
2267         for (i=0; i<info->count; i++) {
2268                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2269                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2270                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2271         }
2272         */
2273         
2274         return NT_STATUS_NO_PROBLEMO;
2275 }
2276
2277 /*******************************************************************
2278  *
2279  * fill a notify_info struct with info asked
2280  *
2281  ********************************************************************/
2282 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2283                                   TALLOC_CTX *mem_ctx)
2284 {
2285         int snum;
2286         Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2287         int i;
2288         uint32 id;
2289         SPOOL_NOTIFY_OPTION *option;
2290         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2291         int count,j;
2292         print_queue_struct *queue=NULL;
2293         print_status_struct status;
2294         
2295         DEBUG(4,("printer_notify_info\n"));
2296
2297         option=Printer->notify.option;
2298         id=0xffffffff;
2299         info->version=2;
2300         info->data=NULL;
2301         info->count=0;
2302
2303         get_printer_snum(hnd, &snum);
2304
2305         for (i=0; i<option->count; i++) {
2306                 option_type=&option->ctr.type[i];
2307                 
2308                 switch ( option_type->type ) {
2309                 case PRINTER_NOTIFY_TYPE:
2310                         if(construct_notify_printer_info(info, snum, 
2311                                                          option_type, id,
2312                                                          mem_ctx))  
2313                                 id--;
2314                         break;
2315                         
2316                 case JOB_NOTIFY_TYPE: {
2317                         NT_PRINTER_INFO_LEVEL *printer = NULL;
2318
2319                         memset(&status, 0, sizeof(status));     
2320                         count = print_queue_status(snum, &queue, &status);
2321
2322                         if (get_a_printer(&printer, 2, 
2323                                           lp_servicename(snum)) != 0)
2324                                 goto done;
2325
2326                         for (j=0; j<count; j++) {
2327                                 construct_notify_jobs_info(&queue[j], info,
2328                                                            printer, snum,
2329                                                            option_type,
2330                                                            queue[j].job,
2331                                                            mem_ctx); 
2332                         }
2333
2334                         free_a_printer(&printer, 2);
2335                         
2336                 done:
2337                         safe_free(queue);
2338                         break;
2339                 }
2340                 }
2341         }
2342         
2343         /*
2344          * Debugging information, don't delete.
2345          */
2346         /*
2347         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2348         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2349         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2350         
2351         for (i=0; i<info->count; i++) {
2352                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2353                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2354                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2355         }
2356         */
2357         return NT_STATUS_NO_PROBLEMO;
2358 }
2359
2360 /********************************************************************
2361  * spoolss_rfnpcnex
2362  ********************************************************************/
2363
2364 uint32 _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2365 {
2366         POLICY_HND *handle = &q_u->handle;
2367 /*      uint32 change = q_u->change; - notused. */
2368 /*      SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2369         SPOOL_NOTIFY_INFO *info = &r_u->info;
2370
2371         Printer_entry *Printer=find_printer_index_by_hnd(handle);
2372         uint32 result = ERROR_INVALID_HANDLE;
2373
2374         /* we always have a NOTIFY_INFO struct */
2375         r_u->info_ptr=0x1;
2376
2377         if (!OPEN_HANDLE(Printer)) {
2378                 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2379                          OUR_HANDLE(handle)));
2380                 goto done;
2381         }
2382
2383         DEBUG(4,("Printer type %x\n",Printer->printer_type));
2384
2385         /* jfm: the change value isn't used right now.
2386          *      we will honour it when
2387          *      a) we'll be able to send notification to the client
2388          *      b) we'll have a way to communicate between the spoolss process.
2389          *
2390          *      same thing for option->flags
2391          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2392          *      I don't have a global notification system, I'm sending back all the
2393          *      informations even when _NOTHING_ has changed.
2394          */
2395
2396         /* just ignore the SPOOL_NOTIFY_OPTION */
2397         
2398         switch (Printer->printer_type) {
2399                 case PRINTER_HANDLE_IS_PRINTSERVER:
2400                         result = printserver_notify_info(handle, info, 
2401                                                          p->mem_ctx);
2402                         break;
2403                         
2404                 case PRINTER_HANDLE_IS_PRINTER:
2405                         result = printer_notify_info(handle, info, p->mem_ctx);
2406                         break;
2407         }
2408         
2409  done:
2410         return result;
2411 }
2412
2413 /********************************************************************
2414  * construct_printer_info_0
2415  * fill a printer_info_0 struct
2416  ********************************************************************/
2417 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2418 {
2419         pstring chaine;
2420         int count;
2421         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2422         counter_printer_0 *session_counter;
2423         uint32 global_counter;
2424         struct tm *t;
2425         time_t setuptime;
2426
2427         print_queue_struct *queue=NULL;
2428         print_status_struct status;
2429         
2430         memset(&status, 0, sizeof(status));     
2431
2432         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2433                 return False;
2434
2435         count = print_queue_status(snum, &queue, &status);
2436
2437         /* check if we already have a counter for this printer */       
2438         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2439
2440         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2441                 if (session_counter->snum == snum)
2442                         break;
2443         }
2444
2445         /* it's the first time, add it to the list */
2446         if (session_counter==NULL) {
2447                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2448                         free_a_printer(&ntprinter, 2);
2449                         return False;
2450                 }
2451                 ZERO_STRUCTP(session_counter);
2452                 session_counter->snum=snum;
2453                 session_counter->counter=0;
2454                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2455         }
2456         
2457         /* increment it */
2458         session_counter->counter++;
2459         
2460         /* JFM:
2461          * the global_counter should be stored in a TDB as it's common to all the clients
2462          * and should be zeroed on samba startup
2463          */
2464         global_counter=session_counter->counter;
2465         
2466         pstrcpy(chaine,ntprinter->info_2->printername);
2467
2468         init_unistr(&printer->printername, chaine);
2469         
2470         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2471         init_unistr(&printer->servername, chaine);
2472         
2473         printer->cjobs = count;
2474         printer->total_jobs = 0;
2475         printer->total_bytes = 0;
2476
2477         setuptime = (time_t)ntprinter->info_2->setuptime;
2478         t=gmtime(&setuptime);
2479
2480         printer->year = t->tm_year+1900;
2481         printer->month = t->tm_mon+1;
2482         printer->dayofweek = t->tm_wday;
2483         printer->day = t->tm_mday;
2484         printer->hour = t->tm_hour;
2485         printer->minute = t->tm_min;
2486         printer->second = t->tm_sec;
2487         printer->milliseconds = 0;
2488
2489         printer->global_counter = global_counter;
2490         printer->total_pages = 0;
2491         printer->major_version = 0x0004;        /* NT 4 */
2492         printer->build_version = 0x0565;        /* build 1381 */
2493         printer->unknown7 = 0x1;
2494         printer->unknown8 = 0x0;
2495         printer->unknown9 = 0x0;
2496         printer->session_counter = session_counter->counter;
2497         printer->unknown11 = 0x0;
2498         printer->printer_errors = 0x0;          /* number of print failure */
2499         printer->unknown13 = 0x0;
2500         printer->unknown14 = 0x1;
2501         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
2502         printer->unknown16 =  0x0;
2503         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2504         printer->unknown18 =  0x0;
2505         printer->status = nt_printq_status(status.status);
2506         printer->unknown20 =  0x0;
2507         printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2508         printer->unknown22 = 0x0;
2509         printer->unknown23 = 0x6;               /* 6  ???*/
2510         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
2511         printer->unknown25 = 0;
2512         printer->unknown26 = 0;
2513         printer->unknown27 = 0;
2514         printer->unknown28 = 0;
2515         printer->unknown29 = 0;
2516         
2517         safe_free(queue);
2518         free_a_printer(&ntprinter,2);
2519         return (True);  
2520 }
2521
2522 /********************************************************************
2523  * construct_printer_info_1
2524  * fill a printer_info_1 struct
2525  ********************************************************************/
2526 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2527 {
2528         pstring chaine;
2529         pstring chaine2;
2530         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2531
2532         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2533                 return False;
2534
2535         printer->flags=flags;
2536
2537         if (*ntprinter->info_2->comment == '\0') {
2538                 init_unistr(&printer->comment, lp_comment(snum));
2539                 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2540                         ntprinter->info_2->drivername, lp_comment(snum));
2541         }
2542         else {
2543                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2544                 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2545                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
2546         }
2547                 
2548         slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2549
2550         init_unistr(&printer->description, chaine);
2551         init_unistr(&printer->name, chaine2);   
2552         
2553         free_a_printer(&ntprinter,2);
2554
2555         return True;
2556 }
2557
2558 /****************************************************************************
2559  Free a DEVMODE struct.
2560 ****************************************************************************/
2561
2562 static void free_dev_mode(DEVICEMODE *dev)
2563 {
2564         if (dev == NULL)
2565                 return;
2566
2567         if (dev->private)
2568                 safe_free(dev->private);
2569
2570         safe_free(dev); 
2571 }
2572
2573 /****************************************************************************
2574  Create a DEVMODE struct. Returns malloced memory.
2575 ****************************************************************************/
2576
2577 static DEVICEMODE *construct_dev_mode(int snum)
2578 {
2579         char adevice[32];
2580         char aform[32];
2581         NT_PRINTER_INFO_LEVEL *printer = NULL;
2582         NT_DEVICEMODE *ntdevmode = NULL;
2583         DEVICEMODE *devmode = NULL;
2584
2585         DEBUG(7,("construct_dev_mode\n"));
2586         
2587         DEBUGADD(8,("getting printer characteristics\n"));
2588
2589         if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2590                 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2591                 return NULL;
2592         }
2593
2594         ZERO_STRUCTP(devmode);  
2595
2596         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2597                 goto fail;
2598
2599         if (printer->info_2->devmode)
2600                 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2601
2602         if (ntdevmode == NULL)
2603                 goto fail;
2604
2605         DEBUGADD(8,("loading DEVICEMODE\n"));
2606
2607         slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2608         init_unistr(&devmode->devicename, adevice);
2609
2610         slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2611         init_unistr(&devmode->formname, aform);
2612
2613         devmode->specversion      = ntdevmode->specversion;
2614         devmode->driverversion    = ntdevmode->driverversion;
2615         devmode->size             = ntdevmode->size;
2616         devmode->driverextra      = ntdevmode->driverextra;
2617         devmode->fields           = ntdevmode->fields;
2618                                 
2619         devmode->orientation      = ntdevmode->orientation;     
2620         devmode->papersize        = ntdevmode->papersize;
2621         devmode->paperlength      = ntdevmode->paperlength;
2622         devmode->paperwidth       = ntdevmode->paperwidth;
2623         devmode->scale            = ntdevmode->scale;
2624         devmode->copies           = ntdevmode->copies;
2625         devmode->defaultsource    = ntdevmode->defaultsource;
2626         devmode->printquality     = ntdevmode->printquality;
2627         devmode->color            = ntdevmode->color;
2628         devmode->duplex           = ntdevmode->duplex;
2629         devmode->yresolution      = ntdevmode->yresolution;
2630         devmode->ttoption         = ntdevmode->ttoption;
2631         devmode->collate          = ntdevmode->collate;
2632         devmode->icmmethod        = ntdevmode->icmmethod;
2633         devmode->icmintent        = ntdevmode->icmintent;
2634         devmode->mediatype        = ntdevmode->mediatype;
2635         devmode->dithertype       = ntdevmode->dithertype;
2636
2637         if (ntdevmode->private != NULL) {
2638                 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2639                         goto fail;
2640         }
2641
2642         free_nt_devicemode(&ntdevmode);
2643         free_a_printer(&printer,2);
2644
2645         return devmode;
2646
2647   fail:
2648
2649         if (ntdevmode)
2650                 free_nt_devicemode(&ntdevmode);
2651         if (printer)
2652                 free_a_printer(&printer,2);
2653         free_dev_mode(devmode);
2654
2655         return NULL;
2656 }
2657
2658 /********************************************************************
2659  * construct_printer_info_2
2660  * fill a printer_info_2 struct
2661  ********************************************************************/
2662
2663 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2664 {
2665         int count;
2666         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2667
2668         print_queue_struct *queue=NULL;
2669         print_status_struct status;
2670         memset(&status, 0, sizeof(status));     
2671
2672         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2673                 return False;
2674                 
2675         memset(&status, 0, sizeof(status));             
2676         count = print_queue_status(snum, &queue, &status);
2677
2678         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2679         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2680         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
2681         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
2682         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
2683
2684         if (*ntprinter->info_2->comment == '\0')
2685                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
2686         else
2687                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2688
2689         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
2690         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
2691         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2692         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
2693         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
2694
2695         printer->attributes = ntprinter->info_2->attributes;
2696
2697         printer->priority = ntprinter->info_2->priority;                                /* priority */  
2698         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
2699         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
2700         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
2701         printer->status = nt_printq_status(status.status);                      /* status */
2702         printer->cjobs = count;                                                 /* jobs */
2703         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
2704                         
2705         if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2706                 DEBUG(8, ("Returning NULL Devicemode!\n"));
2707         }
2708
2709         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2710                 /* steal the printer info sec_desc structure.  [badly done]. */
2711                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2712                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2713                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2714                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2715         }
2716         else {
2717                 printer->secdesc = NULL;
2718         }
2719
2720         free_a_printer(&ntprinter, 2);
2721         safe_free(queue);
2722         return True;
2723 }
2724
2725 /********************************************************************
2726  * construct_printer_info_3
2727  * fill a printer_info_3 struct
2728  ********************************************************************/
2729 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2730 {
2731         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2732         PRINTER_INFO_3 *printer = NULL;
2733
2734         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2735                 return False;
2736
2737         *pp_printer = NULL;
2738         if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2739                 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2740                 return False;
2741         }
2742
2743         ZERO_STRUCTP(printer);
2744         
2745         printer->flags = 4; /* These are the components of the SD we are returning. */
2746         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2747                 /* steal the printer info sec_desc structure.  [badly done]. */
2748                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2749
2750 #if 0
2751                 /*
2752                  * Set the flags for the components we are returning.
2753                  */
2754
2755                 if (printer->secdesc->owner_sid)
2756                         printer->flags |= OWNER_SECURITY_INFORMATION;
2757
2758                 if (printer->secdesc->grp_sid)
2759                         printer->flags |= GROUP_SECURITY_INFORMATION;
2760
2761                 if (printer->secdesc->dacl)
2762                         printer->flags |= DACL_SECURITY_INFORMATION;
2763
2764                 if (printer->secdesc->sacl)
2765                         printer->flags |= SACL_SECURITY_INFORMATION;
2766 #endif
2767
2768                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2769                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2770                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2771         }
2772
2773         free_a_printer(&ntprinter, 2);
2774
2775         *pp_printer = printer;
2776         return True;
2777 }
2778
2779 /********************************************************************
2780  Spoolss_enumprinters.
2781 ********************************************************************/
2782 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2783 {
2784         int snum;
2785         int i;
2786         int n_services=lp_numservices();
2787         PRINTER_INFO_1 *printers=NULL;
2788         PRINTER_INFO_1 current_prt;
2789         
2790         DEBUG(4,("enum_all_printers_info_1\n"));        
2791
2792         for (snum=0; snum<n_services; snum++) {
2793                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2794                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2795                                 
2796                         if (construct_printer_info_1(flags, &current_prt, snum)) {
2797                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2798                                         *returned=0;
2799                                         return ERROR_NOT_ENOUGH_MEMORY;
2800                                 }
2801                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
2802                                 memcpy(&(printers[*returned]), &current_prt, sizeof(PRINTER_INFO_1));
2803                                 (*returned)++;
2804                         }
2805                 }
2806         }
2807                 
2808         /* check the required size. */  
2809         for (i=0; i<*returned; i++)
2810                 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2811
2812         if (!alloc_buffer_size(buffer, *needed))
2813                 return ERROR_INSUFFICIENT_BUFFER;
2814
2815         /* fill the buffer with the structures */
2816         for (i=0; i<*returned; i++)
2817                 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);       
2818
2819         /* clear memory */
2820         safe_free(printers);
2821
2822         if (*needed > offered) {
2823                 *returned=0;
2824                 return ERROR_INSUFFICIENT_BUFFER;
2825         }
2826         else
2827                 return NT_STATUS_NO_PROBLEMO;
2828 }
2829
2830 /********************************************************************
2831  enum_all_printers_info_1_local.
2832 *********************************************************************/
2833 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2834 {
2835         DEBUG(4,("enum_all_printers_info_1_local\n"));  
2836         
2837         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2838 }
2839
2840 /********************************************************************
2841  enum_all_printers_info_1_name.
2842 *********************************************************************/
2843 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2844 {
2845         fstring temp;
2846         DEBUG(4,("enum_all_printers_info_1_name\n"));   
2847         
2848         fstrcpy(temp, "\\\\");
2849         fstrcat(temp, global_myname);
2850
2851         if (strequal(name, temp)) {
2852                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2853         }
2854         else
2855                 return ERROR_INVALID_NAME;
2856 }
2857
2858 /********************************************************************
2859  enum_all_printers_info_1_remote.
2860 *********************************************************************/
2861 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2862 {
2863         PRINTER_INFO_1 *printer;
2864         fstring printername;
2865         fstring desc;
2866         fstring comment;
2867         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
2868
2869         /* JFM: currently it's more a place holder than anything else.
2870          * In the spooler world there is a notion of server registration.
2871          * the print servers are registring (sp ?) on the PDC (in the same domain)
2872          *
2873          * We should have a TDB here. The registration is done thru an undocumented RPC call.
2874          */
2875         
2876         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2877                 return ERROR_NOT_ENOUGH_MEMORY;
2878
2879         *returned=1;
2880         
2881         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);               
2882         slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2883         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2884
2885         init_unistr(&printer->description, desc);
2886         init_unistr(&printer->name, printername);       
2887         init_unistr(&printer->comment, comment);
2888         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2889                 
2890         /* check the required size. */  
2891         *needed += spoolss_size_printer_info_1(printer);
2892
2893         if (!alloc_buffer_size(buffer, *needed)) {
2894                 safe_free(printer);
2895                 return ERROR_INSUFFICIENT_BUFFER;
2896         }
2897
2898         /* fill the buffer with the structures */
2899         new_smb_io_printer_info_1("", buffer, printer, 0);      
2900
2901         /* clear memory */
2902         safe_free(printer);
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  enum_all_printers_info_1_network.
2914 *********************************************************************/
2915
2916 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2917 {
2918         DEBUG(4,("enum_all_printers_info_1_network\n"));        
2919         
2920         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2921 }
2922
2923 /********************************************************************
2924  * api_spoolss_enumprinters
2925  *
2926  * called from api_spoolss_enumprinters (see this to understand)
2927  ********************************************************************/
2928
2929 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2930 {
2931         int snum;
2932         int i;
2933         int n_services=lp_numservices();
2934         PRINTER_INFO_2 *printers=NULL;
2935         PRINTER_INFO_2 current_prt;
2936
2937         for (snum=0; snum<n_services; snum++) {
2938                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2939                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2940                                 
2941                         if (construct_printer_info_2(&current_prt, snum)) {
2942                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2943                                         return ERROR_NOT_ENOUGH_MEMORY;
2944                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
2945                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
2946                                 (*returned)++;
2947                         }
2948                 }
2949         }
2950         
2951         /* check the required size. */  
2952         for (i=0; i<*returned; i++)
2953                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2954
2955         if (!alloc_buffer_size(buffer, *needed)) {
2956                 for (i=0; i<*returned; i++) {
2957                         free_devmode(printers[i].devmode);
2958                 }
2959                 safe_free(printers);
2960                 return ERROR_INSUFFICIENT_BUFFER;
2961         }
2962
2963         /* fill the buffer with the structures */
2964         for (i=0; i<*returned; i++)
2965                 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);       
2966         
2967         /* clear memory */
2968         for (i=0; i<*returned; i++) {
2969                 free_devmode(printers[i].devmode);
2970         }
2971         safe_free(printers);
2972
2973         if (*needed > offered) {
2974                 *returned=0;
2975                 return ERROR_INSUFFICIENT_BUFFER;
2976         }
2977         else
2978                 return NT_STATUS_NO_PROBLEMO;
2979 }
2980
2981 /********************************************************************
2982  * handle enumeration of printers at level 1
2983  ********************************************************************/
2984 static uint32 enumprinters_level1( uint32 flags, fstring name,
2985                                  NEW_BUFFER *buffer, uint32 offered,
2986                                  uint32 *needed, uint32 *returned)
2987 {
2988         /* Not all the flags are equals */
2989
2990         if (flags & PRINTER_ENUM_LOCAL)
2991                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2992
2993         if (flags & PRINTER_ENUM_NAME)
2994                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2995
2996         if (flags & PRINTER_ENUM_REMOTE)
2997                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2998
2999         if (flags & PRINTER_ENUM_NETWORK)
3000                 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3001
3002         return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
3003 }
3004
3005 /********************************************************************
3006  * handle enumeration of printers at level 2
3007  ********************************************************************/
3008 static uint32 enumprinters_level2( uint32 flags, fstring servername,
3009                                  NEW_BUFFER *buffer, uint32 offered,
3010                                  uint32 *needed, uint32 *returned)
3011 {
3012         fstring temp;
3013         
3014         fstrcpy(temp, "\\\\");
3015         fstrcat(temp, global_myname);
3016
3017         if (flags & PRINTER_ENUM_LOCAL) {
3018                 if (strequal(servername, temp))
3019                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3020                 else
3021                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3022         }
3023
3024         if (flags & PRINTER_ENUM_NAME) {
3025                 if (strequal(servername, temp))
3026                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3027                 else
3028                         return ERROR_INVALID_NAME;
3029         }
3030
3031         if (flags & PRINTER_ENUM_REMOTE)
3032                 return ERROR_INVALID_LEVEL;
3033
3034         return NT_STATUS_NO_PROBLEMO;
3035 }
3036
3037 /********************************************************************
3038  * handle enumeration of printers at level 5
3039  ********************************************************************/
3040 static uint32 enumprinters_level5( uint32 flags, fstring servername,
3041                                  NEW_BUFFER *buffer, uint32 offered,
3042                                  uint32 *needed, uint32 *returned)
3043 {
3044 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3045         return NT_STATUS_NO_PROBLEMO;
3046 }
3047
3048 /********************************************************************
3049  * api_spoolss_enumprinters
3050  *
3051  * called from api_spoolss_enumprinters (see this to understand)
3052  ********************************************************************/
3053
3054 uint32 _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3055 {
3056         uint32 flags = q_u->flags;
3057         UNISTR2 *servername = &q_u->servername;
3058         uint32 level = q_u->level;
3059         NEW_BUFFER *buffer = NULL;
3060         uint32 offered = q_u->offered;
3061         uint32 *needed = &r_u->needed;
3062         uint32 *returned = &r_u->returned;
3063
3064         fstring name;
3065         
3066         /* that's an [in out] buffer */
3067         new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3068         buffer = r_u->buffer;
3069
3070         DEBUG(4,("_spoolss_enumprinters\n"));
3071
3072         *needed=0;
3073         *returned=0;
3074         
3075         /*
3076          * Level 1:
3077          *          flags==PRINTER_ENUM_NAME
3078          *           if name=="" then enumerates all printers
3079          *           if name!="" then enumerate the printer
3080          *          flags==PRINTER_ENUM_REMOTE
3081          *          name is NULL, enumerate printers
3082          * Level 2: name!="" enumerates printers, name can't be NULL
3083          * Level 3: doesn't exist
3084          * Level 4: does a local registry lookup
3085          * Level 5: same as Level 2
3086          */
3087
3088         unistr2_to_ascii(name, servername, sizeof(name)-1);
3089         strupper(name);
3090
3091         switch (level) {
3092         case 1:
3093                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3094         case 2:
3095                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3096         case 5:
3097                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3098         case 3:
3099         case 4:
3100         default:
3101                 return ERROR_INVALID_LEVEL;
3102         }
3103 }
3104
3105 /****************************************************************************
3106 ****************************************************************************/
3107 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3108 {
3109         PRINTER_INFO_0 *printer=NULL;
3110
3111         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3112                 return ERROR_NOT_ENOUGH_MEMORY;
3113
3114         construct_printer_info_0(printer, snum);
3115         
3116         /* check the required size. */  
3117         *needed += spoolss_size_printer_info_0(printer);
3118
3119         if (!alloc_buffer_size(buffer, *needed)) {
3120                 safe_free(printer);
3121                 return ERROR_INSUFFICIENT_BUFFER;
3122         }
3123
3124         /* fill the buffer with the structures */
3125         new_smb_io_printer_info_0("", buffer, printer, 0);      
3126         
3127         /* clear memory */
3128         safe_free(printer);
3129
3130         if (*needed > offered) {
3131                 return ERROR_INSUFFICIENT_BUFFER;
3132         }
3133         else
3134                 return NT_STATUS_NO_PROBLEMO;   
3135 }
3136
3137 /****************************************************************************
3138 ****************************************************************************/
3139 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3140 {
3141         PRINTER_INFO_1 *printer=NULL;
3142
3143         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3144                 return ERROR_NOT_ENOUGH_MEMORY;
3145
3146         construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3147         
3148         /* check the required size. */  
3149         *needed += spoolss_size_printer_info_1(printer);
3150
3151         if (!alloc_buffer_size(buffer, *needed)) {
3152                 safe_free(printer);
3153                 return ERROR_INSUFFICIENT_BUFFER;
3154         }
3155
3156         /* fill the buffer with the structures */
3157         new_smb_io_printer_info_1("", buffer, printer, 0);      
3158         
3159         /* clear memory */
3160         safe_free(printer);
3161
3162         if (*needed > offered) {
3163                 return ERROR_INSUFFICIENT_BUFFER;
3164         }
3165         else
3166                 return NT_STATUS_NO_PROBLEMO;   
3167 }
3168
3169 /****************************************************************************
3170 ****************************************************************************/
3171 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3172 {
3173         PRINTER_INFO_2 *printer=NULL;
3174
3175         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3176                 return ERROR_NOT_ENOUGH_MEMORY;
3177         
3178         construct_printer_info_2(printer, snum);
3179         
3180         /* check the required size. */  
3181         *needed += spoolss_size_printer_info_2(printer);
3182
3183         if (!alloc_buffer_size(buffer, *needed)) {
3184                 free_printer_info_2(printer);
3185                 return ERROR_INSUFFICIENT_BUFFER;
3186         }
3187
3188         /* fill the buffer with the structures */
3189         if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
3190                 free_printer_info_2(printer);
3191                 return ERROR_NOT_ENOUGH_MEMORY;
3192         }
3193         
3194         /* clear memory */
3195         free_printer_info_2(printer);
3196
3197         if (*needed > offered) {
3198                 return ERROR_INSUFFICIENT_BUFFER;
3199         }
3200         else
3201                 return NT_STATUS_NO_PROBLEMO;   
3202 }
3203
3204 /****************************************************************************
3205 ****************************************************************************/
3206 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3207 {
3208         PRINTER_INFO_3 *printer=NULL;
3209
3210         if (!construct_printer_info_3(&printer, snum))
3211                 return ERROR_NOT_ENOUGH_MEMORY;
3212         
3213         /* check the required size. */  
3214         *needed += spoolss_size_printer_info_3(printer);
3215
3216         if (!alloc_buffer_size(buffer, *needed)) {
3217                 free_printer_info_3(printer);
3218                 return ERROR_INSUFFICIENT_BUFFER;
3219         }
3220
3221         /* fill the buffer with the structures */
3222         new_smb_io_printer_info_3("", buffer, printer, 0);      
3223         
3224         /* clear memory */
3225         free_printer_info_3(printer);
3226         
3227         if (*needed > offered) {
3228                 return ERROR_INSUFFICIENT_BUFFER;
3229         }
3230         else
3231                 return NT_STATUS_NO_PROBLEMO;   
3232 }
3233
3234 /****************************************************************************
3235 ****************************************************************************/
3236 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
3237                            NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3238 {
3239         int snum;
3240         
3241         *needed=0;
3242
3243         if (!get_printer_snum(handle, &snum))
3244                 return ERROR_INVALID_HANDLE;
3245
3246         switch (level) {
3247         case 0:
3248                 return getprinter_level_0(snum, buffer, offered, needed);
3249         case 1:
3250                 return getprinter_level_1(snum, buffer, offered, needed);
3251         case 2:         
3252                 return getprinter_level_2(snum, buffer, offered, needed);
3253         case 3:         
3254                 return getprinter_level_3(snum, buffer, offered, needed);
3255         default:
3256                 return ERROR_INVALID_LEVEL;
3257         }
3258 }       
3259                 
3260 /********************************************************************
3261  * fill a DRIVER_INFO_1 struct
3262  ********************************************************************/
3263 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3264 {
3265         init_unistr( &info->name, driver.info_3->name);
3266 }
3267
3268 /********************************************************************
3269  * construct_printer_driver_info_1
3270  ********************************************************************/
3271 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3272 {       
3273         NT_PRINTER_INFO_LEVEL *printer = NULL;
3274         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3275
3276         ZERO_STRUCT(driver);
3277
3278         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3279                 return ERROR_INVALID_PRINTER_NAME;
3280
3281         if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3282                 return ERROR_UNKNOWN_PRINTER_DRIVER;
3283
3284         fill_printer_driver_info_1(info, driver, servername, architecture);
3285
3286         free_a_printer(&printer,2);
3287
3288         return NT_STATUS_NO_PROBLEMO;
3289 }
3290
3291 /********************************************************************
3292  * construct_printer_driver_info_2
3293  * fill a printer_info_2 struct
3294  ********************************************************************/
3295 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3296 {
3297         pstring temp;
3298
3299         info->version=driver.info_3->cversion;
3300
3301         init_unistr( &info->name, driver.info_3->name );
3302         init_unistr( &info->architecture, driver.info_3->environment );
3303
3304
3305     if (strlen(driver.info_3->driverpath)) {
3306                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3307                 init_unistr( &info->driverpath, temp );
3308     } else
3309         init_unistr( &info->driverpath, "" );
3310
3311         if (strlen(driver.info_3->datafile)) {
3312                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3313                 init_unistr( &info->datafile, temp );
3314         } else
3315                 init_unistr( &info->datafile, "" );
3316         
3317         if (strlen(driver.info_3->configfile)) {
3318                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3319                 init_unistr( &info->configfile, temp ); 
3320         } else
3321                 init_unistr( &info->configfile, "" );
3322 }
3323
3324 /********************************************************************
3325  * construct_printer_driver_info_2
3326  * fill a printer_info_2 struct
3327  ********************************************************************/
3328 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3329 {
3330         NT_PRINTER_INFO_LEVEL *printer = NULL;
3331         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3332
3333         ZERO_STRUCT(printer);
3334         ZERO_STRUCT(driver);
3335
3336         if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3337                 return ERROR_INVALID_PRINTER_NAME;
3338
3339         if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3340                 return ERROR_UNKNOWN_PRINTER_DRIVER;
3341
3342         fill_printer_driver_info_2(info, driver, servername);
3343
3344         free_a_printer(&printer,2);
3345
3346         return NT_STATUS_NO_PROBLEMO;
3347 }
3348
3349 /********************************************************************
3350  * copy a strings array and convert to UNICODE
3351  *
3352  * convert an array of ascii string to a UNICODE string
3353  ********************************************************************/
3354 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3355 {
3356         int i=0;
3357         int j=0;
3358         char *v;
3359         pstring line;
3360
3361         DEBUG(6,("init_unistr_array\n"));
3362         *uni_array=NULL;
3363
3364         while (1) {
3365                 if (char_array == NULL)
3366                         v = "";
3367                 else {
3368                         v = char_array[i];
3369                         if (!v) v = ""; /* hack to handle null lists */
3370                 }
3371                 if (strlen(v) == 0) break;
3372                 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3373                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3374                 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3375                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
3376                         return;
3377                 }
3378                 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3379                 i++;
3380         }
3381         
3382         if (*uni_array) {
3383                 (*uni_array)[j]=0x0000;
3384         }
3385         
3386         DEBUGADD(6,("last one:done\n"));
3387 }
3388
3389 /********************************************************************
3390  * construct_printer_info_3
3391  * fill a printer_info_3 struct
3392  ********************************************************************/
3393 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3394 {
3395         pstring temp;
3396
3397         ZERO_STRUCTP(info);
3398
3399         info->version=driver.info_3->cversion;
3400
3401         init_unistr( &info->name, driver.info_3->name );        
3402         init_unistr( &info->architecture, driver.info_3->environment );
3403
3404     if (strlen(driver.info_3->driverpath)) {
3405         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3406         init_unistr( &info->driverpath, temp );
3407     } else
3408         init_unistr( &info->driverpath, "" );
3409     
3410     if (strlen(driver.info_3->datafile)) {
3411         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3412         init_unistr( &info->datafile, temp );
3413     } else
3414         init_unistr( &info->datafile, "" );
3415
3416     if (strlen(driver.info_3->configfile)) {
3417         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3418         init_unistr( &info->configfile, temp ); 
3419     } else
3420         init_unistr( &info->configfile, "" );
3421
3422     if (strlen(driver.info_3->helpfile)) {
3423         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3424         init_unistr( &info->helpfile, temp );
3425     } else
3426         init_unistr( &info->helpfile, "" );
3427
3428         init_unistr( &info->monitorname, driver.info_3->monitorname );
3429         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3430
3431         info->dependentfiles=NULL;
3432         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3433 }
3434
3435 /********************************************************************
3436  * construct_printer_info_3
3437  * fill a printer_info_3 struct
3438  ********************************************************************/
3439 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3440 {       
3441         NT_PRINTER_INFO_LEVEL *printer = NULL;
3442         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3443         uint32 status=0;
3444         ZERO_STRUCT(driver);
3445
3446         status=get_a_printer(&printer, 2, lp_servicename(snum) );
3447         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3448         if (status != 0)
3449                 return ERROR_INVALID_PRINTER_NAME;
3450
3451         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3452         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3453         if (status != 0) {
3454                 free_a_printer(&printer,2);
3455                 return ERROR_UNKNOWN_PRINTER_DRIVER;
3456         }
3457
3458         fill_printer_driver_info_3(info, driver, servername);
3459
3460         free_a_printer(&printer,2);
3461
3462         return NT_STATUS_NO_PROBLEMO;
3463 }
3464
3465 /********************************************************************
3466  * construct_printer_info_6
3467  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3468  ********************************************************************/
3469
3470 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3471 {
3472         pstring temp;
3473         fstring nullstr;
3474
3475         ZERO_STRUCTP(info);
3476         memset(&nullstr, '\0', sizeof(fstring));
3477
3478         info->version=driver.info_3->cversion;
3479
3480         init_unistr( &info->name, driver.info_3->name );        
3481         init_unistr( &info->architecture, driver.info_3->environment );
3482
3483         if (strlen(driver.info_3->driverpath)) {
3484                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3485                 init_unistr( &info->driverpath, temp );
3486         } else
3487                 init_unistr( &info->driverpath, "" );
3488
3489         if (strlen(driver.info_3->datafile)) {
3490                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3491                 init_unistr( &info->datafile, temp );
3492         } else
3493                 init_unistr( &info->datafile, "" );
3494
3495         if (strlen(driver.info_3->configfile)) {
3496                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3497                 init_unistr( &info->configfile, temp ); 
3498         } else
3499                 init_unistr( &info->configfile, "" );
3500
3501         if (strlen(driver.info_3->helpfile)) {
3502                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3503                 init_unistr( &info->helpfile, temp );
3504         } else
3505                 init_unistr( &info->helpfile, "" );
3506         
3507         init_unistr( &info->monitorname, driver.info_3->monitorname );
3508         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3509
3510         info->dependentfiles=NULL;
3511         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3512
3513         info->previousdrivernames=NULL;
3514         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3515
3516         info->driver_date.low=0;
3517         info->driver_date.high=0;
3518
3519         info->padding=0;
3520         info->driver_version_low=0;
3521         info->driver_version_high=0;
3522
3523         init_unistr( &info->mfgname, "");
3524         init_unistr( &info->oem_url, "");
3525         init_unistr( &info->hardware_id, "");
3526         init_unistr( &info->provider, "");
3527 }
3528
3529 /********************************************************************
3530  * construct_printer_info_6
3531  * fill a printer_info_6 struct
3532  ********************************************************************/
3533 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3534 {       
3535         NT_PRINTER_INFO_LEVEL *printer = NULL;
3536         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3537         uint32 status=0;
3538         ZERO_STRUCT(driver);
3539
3540         status=get_a_printer(&printer, 2, lp_servicename(snum) );
3541         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3542         if (status != 0)
3543                 return ERROR_INVALID_PRINTER_NAME;
3544
3545         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3546         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3547         if (status != 0) {
3548                 /*
3549                  * Is this a W2k client ?
3550                  */
3551
3552                 if (version < 3) {
3553                         free_a_printer(&printer,2);
3554                         return ERROR_UNKNOWN_PRINTER_DRIVER;
3555                 }
3556
3557                 /* Yes - try again with a WinNT driver. */
3558                 version = 2;
3559                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3560                 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3561                 if (status != 0) {
3562                         free_a_printer(&printer,2);
3563                         return ERROR_UNKNOWN_PRINTER_DRIVER;
3564                 }
3565         }
3566
3567         fill_printer_driver_info_6(info, driver, servername);
3568
3569         free_a_printer(&printer,2);
3570
3571         return NT_STATUS_NO_PROBLEMO;
3572 }
3573
3574 /****************************************************************************
3575 ****************************************************************************/
3576
3577 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3578 {
3579         safe_free(info->dependentfiles);
3580 }
3581
3582 /****************************************************************************
3583 ****************************************************************************/
3584
3585 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3586 {
3587         safe_free(info->dependentfiles);
3588         
3589 }
3590
3591 /****************************************************************************
3592 ****************************************************************************/
3593 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3594 {
3595         DRIVER_INFO_1 *info=NULL;
3596         uint32 status;
3597         
3598         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3599                 return ERROR_NOT_ENOUGH_MEMORY;
3600         
3601         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3602         if (status != NT_STATUS_NO_PROBLEMO) {
3603                 safe_free(info);
3604                 return status;
3605         }
3606
3607         /* check the required size. */  
3608         *needed += spoolss_size_printer_driver_info_1(info);
3609
3610         if (!alloc_buffer_size(buffer, *needed)) {
3611                 safe_free(info);
3612                 return ERROR_INSUFFICIENT_BUFFER;
3613         }
3614
3615         /* fill the buffer with the structures */
3616         new_smb_io_printer_driver_info_1("", buffer, info, 0);  
3617
3618         /* clear memory */
3619         safe_free(info);
3620
3621         if (*needed > offered)
3622                 return ERROR_INSUFFICIENT_BUFFER;
3623         else
3624                 return NT_STATUS_NO_PROBLEMO;
3625 }
3626
3627 /****************************************************************************
3628 ****************************************************************************/
3629 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3630 {
3631         DRIVER_INFO_2 *info=NULL;
3632         uint32 status;
3633         
3634         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3635                 return ERROR_NOT_ENOUGH_MEMORY;
3636         
3637         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3638         if (status != NT_STATUS_NO_PROBLEMO) {
3639                 safe_free(info);
3640                 return status;
3641         }
3642
3643         /* check the required size. */  
3644         *needed += spoolss_size_printer_driver_info_2(info);
3645
3646         if (!alloc_buffer_size(buffer, *needed)) {
3647                 safe_free(info);
3648                 return ERROR_INSUFFICIENT_BUFFER;
3649         }
3650
3651         /* fill the buffer with the structures */
3652         new_smb_io_printer_driver_info_2("", buffer, info, 0);  
3653
3654         /* clear memory */
3655         safe_free(info);
3656
3657         if (*needed > offered)
3658                 return ERROR_INSUFFICIENT_BUFFER;
3659         else
3660                 return NT_STATUS_NO_PROBLEMO;
3661 }
3662
3663 /****************************************************************************
3664 ****************************************************************************/
3665 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3666 {
3667         DRIVER_INFO_3 info;
3668         uint32 status;
3669
3670         ZERO_STRUCT(info);
3671
3672         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3673         if (status != NT_STATUS_NO_PROBLEMO) {
3674                 return status;
3675         }
3676
3677         /* check the required size. */  
3678         *needed += spoolss_size_printer_driver_info_3(&info);
3679
3680         if (!alloc_buffer_size(buffer, *needed)) {
3681                 free_printer_driver_info_3(&info);
3682                 return ERROR_INSUFFICIENT_BUFFER;
3683         }
3684
3685         /* fill the buffer with the structures */
3686         new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3687
3688         free_printer_driver_info_3(&info);
3689
3690         if (*needed > offered)
3691                 return ERROR_INSUFFICIENT_BUFFER;
3692         else
3693                 return NT_STATUS_NO_PROBLEMO;
3694 }
3695
3696 /****************************************************************************
3697 ****************************************************************************/
3698 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3699 {
3700         DRIVER_INFO_6 info;
3701         uint32 status;
3702
3703         ZERO_STRUCT(info);
3704
3705         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3706         if (status != NT_STATUS_NO_PROBLEMO) {
3707                 return status;
3708         }
3709
3710         /* check the required size. */  
3711         *needed += spoolss_size_printer_driver_info_6(&info);
3712
3713         if (!alloc_buffer_size(buffer, *needed)) {
3714                 free_printer_driver_info_6(&info);
3715                 return ERROR_INSUFFICIENT_BUFFER;
3716         }
3717
3718         /* fill the buffer with the structures */
3719         new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3720
3721         free_printer_driver_info_6(&info);
3722
3723         if (*needed > offered)
3724                 return ERROR_INSUFFICIENT_BUFFER;
3725         else
3726                 return NT_STATUS_NO_PROBLEMO;
3727 }
3728
3729 /****************************************************************************
3730 ****************************************************************************/
3731 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3732                                 uint32 clientmajorversion, uint32 clientminorversion,
3733                                 NEW_BUFFER *buffer, uint32 offered,
3734                                 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3735 {
3736         fstring servername;
3737         fstring architecture;
3738         int snum;
3739
3740         DEBUG(4,("_spoolss_getprinterdriver2\n"));
3741
3742         *needed=0;
3743         *servermajorversion=0;
3744         *serverminorversion=0;
3745
3746         pstrcpy(servername, global_myname);
3747         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3748
3749         if (!get_printer_snum(handle, &snum))
3750                 return ERROR_INVALID_HANDLE;
3751
3752         switch (level) {
3753         case 1:
3754                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3755         case 2:
3756                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3757         case 3:
3758                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3759         case 6:
3760                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3761         default:
3762                 return ERROR_INVALID_LEVEL;
3763         }
3764 }
3765
3766 /****************************************************************************
3767 ****************************************************************************/
3768 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3769 {
3770         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3771
3772         if (OPEN_HANDLE(Printer)) {
3773                 Printer->page_started=True;
3774                 return 0x0;
3775         }
3776
3777         DEBUG(3,("Error in startpageprinter printer handle\n"));
3778         return ERROR_INVALID_HANDLE;
3779 }
3780
3781 /****************************************************************************
3782 ****************************************************************************/
3783 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3784 {
3785         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3786
3787         if (!OPEN_HANDLE(Printer)) {
3788                 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3789                 return ERROR_INVALID_HANDLE;
3790         }
3791         
3792         Printer->page_started=False;
3793
3794         return NT_STATUS_NO_PROBLEMO;
3795 }
3796
3797
3798 /********************************************************************
3799  * api_spoolss_getprinter
3800  * called from the spoolss dispatcher
3801  *
3802  ********************************************************************/
3803 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3804                                 pipes_struct *p, DOC_INFO *docinfo,
3805                                 uint32 *jobid)
3806 {
3807         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3808         int snum;
3809         pstring jobname;
3810         fstring datatype;
3811         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3812         struct current_user user;
3813
3814         if (!OPEN_HANDLE(Printer)) {
3815                 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3816                 return ERROR_INVALID_HANDLE;
3817         }
3818
3819         get_current_user(&user, p);
3820
3821         /*
3822          * a nice thing with NT is it doesn't listen to what you tell it.
3823          * when asked to send _only_ RAW datas, it tries to send datas
3824          * in EMF format.
3825          *
3826          * So I add checks like in NT Server ...
3827          *
3828          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
3829          * there's a bug in NT client-side code, so we'll fix it in the
3830          * server-side code. *nnnnnggggh!*
3831          */
3832         
3833         if (info_1->p_datatype != 0) {
3834                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3835                 if (strcmp(datatype, "RAW") != 0) {
3836                         (*jobid)=0;
3837                         return ERROR_INVALID_DATATYPE;
3838                 }               
3839         }               
3840         
3841         /* get the share number of the printer */
3842         if (!get_printer_snum(handle, &snum)) {
3843                 return ERROR_INVALID_HANDLE;
3844         }
3845
3846         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3847         
3848         Printer->jobid = print_job_start(&user, snum, jobname);
3849
3850         /* An error occured in print_job_start() so return an appropriate
3851            NT error code. */
3852
3853         if (Printer->jobid == -1) {
3854                 return map_nt_error_from_unix(errno);
3855         }
3856         
3857         Printer->document_started=True;
3858         (*jobid) = Printer->jobid;
3859
3860         return 0x0;
3861 }
3862
3863 /********************************************************************
3864  * api_spoolss_getprinter
3865  * called from the spoolss dispatcher
3866  *
3867  ********************************************************************/
3868 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3869 {
3870         Printer_entry *Printer=find_printer_index_by_hnd(handle);
3871         
3872         if (!OPEN_HANDLE(Printer)) {
3873                 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3874                 return ERROR_INVALID_HANDLE;
3875         }
3876         
3877         Printer->document_started=False;
3878         print_job_end(Printer->jobid,True);
3879         /* error codes unhandled so far ... */
3880
3881         return 0x0;
3882 }
3883
3884 /****************************************************************************
3885 ****************************************************************************/
3886 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3887                                 uint32 buffer_size,
3888                                 uint8 *buffer,
3889                                 uint32 *buffer_written)
3890 {
3891         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3892         
3893         if (!OPEN_HANDLE(Printer)) {
3894                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3895                 return ERROR_INVALID_HANDLE;
3896         }
3897
3898         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3899                                             buffer_size);
3900
3901         return 0x0;
3902 }
3903
3904 /********************************************************************
3905  * api_spoolss_getprinter
3906  * called from the spoolss dispatcher
3907  *
3908  ********************************************************************/
3909 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3910                               pipes_struct *p)
3911 {
3912         struct current_user user;
3913         int snum, errcode = ERROR_INVALID_FUNCTION;
3914         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3915
3916         get_current_user(&user, p);
3917
3918         if (!OPEN_HANDLE(Printer)) {
3919                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3920                 return ERROR_INVALID_HANDLE;
3921         }
3922
3923         if (!get_printer_snum(handle, &snum))
3924                 return ERROR_INVALID_HANDLE;
3925
3926         switch (command) {
3927         case PRINTER_CONTROL_PAUSE:
3928                 if (print_queue_pause(&user, snum, &errcode)) {
3929                         errcode = 0;
3930                 }
3931                 break;
3932         case PRINTER_CONTROL_RESUME:
3933         case PRINTER_CONTROL_UNPAUSE:
3934                 if (print_queue_resume(&user, snum, &errcode)) {
3935                         errcode = 0;
3936                 }
3937                 break;
3938         case PRINTER_CONTROL_PURGE:
3939                 if (print_queue_purge(&user, snum, &errcode)) {
3940                         errcode = 0;
3941                 }
3942                 break;
3943         default:
3944                 return ERROR_INVALID_LEVEL;
3945         }
3946
3947         return errcode;
3948 }
3949
3950 /********************************************************************
3951  * api_spoolss_abortprinter
3952  ********************************************************************/
3953
3954 uint32 _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
3955 {
3956         POLICY_HND *handle = &q_u->handle;
3957
3958         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3959 }
3960
3961 /********************************************************************
3962  * called by spoolss_api_setprinter
3963  * when updating a printer description
3964  ********************************************************************/
3965 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3966                                  const SPOOL_PRINTER_INFO_LEVEL *info,
3967                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3968 {
3969         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3970         struct current_user user;
3971         uint32 result;
3972         int snum;
3973
3974         Printer_entry *Printer = find_printer_index_by_hnd(handle);
3975
3976         if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3977                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3978                          OUR_HANDLE(handle)));
3979
3980                 result = ERROR_INVALID_HANDLE;
3981                 goto done;
3982         }
3983
3984         /* NT seems to like setting the security descriptor even though
3985            nothing may have actually changed.  This causes annoying
3986            dialog boxes when the user doesn't have permission to change
3987            the security descriptor. */
3988
3989         nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
3990
3991         if (DEBUGLEVEL >= 10) {
3992                 SEC_ACL *acl;
3993                 int i;
3994
3995                 acl = old_secdesc_ctr->sec->dacl;
3996                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
3997                            PRINTERNAME(snum), acl->num_aces));
3998
3999                 for (i = 0; i < acl->num_aces; i++) {
4000                         fstring sid_str;
4001
4002                         sid_to_string(sid_str, &acl->ace[i].sid);
4003
4004                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
4005                                   acl->ace[i].info.mask));
4006                 }
4007
4008                 acl = secdesc_ctr->sec->dacl;
4009
4010                 if (acl) {
4011                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4012                                    PRINTERNAME(snum), acl->num_aces));
4013
4014                         for (i = 0; i < acl->num_aces; i++) {
4015                                 fstring sid_str;
4016                                 
4017                                 sid_to_string(sid_str, &acl->ace[i].sid);
4018                                 
4019                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
4020                                            acl->ace[i].info.mask));
4021                         }
4022                 } else {
4023                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4024                 }
4025         }
4026
4027         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4028
4029         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4030                 result = NT_STATUS_NO_PROBLEMO;
4031                 goto done;
4032         }
4033
4034         /* Work out which user is performing the operation */
4035
4036         get_current_user(&user, p);
4037
4038         /* Check the user has permissions to change the security
4039            descriptor.  By experimentation with two NT machines, the user
4040            requires Full Access to the printer to change security
4041            information. */
4042
4043         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4044                 result = ERROR_ACCESS_DENIED;
4045                 goto done;
4046         }
4047
4048         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4049
4050  done:
4051
4052         return result;
4053 }
4054
4055 /********************************************************************
4056  Do Samba sanity checks on a printer info struct.
4057  this has changed purpose: it now "canonicalises" printer
4058  info from a client rather than just checking it is correct
4059  ********************************************************************/
4060
4061 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4062 {
4063         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4064                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4065
4066         /* we force some elements to "correct" values */
4067         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4068         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4069                  global_myname, lp_servicename(snum));
4070         fstrcpy(info->sharename, lp_servicename(snum));
4071         info->attributes = PRINTER_ATTRIBUTE_SHARED   \
4072                 | PRINTER_ATTRIBUTE_LOCAL  \
4073                 | PRINTER_ATTRIBUTE_RAW_ONLY \
4074                 | PRINTER_ATTRIBUTE_QUEUED ;
4075         
4076         return True;
4077 }
4078
4079 /****************************************************************************
4080 ****************************************************************************/
4081 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4082 {
4083         pid_t local_pid = sys_getpid();
4084         char *cmd = lp_addprinter_cmd();
4085         char *path;
4086         char **qlines;
4087         pstring tmp_file;
4088         pstring command;
4089         pstring driverlocation;
4090         int numlines;
4091         int ret;
4092
4093         if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4094                 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4095         else
4096                 path = tmpdir();
4097
4098         /* build driver path... only 9X architecture is needed for legacy reasons */
4099         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4100                         global_myname);
4101         /* change \ to \\ for the shell */
4102         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4103         
4104         slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
4105         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4106                         cmd, printer->info_2->printername, printer->info_2->sharename,
4107                         printer->info_2->portname, printer->info_2->drivername,
4108                         printer->info_2->location, driverlocation);
4109
4110         unlink(tmp_file);
4111
4112     /* Convert script args to unix-codepage */
4113     dos_to_unix(command, True);
4114         DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4115         ret = smbrun(command, tmp_file, False);
4116         DEBUGADD(10,("returned [%d]\n", ret));
4117
4118         if ( ret != 0 ) {
4119                 unlink(tmp_file);
4120                 return False;
4121         }
4122
4123         numlines = 0;
4124     /* Get lines and convert them back to dos-codepage */
4125         qlines = file_lines_load(tmp_file, &numlines, True);
4126         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4127         DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
4128         unlink(tmp_file);
4129
4130         if(numlines) {
4131                 /* Set the portname to what the script says the portname should be. */
4132                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4133                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4134
4135                 /* Send SIGHUP to process group... is there a better way? */
4136                 kill(0, SIGHUP);
4137                 add_all_printers();
4138         }
4139
4140         file_lines_free(qlines);
4141         return True;
4142 }
4143
4144 /* Return true if two devicemodes are equal */
4145
4146 #define DEVMODE_CHECK_INT(field) \
4147     if (d1->field != d2->field) { \
4148         DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4149             d1->field, d2->field)); \
4150         return False; \
4151     }
4152
4153 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4154 {
4155         if (!d1 && !d2) goto equal;  /* if both are NULL they are equal */
4156
4157         if (!d1 ^ !d2) {
4158                 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4159                 return False; /* if either is exclusively NULL are not equal */
4160         }
4161
4162         if (!strequal(d1->devicename, d2->devicename)) {
4163                 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4164                 return False;
4165         }
4166
4167         if (!strequal(d1->formname, d2->formname)) {
4168                 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4169                 return False;
4170         }
4171
4172         DEVMODE_CHECK_INT(specversion);
4173         DEVMODE_CHECK_INT(driverversion);
4174         DEVMODE_CHECK_INT(driverextra);
4175         DEVMODE_CHECK_INT(orientation);
4176         DEVMODE_CHECK_INT(papersize);
4177         DEVMODE_CHECK_INT(paperlength);
4178         DEVMODE_CHECK_INT(paperwidth);
4179         DEVMODE_CHECK_INT(scale);
4180         DEVMODE_CHECK_INT(copies);
4181         DEVMODE_CHECK_INT(defaultsource);
4182         DEVMODE_CHECK_INT(printquality);
4183         DEVMODE_CHECK_INT(color);
4184         DEVMODE_CHECK_INT(duplex);
4185         DEVMODE_CHECK_INT(yresolution);
4186         DEVMODE_CHECK_INT(ttoption);
4187         DEVMODE_CHECK_INT(collate);
4188         DEVMODE_CHECK_INT(logpixels);
4189
4190         DEVMODE_CHECK_INT(fields);
4191         DEVMODE_CHECK_INT(bitsperpel);
4192         DEVMODE_CHECK_INT(pelswidth);
4193         DEVMODE_CHECK_INT(pelsheight);
4194         DEVMODE_CHECK_INT(displayflags);
4195         DEVMODE_CHECK_INT(displayfrequency);
4196         DEVMODE_CHECK_INT(icmmethod);
4197         DEVMODE_CHECK_INT(icmintent);
4198         DEVMODE_CHECK_INT(mediatype);
4199         DEVMODE_CHECK_INT(dithertype);
4200         DEVMODE_CHECK_INT(reserved1);
4201         DEVMODE_CHECK_INT(reserved2);
4202         DEVMODE_CHECK_INT(panningwidth);
4203         DEVMODE_CHECK_INT(panningheight);
4204
4205         /* compare the private data if it exists */
4206         if (!d1->driverextra && !d2->driverextra) goto equal;
4207
4208
4209         DEVMODE_CHECK_INT(driverextra);
4210
4211         if (memcmp(d1->private, d2->private, d1->driverextra)) {
4212                 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4213                 return False;
4214         }
4215
4216  equal:
4217         DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4218         return True;
4219 }
4220
4221 /* Return true if two NT_PRINTER_PARAM structures are equal */
4222
4223 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4224                                    NT_PRINTER_PARAM *p2)
4225 {
4226         if (!p1 && !p2) goto equal;
4227
4228         if ((!p1 && p2) || (p1 && !p2)) {
4229                 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4230                 return False;
4231         }
4232
4233         /* Compare lists of printer parameters */
4234
4235         while (p1) {
4236                 BOOL found = False;
4237                 NT_PRINTER_PARAM *q = p1;
4238
4239                 /* Find the parameter in the second structure */
4240
4241                 while(q) {
4242
4243                         if (strequal(p1->value, q->value)) {
4244
4245                                 if (p1->type != q->type) {
4246                                         DEBUG(10, ("nt_printer_param_equal():"
4247                                                    "types for %s differ (%d != %d)\n",
4248                                                    p1->value, p1->type,
4249                                                    q->type));
4250                                         break;
4251                                 }
4252
4253                                 if (p1->data_len != q->data_len) {
4254                                         DEBUG(10, ("nt_printer_param_equal():"
4255                                                    "len for %s differs (%d != %d)\n",
4256                                                    p1->value, p1->data_len,
4257                                                    q->data_len));
4258                                         break;
4259                                 }
4260
4261                                 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4262                                         found = True;
4263                                 } else {
4264                                         DEBUG(10, ("nt_printer_param_equal():"
4265                                                    "data for %s differs\n", p1->value));
4266                                 }
4267
4268                                 break;
4269                         }
4270
4271                         q = q->next;
4272                 }
4273
4274                 if (!found) {
4275                         DEBUG(10, ("nt_printer_param_equal(): param %s "
4276                                    "does not exist\n", p1->value));
4277                         return False;
4278                 }
4279
4280                 p1 = p1->next;
4281         }
4282
4283         equal:
4284
4285         DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4286         return True;
4287 }
4288
4289 /********************************************************************
4290  * Called by update_printer when trying to work out whether to
4291  * actually update printer info.
4292  ********************************************************************/
4293
4294 #define PI_CHECK_INT(field) \
4295     if (pi1->field != pi2->field) { \
4296         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4297             pi1->field, pi2->field)); \
4298         return False; \
4299     }
4300
4301 #define PI_CHECK_STR(field) \
4302     if (!strequal(pi1->field, pi2->field)) { \
4303         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4304             pi1->field, pi2->field)); \
4305         return False; \
4306     }
4307
4308 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4309                                         NT_PRINTER_INFO_LEVEL *p2)
4310 {
4311         NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4312
4313         /* Trivial conditions */
4314
4315         if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4316                 goto equal;
4317         }
4318
4319         if ((!p1 && p2) || (p1 && !p2) ||
4320             (!p1->info_2 && p2->info_2) ||
4321             (p1->info_2 && !p2->info_2)) {
4322                 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4323                            "differ\n"));
4324                 return False;
4325         }
4326
4327         /* Compare two nt_printer_info_level structures.  Don't compare
4328            status or cjobs as they seem to have something to do with the
4329            printer queue. */
4330
4331         pi1 = p1->info_2;
4332         pi2 = p2->info_2;
4333
4334         /* Don't check the attributes as we stomp on the value in
4335            check_printer_ok() anyway. */
4336
4337 #if 0
4338         PI_CHECK_INT(attributes);
4339 #endif
4340
4341         PI_CHECK_INT(priority);
4342         PI_CHECK_INT(default_priority);
4343         PI_CHECK_INT(starttime);
4344         PI_CHECK_INT(untiltime);
4345         PI_CHECK_INT(averageppm);
4346
4347         /* Yuck - don't check the printername or servername as the
4348            add_a_printer() code plays games with them.  You can't
4349            change the printername or the sharename through this interface
4350            in Samba. */
4351
4352         PI_CHECK_STR(sharename);
4353         PI_CHECK_STR(portname);
4354         PI_CHECK_STR(drivername);
4355         PI_CHECK_STR(comment);
4356         PI_CHECK_STR(location);
4357
4358         if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4359                 return False;
4360         }
4361
4362         PI_CHECK_STR(sepfile);
4363         PI_CHECK_STR(printprocessor);
4364         PI_CHECK_STR(datatype);
4365         PI_CHECK_STR(parameters);
4366
4367         if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4368                 return False;
4369         }
4370
4371         if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4372                 return False;
4373         }
4374
4375         PI_CHECK_INT(changeid);
4376         PI_CHECK_INT(c_setprinter);
4377         PI_CHECK_INT(setuptime);
4378
4379  equal:
4380         DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4381         return True;
4382 }
4383
4384 /********************************************************************
4385  * called by spoolss_api_setprinter
4386  * when updating a printer description
4387  ********************************************************************/
4388
4389 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4390                            const SPOOL_PRINTER_INFO_LEVEL *info,
4391                            DEVICEMODE *devmode)
4392 {
4393         int snum;
4394         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4395         Printer_entry *Printer = find_printer_index_by_hnd(handle);
4396         uint32 result;
4397
4398         DEBUG(8,("update_printer\n"));
4399         
4400         result = NT_STATUS_NO_PROBLEMO;
4401
4402         if (level!=2) {
4403                 DEBUG(0,("Send a mail to samba@samba.org\n"));
4404                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4405                 result = ERROR_INVALID_LEVEL;
4406                 goto done;
4407         }
4408
4409         if (!OPEN_HANDLE(Printer)) {
4410                 result = ERROR_INVALID_HANDLE;
4411                 goto done;
4412         }
4413
4414         if (!get_printer_snum(handle, &snum)) {
4415                 result = ERROR_INVALID_HANDLE;
4416                 goto done;
4417         }
4418
4419         if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4420            (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4421                 result = ERROR_INVALID_HANDLE;
4422                 goto done;
4423         }
4424
4425         DEBUGADD(8,("Converting info_2 struct\n"));
4426
4427         /*
4428          * convert_printer_info converts the incoming
4429          * info from the client and overwrites the info
4430          * just read from the tdb in the pointer 'printer'.
4431          */
4432
4433         convert_printer_info(info, printer, level);
4434
4435         if (info->info_2->devmode_ptr != 0) {
4436                 /* we have a valid devmode
4437                    convert it and link it*/
4438
4439                 DEBUGADD(8,("Converting the devicemode struct\n"));
4440                 if (!convert_devicemode(printer->info_2->printername, devmode,
4441                                 &printer->info_2->devmode)) {
4442                         result =  ERROR_NOT_ENOUGH_MEMORY;
4443                         goto done;
4444                 }
4445         }
4446
4447         /* Do sanity check on the requested changes for Samba */
4448
4449         if (!check_printer_ok(printer->info_2, snum)) {
4450                 result = ERROR_INVALID_PARAMETER;
4451                 goto done;
4452         }
4453
4454         /* NT likes to call this function even though nothing has actually
4455            changed.  Check this so the user doesn't end up with an
4456            annoying permission denied dialog box. */
4457
4458         if (nt_printer_info_level_equal(printer, old_printer)) {
4459                 DEBUG(3, ("printer info has not changed\n"));
4460                 result = NT_STATUS_NO_PROBLEMO;
4461                 goto done;
4462         }
4463
4464         /* Check calling user has permission to update printer description */
4465
4466         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4467                 DEBUG(3, ("printer property change denied by security "
4468                           "descriptor\n"));
4469                 result = ERROR_ACCESS_DENIED;
4470                 goto done;
4471         }
4472
4473         /* Call addprinter hook */
4474
4475         if (*lp_addprinter_cmd() )
4476                 if ( !add_printer_hook(printer) ) {
4477                         result = ERROR_ACCESS_DENIED;
4478                         goto done;
4479                 }
4480         
4481         /* Update printer info */
4482
4483         if (add_a_printer(*printer, 2)!=0) {
4484                 /* I don't really know what to return here !!! */
4485                 result = ERROR_ACCESS_DENIED;
4486                 goto done;
4487         }
4488
4489  done:
4490         free_a_printer(&printer, 2);
4491         free_a_printer(&old_printer, 2);
4492
4493         srv_spoolss_sendnotify(handle);
4494
4495         return result;
4496 }
4497
4498 /****************************************************************************
4499 ****************************************************************************/
4500 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4501                            const SPOOL_PRINTER_INFO_LEVEL *info,
4502                            DEVMODE_CTR devmode_ctr,
4503                            SEC_DESC_BUF *secdesc_ctr,
4504                            uint32 command, pipes_struct *p)
4505 {
4506         Printer_entry *Printer = find_printer_index_by_hnd(handle);
4507         
4508         if (!OPEN_HANDLE(Printer)) {
4509                 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4510                 return ERROR_INVALID_HANDLE;
4511         }
4512
4513         /* check the level */   
4514         switch (level) {
4515                 case 0:
4516                         return control_printer(handle, command, p);
4517                 case 2:
4518                         return update_printer(handle, level, info, devmode_ctr.devmode);
4519                 case 3:
4520                         return update_printer_sec(handle, level, info, p,
4521                                                   secdesc_ctr);
4522                 default:
4523                         return ERROR_INVALID_LEVEL;
4524         }
4525 }
4526
4527 /****************************************************************************
4528 ****************************************************************************/
4529 uint32 _spoolss_fcpn(POLICY_HND *handle)
4530 {
4531         Printer_entry *Printer= find_printer_index_by_hnd(handle);
4532         
4533         if (!OPEN_HANDLE(Printer)) {
4534                 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4535                 return ERROR_INVALID_HANDLE;
4536         }
4537
4538         if (Printer->notify.client_connected==True)
4539                 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4540                         return ERROR_INVALID_HANDLE;
4541
4542         Printer->notify.flags=0;
4543         Printer->notify.options=0;
4544         Printer->notify.localmachine[0]='\0';
4545         Printer->notify.printerlocal=0;
4546         if (Printer->notify.option)
4547                 safe_free(Printer->notify.option->ctr.type);
4548         safe_free(Printer->notify.option);
4549         Printer->notify.option=NULL;
4550         Printer->notify.client_connected=False;
4551
4552         return NT_STATUS_NO_PROBLEMO;
4553 }
4554
4555 /****************************************************************************
4556 ****************************************************************************/
4557 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4558                        NEW_BUFFER *buffer, uint32 offered,
4559                        uint32 *needed)
4560 {
4561         *needed = 0;
4562         return ERROR_INVALID_PARAMETER; /* this is what a NT server
4563                                            returns for AddJob. AddJob
4564                                            must fail on non-local
4565                                            printers */
4566 }
4567
4568 /****************************************************************************
4569 ****************************************************************************/
4570 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4571                             int position, int snum)
4572 {
4573         pstring temp_name;
4574         
4575         struct tm *t;
4576         
4577         t=gmtime(&queue->time);
4578         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4579
4580         job_info->jobid=queue->job;     
4581         init_unistr(&job_info->printername, lp_servicename(snum));
4582         init_unistr(&job_info->machinename, temp_name);
4583         init_unistr(&job_info->username, queue->user);
4584         init_unistr(&job_info->document, queue->file);
4585         init_unistr(&job_info->datatype, "RAW");
4586         init_unistr(&job_info->text_status, "");
4587         job_info->status=nt_printj_status(queue->status);
4588         job_info->priority=queue->priority;
4589         job_info->position=position;
4590         job_info->totalpages=0;
4591         job_info->pagesprinted=0;
4592
4593         make_systemtime(&job_info->submitted, t);
4594 }
4595
4596 /****************************************************************************
4597 ****************************************************************************/
4598 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4599                             int position, int snum, 
4600                             NT_PRINTER_INFO_LEVEL *ntprinter)
4601 {
4602         pstring temp_name;
4603         pstring chaine;
4604         struct tm *t;
4605
4606         t=gmtime(&queue->time);
4607         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4608
4609         job_info->jobid=queue->job;
4610         
4611         slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4612
4613         init_unistr(&job_info->printername, chaine);
4614         
4615         init_unistr(&job_info->machinename, temp_name);
4616         init_unistr(&job_info->username, queue->user);
4617         init_unistr(&job_info->document, queue->file);
4618         init_unistr(&job_info->notifyname, queue->user);
4619         init_unistr(&job_info->datatype, "RAW");
4620         init_unistr(&job_info->printprocessor, "winprint");
4621         init_unistr(&job_info->parameters, "");
4622         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4623         init_unistr(&job_info->text_status, "");
4624         
4625 /* and here the security descriptor */
4626
4627         job_info->status=nt_printj_status(queue->status);
4628         job_info->priority=queue->priority;
4629         job_info->position=position;
4630         job_info->starttime=0;
4631         job_info->untiltime=0;
4632         job_info->totalpages=0;
4633         job_info->size=queue->size;
4634         make_systemtime(&(job_info->submitted), t);
4635         job_info->timeelapsed=0;
4636         job_info->pagesprinted=0;
4637
4638         if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4639                 return False;
4640         }
4641
4642         return (True);
4643 }
4644
4645 /****************************************************************************
4646  Enumjobs at level 1.
4647 ****************************************************************************/
4648 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4649                               NEW_BUFFER *buffer, uint32 offered,
4650                               uint32 *needed, uint32 *returned)
4651 {
4652         JOB_INFO_1 *info;
4653         int i;
4654         
4655         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4656         if (info==NULL) {
4657                 safe_free(queue);
4658                 *returned=0;
4659                 return ERROR_NOT_ENOUGH_MEMORY;
4660         }
4661         
4662         for (i=0; i<*returned; i++)
4663                 fill_job_info_1(&info[i], &queue[i], i, snum);
4664
4665         safe_free(queue);
4666
4667         /* check the required size. */  
4668         for (i=0; i<*returned; i++)
4669                 (*needed) += spoolss_size_job_info_1(&info[i]);
4670
4671         if (!alloc_buffer_size(buffer, *needed)) {
4672                 safe_free(info);
4673                 return ERROR_INSUFFICIENT_BUFFER;
4674         }
4675
4676         /* fill the buffer with the structures */
4677         for (i=0; i<*returned; i++)
4678                 new_smb_io_job_info_1("", buffer, &info[i], 0); 
4679
4680         /* clear memory */
4681         safe_free(info);
4682
4683         if (*needed > offered) {
4684                 *returned=0;
4685                 return ERROR_INSUFFICIENT_BUFFER;
4686         }
4687         else
4688                 return NT_STATUS_NO_PROBLEMO;
4689 }
4690
4691 /****************************************************************************
4692  Enumjobs at level 2.
4693 ****************************************************************************/
4694 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4695                               NEW_BUFFER *buffer, uint32 offered,
4696                               uint32 *needed, uint32 *returned)
4697 {
4698         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4699         JOB_INFO_2 *info;
4700         int i;
4701         
4702         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4703         if (info==NULL) {
4704                 *returned=0;
4705                 return ERROR_NOT_ENOUGH_MEMORY;
4706         }
4707
4708         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4709                 *returned = 0;
4710                 return ERROR_NOT_ENOUGH_MEMORY;
4711         }
4712                 
4713         for (i=0; i<*returned; i++)
4714                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4715
4716         free_a_printer(&ntprinter, 2);
4717         safe_free(queue);
4718
4719         /* check the required size. */  
4720         for (i=0; i<*returned; i++)
4721                 (*needed) += spoolss_size_job_info_2(&info[i]);
4722
4723         if (!alloc_buffer_size(buffer, *needed)) {
4724                 safe_free(info);
4725                 return ERROR_INSUFFICIENT_BUFFER;
4726         }
4727
4728         /* fill the buffer with the structures */
4729         for (i=0; i<*returned; i++)
4730                 new_smb_io_job_info_2("", buffer, &info[i], 0); 
4731
4732         /* clear memory */
4733         for (i = 0; i < *returned; i++)
4734                 free_job_info_2(&info[i]);
4735
4736         free(info);
4737
4738         if (*needed > offered) {
4739                 *returned=0;
4740                 return ERROR_INSUFFICIENT_BUFFER;
4741         }
4742         else
4743                 return NT_STATUS_NO_PROBLEMO;
4744 }
4745
4746 /****************************************************************************
4747  Enumjobs.
4748 ****************************************************************************/
4749 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,                  
4750                           NEW_BUFFER *buffer, uint32 offered,
4751                           uint32 *needed, uint32 *returned)
4752 {       
4753         int snum;
4754         print_queue_struct *queue=NULL;
4755         print_status_struct prt_status;
4756
4757         DEBUG(4,("_spoolss_enumjobs\n"));
4758
4759         ZERO_STRUCT(prt_status);
4760
4761         *needed=0;
4762         *returned=0;
4763
4764         if (!get_printer_snum(handle, &snum))
4765                 return ERROR_INVALID_HANDLE;
4766
4767         *returned = print_queue_status(snum, &queue, &prt_status);
4768         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4769
4770         if (*returned == 0) {
4771                 safe_free(queue);
4772                 return NT_STATUS_NO_PROBLEMO;
4773         }
4774
4775         switch (level) {
4776         case 1:
4777                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4778         case 2:
4779                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4780         default:
4781                 safe_free(queue);
4782                 *returned=0;
4783                 return ERROR_INVALID_LEVEL;
4784         }
4785 }
4786
4787
4788 /****************************************************************************
4789 ****************************************************************************/
4790 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4791 {
4792         return 0x0;
4793 }
4794
4795 /****************************************************************************
4796 ****************************************************************************/
4797 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4798                        pipes_struct *p, JOB_INFO *ctr, uint32 command)
4799 {
4800         struct current_user user;
4801         print_status_struct prt_status;
4802         int snum, errcode = ERROR_INVALID_FUNCTION;
4803                 
4804         memset(&prt_status, 0, sizeof(prt_status));
4805
4806         if (!get_printer_snum(handle, &snum)) {
4807                 return ERROR_INVALID_HANDLE;
4808         }
4809
4810         if (!print_job_exists(jobid)) {
4811                 return ERROR_INVALID_PRINTER_NAME;
4812         }
4813
4814         get_current_user(&user, p);     
4815
4816         switch (command) {
4817         case JOB_CONTROL_CANCEL:
4818         case JOB_CONTROL_DELETE:
4819                 if (print_job_delete(&user, jobid, &errcode)) {
4820                         errcode = 0;
4821                 }
4822                 break;
4823         case JOB_CONTROL_PAUSE:
4824                 if (print_job_pause(&user, jobid, &errcode)) {
4825                         errcode = 0;
4826                 }               
4827                 break;
4828         case JOB_CONTROL_RESTART:
4829         case JOB_CONTROL_RESUME:
4830                 if (print_job_resume(&user, jobid, &errcode)) {
4831                         errcode = 0;
4832                 }
4833                 break;
4834         default:
4835                 return ERROR_INVALID_LEVEL;
4836         }
4837
4838         return errcode;
4839 }
4840
4841 /****************************************************************************
4842  Enumerates all printer drivers at level 1.
4843 ****************************************************************************/
4844 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4845 {
4846         int i;
4847         int ndrivers;
4848         uint32 version;
4849         fstring *list = NULL;
4850
4851         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4852         DRIVER_INFO_1 *driver_info_1=NULL;
4853
4854         *returned=0;
4855
4856 #define MAX_VERSION 4
4857
4858         for (version=0; version<MAX_VERSION; version++) {
4859                 list=NULL;
4860                 ndrivers=get_ntdrivers(&list, architecture, version);
4861                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4862
4863                 if(ndrivers == -1)
4864                         return ERROR_NOT_ENOUGH_MEMORY;
4865
4866                 if(ndrivers != 0) {
4867                         if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4868                                 safe_free(list);
4869                                 return ERROR_NOT_ENOUGH_MEMORY;
4870                         }
4871                 }
4872
4873                 for (i=0; i<ndrivers; i++) {
4874                         uint32 status;
4875                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4876                         ZERO_STRUCT(driver);
4877                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4878                                 safe_free(list);
4879                                 return status;
4880                         }
4881                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
4882                         free_a_printer_driver(driver, 3);
4883                 }       
4884
4885                 *returned+=ndrivers;
4886                 safe_free(list);
4887         }
4888         
4889         /* check the required size. */
4890         for (i=0; i<*returned; i++) {
4891                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4892                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4893         }
4894
4895         if (!alloc_buffer_size(buffer, *needed)) {
4896                 safe_free(driver_info_1);
4897                 return ERROR_INSUFFICIENT_BUFFER;
4898         }
4899
4900         /* fill the buffer with the form structures */
4901         for (i=0; i<*returned; i++) {
4902                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4903                 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4904         }
4905
4906         safe_free(driver_info_1);
4907
4908         if (*needed > offered) {
4909                 *returned=0;
4910                 return ERROR_INSUFFICIENT_BUFFER;
4911         }
4912         else
4913                 return NT_STATUS_NO_PROBLEMO;
4914 }
4915
4916 /****************************************************************************
4917  Enumerates all printer drivers at level 2.
4918 ****************************************************************************/
4919 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4920 {
4921         int i;
4922         int ndrivers;
4923         uint32 version;
4924         fstring *list = NULL;
4925
4926         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4927         DRIVER_INFO_2 *driver_info_2=NULL;
4928
4929         *returned=0;
4930
4931 #define MAX_VERSION 4
4932
4933         for (version=0; version<MAX_VERSION; version++) {
4934                 list=NULL;
4935                 ndrivers=get_ntdrivers(&list, architecture, version);
4936                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4937
4938                 if(ndrivers == -1)
4939                         return ERROR_NOT_ENOUGH_MEMORY;
4940
4941                 if(ndrivers != 0) {
4942                         if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4943                                 safe_free(list);
4944                                 return ERROR_NOT_ENOUGH_MEMORY;
4945                         }
4946                 }
4947                 
4948                 for (i=0; i<ndrivers; i++) {
4949                         uint32 status;
4950
4951                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4952                         ZERO_STRUCT(driver);
4953                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4954                                 safe_free(list);
4955                                 return status;
4956                         }
4957                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
4958                         free_a_printer_driver(driver, 3);
4959                 }       
4960
4961                 *returned+=ndrivers;
4962                 safe_free(list);
4963         }
4964         
4965         /* check the required size. */
4966         for (i=0; i<*returned; i++) {
4967                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4968                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4969         }
4970
4971         if (!alloc_buffer_size(buffer, *needed)) {
4972                 safe_free(driver_info_2);
4973                 return ERROR_INSUFFICIENT_BUFFER;
4974         }
4975
4976         /* fill the buffer with the form structures */
4977         for (i=0; i<*returned; i++) {
4978                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4979                 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4980         }
4981
4982         safe_free(driver_info_2);
4983
4984         if (*needed > offered) {
4985                 *returned=0;
4986                 return ERROR_INSUFFICIENT_BUFFER;
4987         }
4988         else
4989                 return NT_STATUS_NO_PROBLEMO;
4990 }
4991
4992 /****************************************************************************
4993  Enumerates all printer drivers at level 3.
4994 ****************************************************************************/
4995 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4996 {
4997         int i;
4998         int ndrivers;
4999         uint32 version;
5000         fstring *list = NULL;
5001
5002         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5003         DRIVER_INFO_3 *driver_info_3=NULL;
5004
5005         *returned=0;
5006
5007 #define MAX_VERSION 4
5008
5009         for (version=0; version<MAX_VERSION; version++) {
5010                 list=NULL;
5011                 ndrivers=get_ntdrivers(&list, architecture, version);
5012                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5013
5014                 if(ndrivers == -1)
5015                         return ERROR_NOT_ENOUGH_MEMORY;
5016
5017                 if(ndrivers != 0) {
5018                         if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5019                                 safe_free(list);
5020                                 return ERROR_NOT_ENOUGH_MEMORY;
5021                         }
5022                 }
5023
5024                 for (i=0; i<ndrivers; i++) {
5025                         uint32 status;
5026
5027                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5028                         ZERO_STRUCT(driver);
5029                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5030                                 safe_free(list);
5031                                 return status;
5032                         }
5033                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
5034                         free_a_printer_driver(driver, 3);
5035                 }       
5036
5037                 *returned+=ndrivers;
5038                 safe_free(list);
5039         }
5040
5041         /* check the required size. */
5042         for (i=0; i<*returned; i++) {
5043                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5044                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5045         }
5046
5047         if (!alloc_buffer_size(buffer, *needed)) {
5048                 safe_free(driver_info_3);
5049                 return ERROR_INSUFFICIENT_BUFFER;
5050         }
5051         
5052         /* fill the buffer with the driver structures */
5053         for (i=0; i<*returned; i++) {
5054                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5055                 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5056         }
5057
5058         for (i=0; i<*returned; i++)
5059                 safe_free(driver_info_3[i].dependentfiles);
5060         
5061         safe_free(driver_info_3);
5062         
5063         if (*needed > offered) {
5064                 *returned=0;
5065                 return ERROR_INSUFFICIENT_BUFFER;
5066         }
5067         else
5068                 return NT_STATUS_NO_PROBLEMO;
5069 }
5070
5071 /****************************************************************************
5072  Enumerates all printer drivers.
5073 ****************************************************************************/
5074 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
5075                                     NEW_BUFFER *buffer, uint32 offered,
5076                                     uint32 *needed, uint32 *returned)
5077 {
5078         fstring *list = NULL;
5079         fstring servername;
5080         fstring architecture;
5081
5082         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5083         fstrcpy(servername, global_myname);
5084         *needed=0;
5085         *returned=0;
5086
5087         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5088
5089         switch (level) {
5090         case 1:
5091                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5092         case 2:
5093                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5094         case 3:
5095                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5096         default:
5097                 *returned=0;
5098                 safe_free(list);
5099                 return ERROR_INVALID_LEVEL;
5100         }
5101 }
5102
5103 /****************************************************************************
5104 ****************************************************************************/
5105 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5106 {
5107         form->flag=list->flag;
5108         init_unistr(&form->name, list->name);
5109         form->width=list->width;
5110         form->length=list->length;
5111         form->left=list->left;
5112         form->top=list->top;
5113         form->right=list->right;
5114         form->bottom=list->bottom;      
5115 }
5116         
5117 /****************************************************************************
5118 ****************************************************************************/
5119 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
5120                                NEW_BUFFER *buffer, uint32 offered,
5121                                uint32 *needed, uint32 *numofforms)
5122 {
5123         nt_forms_struct *list=NULL;
5124         FORM_1 *forms_1;
5125         int buffer_size=0;
5126         int i;
5127
5128         DEBUG(4,("_new_spoolss_enumforms\n"));
5129         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5130         DEBUGADD(5,("Info level [%d]\n",          level));
5131
5132         *numofforms = get_ntforms(&list);
5133         DEBUGADD(5,("Number of forms [%d]\n",     *numofforms));
5134
5135         if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5136
5137         switch (level) {
5138         case 1:
5139                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5140                         *numofforms=0;
5141                         return ERROR_NOT_ENOUGH_MEMORY;
5142                 }
5143
5144                 /* construct the list of form structures */
5145                 for (i=0; i<*numofforms; i++) {
5146                         DEBUGADD(6,("Filling form number [%d]\n",i));
5147                         fill_form_1(&forms_1[i], &list[i]);
5148                 }
5149                 
5150                 safe_free(list);
5151
5152                 /* check the required size. */
5153                 for (i=0; i<*numofforms; i++) {
5154                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5155                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5156                 }
5157
5158                 *needed=buffer_size;            
5159                 
5160                 if (!alloc_buffer_size(buffer, buffer_size)){
5161                         safe_free(forms_1);
5162                         return ERROR_INSUFFICIENT_BUFFER;
5163                 }
5164
5165                 /* fill the buffer with the form structures */
5166                 for (i=0; i<*numofforms; i++) {
5167                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5168                         new_smb_io_form_1("", buffer, &forms_1[i], 0);
5169                 }
5170
5171                 safe_free(forms_1);
5172
5173                 if (*needed > offered) {
5174                         *numofforms=0;
5175                         return ERROR_INSUFFICIENT_BUFFER;
5176                 }
5177                 else
5178                         return NT_STATUS_NO_PROBLEMO;
5179                         
5180         default:
5181                 safe_free(list);
5182                 return ERROR_INVALID_LEVEL;
5183         }
5184
5185 }
5186
5187 /****************************************************************************
5188 ****************************************************************************/
5189 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5190 {
5191         nt_forms_struct *list=NULL;
5192         FORM_1 form_1;
5193         fstring form_name;
5194         int buffer_size=0;
5195         int numofforms, i;
5196
5197         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5198
5199         DEBUG(4,("_spoolss_getform\n"));
5200         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5201         DEBUGADD(5,("Info level [%d]\n",          level));
5202
5203         numofforms = get_ntforms(&list);
5204         DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
5205
5206         if (numofforms == 0)
5207                 return ERROR_NO_MORE_ITEMS;
5208
5209         switch (level) {
5210         case 1:
5211
5212                 /* Check if the requested name is in the list of form structures */
5213                 for (i=0; i<numofforms; i++) {
5214
5215                         DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5216
5217                         if (strequal(form_name, list[i].name)) {
5218                                 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5219                                 fill_form_1(&form_1, &list[i]);
5220                                 break;
5221                         }
5222                 }
5223                 
5224                 safe_free(list);
5225
5226                 /* check the required size. */
5227
5228                 *needed=spoolss_size_form_1(&form_1);
5229                 
5230                 if (!alloc_buffer_size(buffer, buffer_size)){
5231                         return ERROR_INSUFFICIENT_BUFFER;
5232                 }
5233
5234                 if (*needed > offered) {
5235                         return ERROR_INSUFFICIENT_BUFFER;
5236                 }
5237
5238                 /* fill the buffer with the form structures */
5239                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5240                 new_smb_io_form_1("", buffer, &form_1, 0);
5241
5242                 return NT_STATUS_NO_PROBLEMO;
5243                         
5244         default:
5245                 safe_free(list);
5246                 return ERROR_INVALID_LEVEL;
5247         }
5248 }
5249
5250 /****************************************************************************
5251 ****************************************************************************/
5252 static void fill_port_1(PORT_INFO_1 *port, char *name)
5253 {
5254         init_unistr(&port->port_name, name);
5255 }
5256
5257 /****************************************************************************
5258 ****************************************************************************/
5259 static void fill_port_2(PORT_INFO_2 *port, char *name)
5260 {
5261         init_unistr(&port->port_name, name);
5262         init_unistr(&port->monitor_name, "Local Monitor");
5263         init_unistr(&port->description, "Local Port");
5264 #define PORT_TYPE_WRITE 1
5265         port->port_type=PORT_TYPE_WRITE;
5266         port->reserved=0x0;     
5267 }
5268
5269 /****************************************************************************
5270  enumports level 1.
5271 ****************************************************************************/
5272 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5273 {
5274         PORT_INFO_1 *ports=NULL;
5275         int i=0;
5276
5277         if (*lp_enumports_cmd()) {
5278                 pid_t local_pid = sys_getpid();
5279                 char *cmd = lp_enumports_cmd();
5280                 char *path;
5281                 char **qlines;
5282                 pstring tmp_file;
5283                 pstring command;
5284                 int numlines;
5285                 int ret;
5286
5287                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5288                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5289                 else
5290                         path = tmpdir();
5291
5292                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5293                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5294
5295                 unlink(tmp_file);
5296                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5297                 ret = smbrun(command, tmp_file, False);
5298                 DEBUG(10,("Returned [%d]\n", ret));
5299                 if (ret != 0) {
5300                         unlink(tmp_file);
5301                         /* Is this the best error to return here? */
5302                         return ERROR_ACCESS_DENIED;
5303                 }
5304
5305                 numlines = 0;
5306                 qlines = file_lines_load(tmp_file, &numlines,True);
5307                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5308                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5309                 unlink(tmp_file);
5310
5311                 if(numlines) {
5312                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5313                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5314                                 file_lines_free(qlines);
5315                                 return ERROR_NOT_ENOUGH_MEMORY;
5316                         }
5317
5318                         for (i=0; i<numlines; i++) {
5319                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5320                                 fill_port_1(&ports[i], qlines[i]);
5321                         }
5322
5323                         file_lines_free(qlines);
5324                 }
5325
5326                 *returned = numlines;
5327
5328         } else {
5329                 *returned = 1; /* Sole Samba port returned. */
5330
5331                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5332                         return ERROR_NOT_ENOUGH_MEMORY;
5333         
5334                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5335
5336                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5337         }
5338
5339         /* check the required size. */
5340         for (i=0; i<*returned; i++) {
5341                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5342                 *needed += spoolss_size_port_info_1(&ports[i]);
5343         }
5344                 
5345         if (!alloc_buffer_size(buffer, *needed)) {
5346                 safe_free(ports);
5347                 return ERROR_INSUFFICIENT_BUFFER;
5348         }
5349
5350         /* fill the buffer with the ports structures */
5351         for (i=0; i<*returned; i++) {
5352                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5353                 new_smb_io_port_1("", buffer, &ports[i], 0);
5354         }
5355
5356         safe_free(ports);
5357
5358         if (*needed > offered) {
5359                 *returned=0;
5360                 return ERROR_INSUFFICIENT_BUFFER;
5361         }
5362         else
5363                 return NT_STATUS_NO_PROBLEMO;
5364 }
5365
5366 /****************************************************************************
5367  enumports level 2.
5368 ****************************************************************************/
5369
5370 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5371 {
5372         PORT_INFO_2 *ports=NULL;
5373         int i=0;
5374
5375         if (*lp_enumports_cmd()) {
5376                 pid_t local_pid = sys_getpid();
5377                 char *cmd = lp_enumports_cmd();
5378                 char *path;
5379                 char **qlines;
5380                 pstring tmp_file;
5381                 pstring command;
5382                 int numlines;
5383                 int ret;
5384
5385                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5386                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5387                 else
5388                         path = tmpdir();
5389
5390                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5391                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5392
5393                 unlink(tmp_file);
5394                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5395                 ret = smbrun(command, tmp_file, False);
5396                 DEBUGADD(10,("returned [%d]\n", ret));
5397                 if (ret != 0) {
5398                         unlink(tmp_file);
5399                         /* Is this the best error to return here? */
5400                         return ERROR_ACCESS_DENIED;
5401                 }
5402
5403                 numlines = 0;
5404                 qlines = file_lines_load(tmp_file, &numlines,True);
5405                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5406                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5407                 unlink(tmp_file);
5408
5409                 if(numlines) {
5410                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5411                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5412                                 file_lines_free(qlines);
5413                                 return ERROR_NOT_ENOUGH_MEMORY;
5414                         }
5415
5416                         for (i=0; i<numlines; i++) {
5417                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5418                                 fill_port_2(&(ports[i]), qlines[i]);
5419                         }
5420
5421                         file_lines_free(qlines);
5422                 }
5423
5424                 *returned = numlines;
5425
5426         } else {
5427
5428                 *returned = 1;
5429
5430                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5431                         return ERROR_NOT_ENOUGH_MEMORY;
5432         
5433                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5434
5435                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5436         }
5437
5438         /* check the required size. */
5439         for (i=0; i<*returned; i++) {
5440                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5441                 *needed += spoolss_size_port_info_2(&ports[i]);
5442         }
5443                 
5444         if (!alloc_buffer_size(buffer, *needed)) {
5445                 safe_free(ports);
5446                 return ERROR_INSUFFICIENT_BUFFER;
5447         }
5448
5449         /* fill the buffer with the ports structures */
5450         for (i=0; i<*returned; i++) {
5451                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5452                 new_smb_io_port_2("", buffer, &ports[i], 0);
5453         }
5454
5455         safe_free(ports);
5456
5457         if (*needed > offered) {
5458                 *returned=0;
5459                 return ERROR_INSUFFICIENT_BUFFER;
5460         }
5461         else
5462                 return NT_STATUS_NO_PROBLEMO;
5463 }
5464
5465 /****************************************************************************
5466  enumports.
5467 ****************************************************************************/
5468 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5469                            NEW_BUFFER *buffer, uint32 offered,
5470                            uint32 *needed, uint32 *returned)
5471 {
5472         DEBUG(4,("_spoolss_enumports\n"));
5473         
5474         *returned=0;
5475         *needed=0;
5476         
5477         switch (level) {
5478         case 1:
5479                 return enumports_level_1(buffer, offered, needed, returned);
5480         case 2:
5481                 return enumports_level_2(buffer, offered, needed, returned);
5482         default:
5483                 return ERROR_INVALID_LEVEL;
5484         }
5485 }
5486
5487 /****************************************************************************
5488 ****************************************************************************/
5489 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5490                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5491                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5492                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5493                                 POLICY_HND *handle)
5494 {
5495         NT_PRINTER_INFO_LEVEL *printer = NULL;
5496         fstring name;
5497         int snum;
5498
5499         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5500                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5501                 return ERROR_NOT_ENOUGH_MEMORY;
5502         }
5503
5504         ZERO_STRUCTP(printer);
5505
5506         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5507         convert_printer_info(info, printer, 2);
5508
5509         if (*lp_addprinter_cmd() )
5510                 if ( !add_printer_hook(printer) ) {
5511                         free_a_printer(&printer,2);
5512                         return ERROR_ACCESS_DENIED;
5513         }
5514
5515         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5516              printer->info_2->sharename);
5517
5518         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5519                 free_a_printer(&printer,2);
5520                 return ERROR_ACCESS_DENIED;
5521         }
5522
5523         /* you must be a printer admin to add a new printer */
5524         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5525                 free_a_printer(&printer,2);
5526                 return ERROR_ACCESS_DENIED;             
5527         }
5528         
5529         /*
5530          * Do sanity check on the requested changes for Samba.
5531          */
5532
5533         if (!check_printer_ok(printer->info_2, snum)) {
5534                 free_a_printer(&printer,2);
5535                 return ERROR_INVALID_PARAMETER;
5536         }
5537
5538         /* write the ASCII on disk */
5539         if (add_a_printer(*printer, 2) != 0) {
5540                 free_a_printer(&printer,2);
5541                 return ERROR_ACCESS_DENIED;
5542         }
5543
5544         if (!open_printer_hnd(handle, name)) {
5545                 /* Handle open failed - remove addition. */
5546                 del_a_printer(printer->info_2->sharename);
5547                 free_a_printer(&printer,2);
5548                 return ERROR_ACCESS_DENIED;
5549         }
5550
5551         free_a_printer(&printer,2);
5552
5553         srv_spoolss_sendnotify(handle);
5554
5555         return NT_STATUS_NO_PROBLEMO;
5556 }
5557
5558 /****************************************************************************
5559 ****************************************************************************/
5560 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5561                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5562                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5563                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5564                                 POLICY_HND *handle)
5565 {
5566         switch (level) {
5567                 case 1:
5568                         /* we don't handle yet */
5569                         /* but I know what to do ... */
5570                         return ERROR_INVALID_LEVEL;
5571                 case 2:
5572                         return spoolss_addprinterex_level_2(uni_srv_name, info,
5573                                                             unk0, unk1, unk2, unk3,
5574                                                             user_switch, user, handle);
5575                 default:
5576                         return ERROR_INVALID_LEVEL;
5577         }
5578 }
5579
5580 /****************************************************************************
5581 ****************************************************************************/
5582 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5583                                  uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5584 {
5585         uint32 err = NT_STATUS_NO_PROBLEMO;
5586         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5587         struct current_user user;
5588         
5589         ZERO_STRUCT(driver);
5590
5591         get_current_user(&user, p);     
5592         
5593         convert_printer_driver_info(info, &driver, level);
5594
5595         DEBUG(5,("Cleaning driver's information\n"));
5596         if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5597                 goto done;
5598
5599         DEBUG(5,("Moving driver to final destination\n"));
5600         if(!move_driver_to_download_area(driver, level, &user, &err)) {
5601                 if (err == 0)
5602                         err = ERROR_ACCESS_DENIED;
5603                 goto done;
5604         }
5605
5606         if (add_a_printer_driver(driver, level)!=0) {
5607                 err = ERROR_ACCESS_DENIED;
5608                 goto done;
5609         }
5610
5611  done:
5612         free_a_printer_driver(driver, level);
5613         return err;
5614 }
5615
5616 /****************************************************************************
5617 ****************************************************************************/
5618 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5619 {
5620         init_unistr(&info->name, name);
5621 }
5622
5623 /****************************************************************************
5624 ****************************************************************************/
5625 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5626 {
5627         pstring path;
5628         pstring long_archi;
5629         pstring short_archi;
5630         DRIVER_DIRECTORY_1 *info=NULL;
5631
5632         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5633
5634         if (get_short_archi(short_archi, long_archi)==FALSE)
5635                 return ERROR_INVALID_ENVIRONMENT;
5636
5637         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5638                 return ERROR_NOT_ENOUGH_MEMORY;
5639
5640         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5641
5642         DEBUG(4,("printer driver directory: [%s]\n", path));
5643
5644         fill_driverdir_1(info, path);
5645         
5646         *needed += spoolss_size_driverdir_info_1(info);
5647
5648         if (!alloc_buffer_size(buffer, *needed)) {
5649                 safe_free(info);
5650                 return ERROR_INSUFFICIENT_BUFFER;
5651         }
5652
5653         new_smb_io_driverdir_1("", buffer, info, 0);
5654
5655         safe_free(info);
5656         
5657         if (*needed > offered)
5658                 return ERROR_INSUFFICIENT_BUFFER;
5659         else
5660                 return NT_STATUS_NO_PROBLEMO;
5661 }
5662
5663 /****************************************************************************
5664 ****************************************************************************/
5665 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5666                                         NEW_BUFFER *buffer, uint32 offered,
5667                                         uint32 *needed)
5668 {
5669         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5670
5671         *needed=0;
5672
5673         switch(level) {
5674         case 1:
5675                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5676         default:
5677                 return ERROR_INVALID_LEVEL;
5678         }
5679 }
5680         
5681 /****************************************************************************
5682 ****************************************************************************/
5683 uint32 _spoolss_enumprinterdata(pipes_struct *p, POLICY_HND *handle, uint32 idx,
5684                                 uint32 in_value_len, uint32 in_data_len,
5685                                 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5686                                 uint32 *out_type,
5687                                 uint32 *out_max_data_len, uint8  **data_out, uint32 *out_data_len)
5688 {
5689         NT_PRINTER_INFO_LEVEL *printer = NULL;
5690         
5691         fstring value;
5692         
5693         uint32 param_index;
5694         uint32 biggest_valuesize;
5695         uint32 biggest_datasize;
5696         uint32 data_len;
5697         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5698         int snum;
5699         uint8 *data=NULL;
5700         uint32 type;
5701
5702         ZERO_STRUCT(printer);
5703         
5704         *out_max_value_len=0;
5705         *out_value=NULL;
5706         *out_value_len=0;
5707
5708         *out_type=0;
5709
5710         *out_max_data_len=0;
5711         *data_out=NULL;
5712         *out_data_len=0;
5713
5714         DEBUG(5,("spoolss_enumprinterdata\n"));
5715
5716         if (!OPEN_HANDLE(Printer)) {
5717                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5718                 return ERROR_INVALID_HANDLE;
5719         }
5720
5721         if (!get_printer_snum(handle, &snum))
5722                 return ERROR_INVALID_HANDLE;
5723         
5724         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5725                 return ERROR_INVALID_HANDLE;
5726
5727         /*
5728          * The NT machine wants to know the biggest size of value and data
5729          *
5730          * cf: MSDN EnumPrinterData remark section
5731          */
5732         if ( (in_value_len==0) && (in_data_len==0) ) {
5733                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5734
5735 #if 0
5736                 /*
5737                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5738                  * if this parameter size doesn't exist.
5739                  * Ok - my opinion here is that the client is not asking for the greatest
5740                  * possible size of all the parameters, but is asking specifically for the size needed
5741                  * for this specific parameter. In that case we can remove the loop below and
5742                  * simplify this lookup code considerably. JF - comments welcome. JRA.
5743                  */
5744
5745                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5746                         safe_free(data);
5747                         free_a_printer(&printer, 2);
5748                         return ERROR_NO_MORE_ITEMS;
5749                 }
5750 #endif
5751
5752                 safe_free(data);
5753                 data = NULL;
5754
5755                 param_index=0;
5756                 biggest_valuesize=0;
5757                 biggest_datasize=0;
5758                 
5759                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5760                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5761                         if (data_len > biggest_datasize) biggest_datasize=data_len;
5762
5763                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5764
5765                         safe_free(data);
5766                         data = NULL;
5767                         param_index++;
5768                 }
5769
5770                 /*
5771                  * I think this is correct, it doesn't break APW and
5772                  * allows Gerald's Win32 test programs to work correctly,
5773                  * but may need altering.... JRA.
5774                  */
5775
5776                 if (param_index == 0) {
5777                         /* No parameters found. */
5778                         free_a_printer(&printer, 2);
5779                         return ERROR_NO_MORE_ITEMS;
5780                 }
5781
5782                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5783                 *out_value_len=2*(1+biggest_valuesize);
5784                 *out_data_len=biggest_datasize;
5785
5786                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5787
5788                 free_a_printer(&printer, 2);
5789                 return NT_STATUS_NO_PROBLEMO;
5790         }
5791         
5792         /*
5793          * the value len is wrong in NT sp3
5794          * that's the number of bytes not the number of unicode chars
5795          */
5796
5797         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5798                 safe_free(data);
5799                 free_a_printer(&printer, 2);
5800                 return ERROR_NO_MORE_ITEMS;
5801         }
5802
5803         free_a_printer(&printer, 2);
5804
5805         /*
5806          * the value is:
5807          * - counted in bytes in the request
5808          * - counted in UNICODE chars in the max reply
5809          * - counted in bytes in the real size
5810          *
5811          * take a pause *before* coding not *during* coding
5812          */
5813         
5814         *out_max_value_len=(in_value_len/sizeof(uint16));
5815         if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
5816                 safe_free(data);
5817                 return ERROR_NOT_ENOUGH_MEMORY;
5818         }
5819         
5820         *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5821
5822         *out_type=type;
5823
5824         /* the data is counted in bytes */
5825         *out_max_data_len=in_data_len;
5826         if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
5827                 safe_free(data);
5828                 return ERROR_NOT_ENOUGH_MEMORY;
5829         }
5830         
5831         memcpy(*data_out, data, (size_t)data_len);
5832         *out_data_len=data_len;
5833
5834         safe_free(data);
5835         
5836         return NT_STATUS_NO_PROBLEMO;
5837 }
5838
5839 /****************************************************************************
5840 ****************************************************************************/
5841 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5842                                 const UNISTR2 *value,
5843                                 uint32 type,
5844                                 uint32 max_len,
5845                                 const uint8 *data,
5846                                 uint32 real_len,
5847                                 uint32 numeric_data)
5848 {
5849         NT_PRINTER_INFO_LEVEL *printer = NULL;
5850         NT_PRINTER_PARAM *param = NULL, old_param;
5851         int snum=0;
5852         uint32 status = 0x0;
5853         Printer_entry *Printer=find_printer_index_by_hnd(handle);
5854         
5855         DEBUG(5,("spoolss_setprinterdata\n"));
5856
5857         if (!OPEN_HANDLE(Printer)) {
5858                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5859                 return ERROR_INVALID_HANDLE;
5860         }
5861
5862         if (!get_printer_snum(handle, &snum))
5863                 return ERROR_INVALID_HANDLE;
5864
5865         status = get_a_printer(&printer, 2, lp_servicename(snum));
5866         if (status != 0x0)
5867                 return ERROR_INVALID_NAME;
5868
5869         convert_specific_param(&param, value , type, data, real_len);
5870
5871     /* Check if we are making any changes or not.  Return true if
5872            nothing is actually changing. */
5873         
5874     ZERO_STRUCT(old_param);
5875
5876         if (get_specific_param(*printer, 2, param->value, &old_param.data,
5877                                &old_param.type, (unsigned int *)&old_param.data_len)) {
5878
5879                 if (param->type == old_param.type &&
5880                     param->data_len == old_param.data_len &&
5881                     memcmp(param->data, old_param.data,
5882                            old_param.data_len) == 0) {
5883
5884                         DEBUG(3, ("setprinterdata hasn't changed\n"));
5885                         status = NT_STATUS_NO_PROBLEMO;
5886                         goto done;
5887                 }
5888         }
5889
5890         /* Access check */
5891
5892         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5893                 DEBUG(3, ("security descriptor change denied by existing "
5894                           "security descriptor\n"));
5895                 status = ERROR_ACCESS_DENIED;
5896                 goto done;
5897         }
5898
5899         unlink_specific_param_if_exist(printer->info_2, param);
5900         
5901         add_a_specific_param(printer->info_2, &param);
5902         status = mod_a_printer(*printer, 2);
5903
5904  done:
5905         free_a_printer(&printer, 2);
5906         if (param)
5907                 free_nt_printer_param(&param);
5908         safe_free(old_param.data);
5909
5910         return status;
5911 }
5912
5913 /****************************************************************************
5914 ****************************************************************************/
5915
5916 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
5917 {
5918         POLICY_HND *handle = &q_u->handle;
5919         UNISTR2 *value = &q_u->valuename;
5920
5921         NT_PRINTER_INFO_LEVEL *printer = NULL;
5922         NT_PRINTER_PARAM param;
5923         int snum=0;
5924         uint32 status = 0x0;
5925         Printer_entry *Printer=find_printer_index_by_hnd(handle);
5926         
5927         DEBUG(5,("spoolss_deleteprinterdata\n"));
5928         
5929         if (!OPEN_HANDLE(Printer)) {
5930                 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5931                 return ERROR_INVALID_HANDLE;
5932         }
5933
5934         if (!get_printer_snum(handle, &snum))
5935                 return ERROR_INVALID_HANDLE;
5936
5937         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5938                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5939                           "change denied by existing security descriptor\n"));
5940                 return ERROR_ACCESS_DENIED;
5941         }
5942
5943         status = get_a_printer(&printer, 2, lp_servicename(snum));
5944         if (status != 0x0)
5945                 return ERROR_INVALID_NAME;
5946
5947         ZERO_STRUCTP(&param);
5948         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5949
5950         if(!unlink_specific_param_if_exist(printer->info_2, &param))
5951                 status = ERROR_INVALID_PARAMETER;
5952         else
5953                 status = mod_a_printer(*printer, 2);
5954
5955         free_a_printer(&printer, 2);
5956         return status;
5957 }
5958
5959 /****************************************************************************
5960 ****************************************************************************/
5961 uint32 _spoolss_addform( POLICY_HND *handle,
5962                                 uint32 level,
5963                                 const FORM *form)
5964 {
5965         int count=0;
5966         nt_forms_struct *list=NULL;
5967         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5968
5969         DEBUG(5,("spoolss_addform\n"));
5970
5971         if (!OPEN_HANDLE(Printer)) {
5972                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5973                 return ERROR_INVALID_HANDLE;
5974         }
5975
5976         count=get_ntforms(&list);
5977         if(!add_a_form(&list, form, &count))
5978                 return ERROR_NOT_ENOUGH_MEMORY;
5979         write_ntforms(&list, count);
5980
5981         safe_free(list);
5982
5983         return 0x0;
5984 }
5985
5986 /****************************************************************************
5987 ****************************************************************************/
5988 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5989 {
5990         int count=0;
5991         uint32 ret = 0;
5992         nt_forms_struct *list=NULL;
5993         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5994
5995         DEBUG(5,("spoolss_deleteform\n"));
5996
5997         if (!OPEN_HANDLE(Printer)) {
5998                 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5999                 return ERROR_INVALID_HANDLE;
6000         }
6001
6002         count = get_ntforms(&list);
6003         if(!delete_a_form(&list, form_name, &count, &ret))
6004                 return ERROR_INVALID_PARAMETER;
6005
6006         safe_free(list);
6007
6008         return ret;
6009 }
6010
6011 /****************************************************************************
6012 ****************************************************************************/
6013 uint32 _spoolss_setform( POLICY_HND *handle,
6014                                 const UNISTR2 *uni_name,
6015                                 uint32 level,
6016                                 const FORM *form)
6017 {
6018         int count=0;
6019         nt_forms_struct *list=NULL;
6020         Printer_entry *Printer = find_printer_index_by_hnd(handle);
6021
6022         DEBUG(5,("spoolss_setform\n"));
6023
6024         if (!OPEN_HANDLE(Printer)) {
6025                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6026                 return ERROR_INVALID_HANDLE;
6027         }
6028         count=get_ntforms(&list);
6029         update_a_form(&list, form, count);
6030         write_ntforms(&list, count);
6031
6032         safe_free(list);
6033
6034         return 0x0;
6035 }
6036
6037 /****************************************************************************
6038  enumprintprocessors level 1.
6039 ****************************************************************************/
6040 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6041 {
6042         PRINTPROCESSOR_1 *info_1=NULL;
6043         
6044         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6045                 return ERROR_NOT_ENOUGH_MEMORY;
6046
6047         (*returned) = 0x1;
6048         
6049         init_unistr(&info_1->name, "winprint");
6050
6051         *needed += spoolss_size_printprocessor_info_1(info_1);
6052
6053         if (!alloc_buffer_size(buffer, *needed))
6054                 return ERROR_INSUFFICIENT_BUFFER;
6055
6056         smb_io_printprocessor_info_1("", buffer, info_1, 0);
6057
6058         safe_free(info_1);
6059
6060         if (*needed > offered) {
6061                 *returned=0;
6062                 return ERROR_INSUFFICIENT_BUFFER;
6063         }
6064         else
6065                 return NT_STATUS_NO_PROBLEMO;
6066 }
6067
6068 /****************************************************************************
6069 ****************************************************************************/
6070 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
6071                                     NEW_BUFFER *buffer, uint32 offered,
6072                                     uint32 *needed, uint32 *returned)
6073 {
6074         DEBUG(5,("spoolss_enumprintprocessors\n"));
6075
6076         /*
6077          * Enumerate the print processors ...
6078          *
6079          * Just reply with "winprint", to keep NT happy
6080          * and I can use my nice printer checker.
6081          */
6082         
6083         *returned=0;
6084         *needed=0;
6085         
6086         switch (level) {
6087         case 1:
6088                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6089         default:
6090                 return ERROR_INVALID_LEVEL;
6091         }
6092 }
6093
6094 /****************************************************************************
6095  enumprintprocdatatypes level 1.
6096 ****************************************************************************/
6097 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6098 {
6099         PRINTPROCDATATYPE_1 *info_1=NULL;
6100         
6101         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6102                 return ERROR_NOT_ENOUGH_MEMORY;
6103
6104         (*returned) = 0x1;
6105         
6106         init_unistr(&info_1->name, "RAW");
6107
6108         *needed += spoolss_size_printprocdatatype_info_1(info_1);
6109
6110         if (!alloc_buffer_size(buffer, *needed))
6111                 return ERROR_INSUFFICIENT_BUFFER;
6112
6113         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6114
6115         safe_free(info_1);
6116
6117         if (*needed > offered) {
6118                 *returned=0;
6119                 return ERROR_INSUFFICIENT_BUFFER;
6120         }
6121         else
6122                 return NT_STATUS_NO_PROBLEMO;
6123 }
6124
6125 /****************************************************************************
6126 ****************************************************************************/
6127 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
6128                                         NEW_BUFFER *buffer, uint32 offered,
6129                                         uint32 *needed, uint32 *returned)
6130 {
6131         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6132         
6133         *returned=0;
6134         *needed=0;
6135         
6136         switch (level) {
6137         case 1:
6138                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6139         default:
6140                 return ERROR_INVALID_LEVEL;
6141         }
6142 }
6143
6144 /****************************************************************************
6145  enumprintmonitors level 1.
6146 ****************************************************************************/
6147 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6148 {
6149         PRINTMONITOR_1 *info_1=NULL;
6150         
6151         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6152                 return ERROR_NOT_ENOUGH_MEMORY;
6153
6154         (*returned) = 0x1;
6155         
6156         init_unistr(&info_1->name, "Local Port");
6157
6158         *needed += spoolss_size_printmonitor_info_1(info_1);
6159
6160         if (!alloc_buffer_size(buffer, *needed))
6161                 return ERROR_INSUFFICIENT_BUFFER;
6162
6163         smb_io_printmonitor_info_1("", buffer, info_1, 0);
6164
6165         safe_free(info_1);
6166
6167         if (*needed > offered) {
6168                 *returned=0;
6169                 return ERROR_INSUFFICIENT_BUFFER;
6170         }
6171         else
6172                 return NT_STATUS_NO_PROBLEMO;
6173 }
6174
6175 /****************************************************************************
6176  enumprintmonitors level 2.
6177 ****************************************************************************/
6178 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6179 {
6180         PRINTMONITOR_2 *info_2=NULL;
6181         
6182         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6183                 return ERROR_NOT_ENOUGH_MEMORY;
6184
6185         (*returned) = 0x1;
6186         
6187         init_unistr(&info_2->name, "Local Port");
6188         init_unistr(&info_2->environment, "Windows NT X86");
6189         init_unistr(&info_2->dll_name, "localmon.dll");
6190
6191         *needed += spoolss_size_printmonitor_info_2(info_2);
6192
6193         if (!alloc_buffer_size(buffer, *needed))
6194                 return ERROR_INSUFFICIENT_BUFFER;
6195
6196         smb_io_printmonitor_info_2("", buffer, info_2, 0);
6197
6198         safe_free(info_2);
6199
6200         if (*needed > offered) {
6201                 *returned=0;
6202                 return ERROR_INSUFFICIENT_BUFFER;
6203         }
6204         else
6205                 return NT_STATUS_NO_PROBLEMO;
6206 }
6207
6208 /****************************************************************************
6209 ****************************************************************************/
6210 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6211                                     NEW_BUFFER *buffer, uint32 offered,
6212                                     uint32 *needed, uint32 *returned)
6213 {
6214         DEBUG(5,("spoolss_enumprintmonitors\n"));
6215
6216         /*
6217          * Enumerate the print monitors ...
6218          *
6219          * Just reply with "Local Port", to keep NT happy
6220          * and I can use my nice printer checker.
6221          */
6222         
6223         *returned=0;
6224         *needed=0;
6225         
6226         switch (level) {
6227         case 1:
6228                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6229         case 2:
6230                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6231         default:
6232                 return ERROR_INVALID_LEVEL;
6233         }
6234 }
6235
6236 /****************************************************************************
6237 ****************************************************************************/
6238 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6239 {
6240         int i=0;
6241         BOOL found=False;
6242         JOB_INFO_1 *info_1=NULL;
6243
6244         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6245
6246         if (info_1 == NULL) {
6247                 safe_free(queue);
6248                 return ERROR_NOT_ENOUGH_MEMORY;
6249         }
6250                 
6251         for (i=0; i<count && found==False; i++) {
6252                 if (queue[i].job==(int)jobid)
6253                         found=True;
6254         }
6255         
6256         if (found==False) {
6257                 safe_free(queue);
6258                 safe_free(info_1);
6259                 /* I shoud reply something else ... I can't find the good one */
6260                 return NT_STATUS_NO_PROBLEMO;
6261         }
6262         
6263         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6264         
6265         safe_free(queue);
6266         
6267         *needed += spoolss_size_job_info_1(info_1);
6268
6269         if (!alloc_buffer_size(buffer, *needed)) {
6270                 safe_free(info_1);
6271                 return ERROR_INSUFFICIENT_BUFFER;
6272         }
6273
6274         new_smb_io_job_info_1("", buffer, info_1, 0);
6275
6276         safe_free(info_1);
6277
6278         if (*needed > offered)
6279                 return ERROR_INSUFFICIENT_BUFFER;
6280         else
6281                 return NT_STATUS_NO_PROBLEMO;
6282 }
6283
6284
6285 /****************************************************************************
6286 ****************************************************************************/
6287 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6288 {
6289         int i=0;
6290         BOOL found=False;
6291         JOB_INFO_2 *info_2;
6292         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6293
6294         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6295
6296         ZERO_STRUCTP(info_2);
6297
6298         if (info_2 == NULL) {
6299                 safe_free(queue);
6300                 return ERROR_NOT_ENOUGH_MEMORY;
6301         }
6302
6303         for (i=0; i<count && found==False; i++) {
6304                 if (queue[i].job==(int)jobid)
6305                         found=True;
6306         }
6307         
6308         if (found==False) {
6309                 safe_free(queue);
6310                 safe_free(info_2);
6311                 /* I shoud reply something else ... I can't find the good one */
6312                 return NT_STATUS_NO_PROBLEMO;
6313         }
6314         
6315         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6316                 safe_free(queue);
6317                 return ERROR_NOT_ENOUGH_MEMORY;
6318         }
6319
6320         fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6321         
6322         free_a_printer(&ntprinter, 2);
6323         safe_free(queue);
6324         
6325         *needed += spoolss_size_job_info_2(info_2);
6326
6327         if (!alloc_buffer_size(buffer, *needed)) {
6328                 safe_free(info_2);
6329                 return ERROR_INSUFFICIENT_BUFFER;
6330         }
6331
6332         new_smb_io_job_info_2("", buffer, info_2, 0);
6333
6334         free_job_info_2(info_2);
6335         free(info_2);
6336
6337         if (*needed > offered)
6338                 return ERROR_INSUFFICIENT_BUFFER;
6339         else
6340                 return NT_STATUS_NO_PROBLEMO;
6341 }
6342
6343 /****************************************************************************
6344 ****************************************************************************/
6345 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6346                         NEW_BUFFER *buffer, uint32 offered,
6347                         uint32 *needed)
6348 {
6349         int snum;
6350         int count;
6351         print_queue_struct *queue=NULL;
6352         print_status_struct prt_status;
6353
6354         DEBUG(5,("spoolss_getjob\n"));
6355         
6356         memset(&prt_status, 0, sizeof(prt_status));
6357
6358         *needed=0;
6359         
6360         if (!get_printer_snum(handle, &snum))
6361                 return ERROR_INVALID_HANDLE;
6362         
6363         count = print_queue_status(snum, &queue, &prt_status);
6364         
6365         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6366                      count, prt_status.status, prt_status.message));
6367                 
6368         switch (level) {
6369         case 1:
6370                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6371         case 2:
6372                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6373         default:
6374                 safe_free(queue);
6375                 return ERROR_INVALID_LEVEL;
6376         }
6377 }
6378 #undef OLD_NTDOMAIN