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