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