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