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