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