Move to talloc controlled NT forms.
[bbaumbach/samba-autobuild/.git] / source / rpc_server / srv_spoolss_nt.c
1 #define OLD_NTDOMAIN 1
2 /*
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-2000,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8  *  Copyright (C) Jean François Micouleau      1998-2000.
9  *  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(p->mem_ctx, &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 *)talloc(p->mem_ctx, *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                 /* check the required size. */
5300                 for (i=0; i<*numofforms; i++) {
5301                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5302                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5303                 }
5304
5305                 *needed=buffer_size;            
5306                 
5307                 if (!alloc_buffer_size(buffer, buffer_size))
5308                         return ERROR_INSUFFICIENT_BUFFER;
5309
5310                 /* fill the buffer with the form structures */
5311                 for (i=0; i<*numofforms; i++) {
5312                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5313                         new_smb_io_form_1("", buffer, &forms_1[i], 0);
5314                 }
5315
5316                 if (*needed > offered) {
5317                         *numofforms=0;
5318                         return ERROR_INSUFFICIENT_BUFFER;
5319                 }
5320                 else
5321                         return NT_STATUS_NO_PROBLEMO;
5322                         
5323         default:
5324                 return ERROR_INVALID_LEVEL;
5325         }
5326 }
5327
5328 /****************************************************************************
5329 ****************************************************************************/
5330
5331 uint32 _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5332 {
5333 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5334         uint32 level = q_u->level;
5335         UNISTR2 *uni_formname = &q_u->formname;
5336         NEW_BUFFER *buffer = NULL;
5337         uint32 offered = q_u->offered;
5338         uint32 *needed = &r_u->needed;
5339
5340         nt_forms_struct *list=NULL;
5341         FORM_1 form_1;
5342         fstring form_name;
5343         int buffer_size=0;
5344         int numofforms, i;
5345
5346         /* that's an [in out] buffer */
5347         new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5348         buffer = r_u->buffer;
5349
5350         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5351
5352         DEBUG(4,("_spoolss_getform\n"));
5353         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5354         DEBUGADD(5,("Info level [%d]\n",          level));
5355
5356         numofforms = get_ntforms(p->mem_ctx, &list);
5357         DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
5358
5359         if (numofforms == 0)
5360                 return ERROR_NO_MORE_ITEMS;
5361
5362         switch (level) {
5363         case 1:
5364
5365                 /* Check if the requested name is in the list of form structures */
5366                 for (i=0; i<numofforms; i++) {
5367
5368                         DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5369
5370                         if (strequal(form_name, list[i].name)) {
5371                                 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5372                                 fill_form_1(&form_1, &list[i]);
5373                                 break;
5374                         }
5375                 }
5376                 
5377                 /* check the required size. */
5378
5379                 *needed=spoolss_size_form_1(&form_1);
5380                 
5381                 if (!alloc_buffer_size(buffer, buffer_size)){
5382                         return ERROR_INSUFFICIENT_BUFFER;
5383                 }
5384
5385                 if (*needed > offered) {
5386                         return ERROR_INSUFFICIENT_BUFFER;
5387                 }
5388
5389                 /* fill the buffer with the form structures */
5390                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5391                 new_smb_io_form_1("", buffer, &form_1, 0);
5392
5393                 return NT_STATUS_NO_PROBLEMO;
5394                         
5395         default:
5396                 return ERROR_INVALID_LEVEL;
5397         }
5398 }
5399
5400 /****************************************************************************
5401 ****************************************************************************/
5402 static void fill_port_1(PORT_INFO_1 *port, char *name)
5403 {
5404         init_unistr(&port->port_name, name);
5405 }
5406
5407 /****************************************************************************
5408 ****************************************************************************/
5409 static void fill_port_2(PORT_INFO_2 *port, char *name)
5410 {
5411         init_unistr(&port->port_name, name);
5412         init_unistr(&port->monitor_name, "Local Monitor");
5413         init_unistr(&port->description, "Local Port");
5414 #define PORT_TYPE_WRITE 1
5415         port->port_type=PORT_TYPE_WRITE;
5416         port->reserved=0x0;     
5417 }
5418
5419 /****************************************************************************
5420  enumports level 1.
5421 ****************************************************************************/
5422 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5423 {
5424         PORT_INFO_1 *ports=NULL;
5425         int i=0;
5426
5427         if (*lp_enumports_cmd()) {
5428                 pid_t local_pid = sys_getpid();
5429                 char *cmd = lp_enumports_cmd();
5430                 char *path;
5431                 char **qlines;
5432                 pstring tmp_file;
5433                 pstring command;
5434                 int numlines;
5435                 int ret;
5436
5437                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5438                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5439                 else
5440                         path = tmpdir();
5441
5442                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5443                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5444
5445                 unlink(tmp_file);
5446                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5447                 ret = smbrun(command, tmp_file, False);
5448                 DEBUG(10,("Returned [%d]\n", ret));
5449                 if (ret != 0) {
5450                         unlink(tmp_file);
5451                         /* Is this the best error to return here? */
5452                         return ERROR_ACCESS_DENIED;
5453                 }
5454
5455                 numlines = 0;
5456                 qlines = file_lines_load(tmp_file, &numlines,True);
5457                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5458                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5459                 unlink(tmp_file);
5460
5461                 if(numlines) {
5462                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5463                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5464                                 file_lines_free(qlines);
5465                                 return ERROR_NOT_ENOUGH_MEMORY;
5466                         }
5467
5468                         for (i=0; i<numlines; i++) {
5469                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5470                                 fill_port_1(&ports[i], qlines[i]);
5471                         }
5472
5473                         file_lines_free(qlines);
5474                 }
5475
5476                 *returned = numlines;
5477
5478         } else {
5479                 *returned = 1; /* Sole Samba port returned. */
5480
5481                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5482                         return ERROR_NOT_ENOUGH_MEMORY;
5483         
5484                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5485
5486                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5487         }
5488
5489         /* check the required size. */
5490         for (i=0; i<*returned; i++) {
5491                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5492                 *needed += spoolss_size_port_info_1(&ports[i]);
5493         }
5494                 
5495         if (!alloc_buffer_size(buffer, *needed)) {
5496                 safe_free(ports);
5497                 return ERROR_INSUFFICIENT_BUFFER;
5498         }
5499
5500         /* fill the buffer with the ports structures */
5501         for (i=0; i<*returned; i++) {
5502                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5503                 new_smb_io_port_1("", buffer, &ports[i], 0);
5504         }
5505
5506         safe_free(ports);
5507
5508         if (*needed > offered) {
5509                 *returned=0;
5510                 return ERROR_INSUFFICIENT_BUFFER;
5511         }
5512         else
5513                 return NT_STATUS_NO_PROBLEMO;
5514 }
5515
5516 /****************************************************************************
5517  enumports level 2.
5518 ****************************************************************************/
5519
5520 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5521 {
5522         PORT_INFO_2 *ports=NULL;
5523         int i=0;
5524
5525         if (*lp_enumports_cmd()) {
5526                 pid_t local_pid = sys_getpid();
5527                 char *cmd = lp_enumports_cmd();
5528                 char *path;
5529                 char **qlines;
5530                 pstring tmp_file;
5531                 pstring command;
5532                 int numlines;
5533                 int ret;
5534
5535                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5536                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5537                 else
5538                         path = tmpdir();
5539
5540                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5541                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5542
5543                 unlink(tmp_file);
5544                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5545                 ret = smbrun(command, tmp_file, False);
5546                 DEBUGADD(10,("returned [%d]\n", ret));
5547                 if (ret != 0) {
5548                         unlink(tmp_file);
5549                         /* Is this the best error to return here? */
5550                         return ERROR_ACCESS_DENIED;
5551                 }
5552
5553                 numlines = 0;
5554                 qlines = file_lines_load(tmp_file, &numlines,True);
5555                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5556                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5557                 unlink(tmp_file);
5558
5559                 if(numlines) {
5560                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5561                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5562                                 file_lines_free(qlines);
5563                                 return ERROR_NOT_ENOUGH_MEMORY;
5564                         }
5565
5566                         for (i=0; i<numlines; i++) {
5567                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5568                                 fill_port_2(&(ports[i]), qlines[i]);
5569                         }
5570
5571                         file_lines_free(qlines);
5572                 }
5573
5574                 *returned = numlines;
5575
5576         } else {
5577
5578                 *returned = 1;
5579
5580                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5581                         return ERROR_NOT_ENOUGH_MEMORY;
5582         
5583                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5584
5585                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5586         }
5587
5588         /* check the required size. */
5589         for (i=0; i<*returned; i++) {
5590                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5591                 *needed += spoolss_size_port_info_2(&ports[i]);
5592         }
5593                 
5594         if (!alloc_buffer_size(buffer, *needed)) {
5595                 safe_free(ports);
5596                 return ERROR_INSUFFICIENT_BUFFER;
5597         }
5598
5599         /* fill the buffer with the ports structures */
5600         for (i=0; i<*returned; i++) {
5601                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5602                 new_smb_io_port_2("", buffer, &ports[i], 0);
5603         }
5604
5605         safe_free(ports);
5606
5607         if (*needed > offered) {
5608                 *returned=0;
5609                 return ERROR_INSUFFICIENT_BUFFER;
5610         }
5611         else
5612                 return NT_STATUS_NO_PROBLEMO;
5613 }
5614
5615 /****************************************************************************
5616  enumports.
5617 ****************************************************************************/
5618
5619 uint32 _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5620 {
5621 /*      UNISTR2 *name = &q_u->name; - notused. */
5622         uint32 level = q_u->level;
5623         NEW_BUFFER *buffer = NULL;
5624         uint32 offered = q_u->offered;
5625         uint32 *needed = &r_u->needed;
5626         uint32 *returned = &r_u->returned;
5627
5628         /* that's an [in out] buffer */
5629         new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5630         buffer = r_u->buffer;
5631
5632         DEBUG(4,("_spoolss_enumports\n"));
5633         
5634         *returned=0;
5635         *needed=0;
5636         
5637         switch (level) {
5638         case 1:
5639                 return enumports_level_1(buffer, offered, needed, returned);
5640         case 2:
5641                 return enumports_level_2(buffer, offered, needed, returned);
5642         default:
5643                 return ERROR_INVALID_LEVEL;
5644         }
5645 }
5646
5647 /****************************************************************************
5648 ****************************************************************************/
5649 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5650                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5651                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5652                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5653                                 POLICY_HND *handle)
5654 {
5655         NT_PRINTER_INFO_LEVEL *printer = NULL;
5656         fstring name;
5657         int snum;
5658
5659         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5660                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5661                 return ERROR_NOT_ENOUGH_MEMORY;
5662         }
5663
5664         ZERO_STRUCTP(printer);
5665
5666         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5667         convert_printer_info(info, printer, 2);
5668
5669         if (*lp_addprinter_cmd() )
5670                 if ( !add_printer_hook(printer) ) {
5671                         free_a_printer(&printer,2);
5672                         return ERROR_ACCESS_DENIED;
5673         }
5674
5675         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5676              printer->info_2->sharename);
5677
5678         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5679                 free_a_printer(&printer,2);
5680                 return ERROR_ACCESS_DENIED;
5681         }
5682
5683         /* you must be a printer admin to add a new printer */
5684         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5685                 free_a_printer(&printer,2);
5686                 return ERROR_ACCESS_DENIED;             
5687         }
5688         
5689         /*
5690          * Do sanity check on the requested changes for Samba.
5691          */
5692
5693         if (!check_printer_ok(printer->info_2, snum)) {
5694                 free_a_printer(&printer,2);
5695                 return ERROR_INVALID_PARAMETER;
5696         }
5697
5698         /* write the ASCII on disk */
5699         if (add_a_printer(*printer, 2) != 0) {
5700                 free_a_printer(&printer,2);
5701                 return ERROR_ACCESS_DENIED;
5702         }
5703
5704         if (!open_printer_hnd(handle, name)) {
5705                 /* Handle open failed - remove addition. */
5706                 del_a_printer(printer->info_2->sharename);
5707                 free_a_printer(&printer,2);
5708                 return ERROR_ACCESS_DENIED;
5709         }
5710
5711         free_a_printer(&printer,2);
5712
5713         srv_spoolss_sendnotify(handle);
5714
5715         return NT_STATUS_NO_PROBLEMO;
5716 }
5717
5718 /****************************************************************************
5719 ****************************************************************************/
5720
5721 uint32 _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5722 {
5723         UNISTR2 *uni_srv_name = &q_u->server_name;
5724         uint32 level = q_u->level;
5725         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5726         uint32 unk0 = q_u->unk0;
5727         uint32 unk1 = q_u->unk1;
5728         uint32 unk2 = q_u->unk2;
5729         uint32 unk3 = q_u->unk3;
5730         uint32 user_switch = q_u->user_switch;
5731         SPOOL_USER_CTR *user = &q_u->user_ctr;
5732         POLICY_HND *handle = &r_u->handle;
5733
5734         switch (level) {
5735                 case 1:
5736                         /* we don't handle yet */
5737                         /* but I know what to do ... */
5738                         return ERROR_INVALID_LEVEL;
5739                 case 2:
5740                         return spoolss_addprinterex_level_2(uni_srv_name, info,
5741                                                             unk0, unk1, unk2, unk3,
5742                                                             user_switch, user, handle);
5743                 default:
5744                         return ERROR_INVALID_LEVEL;
5745         }
5746 }
5747
5748 /****************************************************************************
5749 ****************************************************************************/
5750
5751 uint32 _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5752 {
5753 /*      UNISTR2 *server_name = &q_u->server_name; - notused. */
5754         uint32 level = q_u->level;
5755         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5756
5757         uint32 err = NT_STATUS_NO_PROBLEMO;
5758         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5759         struct current_user user;
5760         
5761         ZERO_STRUCT(driver);
5762
5763         get_current_user(&user, p);     
5764         
5765         convert_printer_driver_info(info, &driver, level);
5766
5767         DEBUG(5,("Cleaning driver's information\n"));
5768         if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5769                 goto done;
5770
5771         DEBUG(5,("Moving driver to final destination\n"));
5772         if(!move_driver_to_download_area(driver, level, &user, &err)) {
5773                 if (err == 0)
5774                         err = ERROR_ACCESS_DENIED;
5775                 goto done;
5776         }
5777
5778         if (add_a_printer_driver(driver, level)!=0) {
5779                 err = ERROR_ACCESS_DENIED;
5780                 goto done;
5781         }
5782
5783  done:
5784         free_a_printer_driver(driver, level);
5785         return err;
5786 }
5787
5788 /****************************************************************************
5789 ****************************************************************************/
5790 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5791 {
5792         init_unistr(&info->name, name);
5793 }
5794
5795 /****************************************************************************
5796 ****************************************************************************/
5797 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5798 {
5799         pstring path;
5800         pstring long_archi;
5801         pstring short_archi;
5802         DRIVER_DIRECTORY_1 *info=NULL;
5803
5804         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5805
5806         if (get_short_archi(short_archi, long_archi)==FALSE)
5807                 return ERROR_INVALID_ENVIRONMENT;
5808
5809         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5810                 return ERROR_NOT_ENOUGH_MEMORY;
5811
5812         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5813
5814         DEBUG(4,("printer driver directory: [%s]\n", path));
5815
5816         fill_driverdir_1(info, path);
5817         
5818         *needed += spoolss_size_driverdir_info_1(info);
5819
5820         if (!alloc_buffer_size(buffer, *needed)) {
5821                 safe_free(info);
5822                 return ERROR_INSUFFICIENT_BUFFER;
5823         }
5824
5825         new_smb_io_driverdir_1("", buffer, info, 0);
5826
5827         safe_free(info);
5828         
5829         if (*needed > offered)
5830                 return ERROR_INSUFFICIENT_BUFFER;
5831         else
5832                 return NT_STATUS_NO_PROBLEMO;
5833 }
5834
5835 /****************************************************************************
5836 ****************************************************************************/
5837
5838 uint32 _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5839 {
5840         UNISTR2 *name = &q_u->name;
5841         UNISTR2 *uni_environment = &q_u->environment;
5842         uint32 level = q_u->level;
5843         NEW_BUFFER *buffer = NULL;
5844         uint32 offered = q_u->offered;
5845         uint32 *needed = &r_u->needed;
5846
5847         /* that's an [in out] buffer */
5848         new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5849         buffer = r_u->buffer;
5850
5851         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5852
5853         *needed=0;
5854
5855         switch(level) {
5856         case 1:
5857                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5858         default:
5859                 return ERROR_INVALID_LEVEL;
5860         }
5861 }
5862         
5863 /****************************************************************************
5864 ****************************************************************************/
5865
5866 uint32 _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5867 {
5868         POLICY_HND *handle = &q_u->handle;
5869         uint32 idx = q_u->index;
5870         uint32 in_value_len = q_u->valuesize;
5871         uint32 in_data_len = q_u->datasize;
5872         uint32 *out_max_value_len = &r_u->valuesize;
5873         uint16 **out_value = &r_u->value;
5874         uint32 *out_value_len = &r_u->realvaluesize;
5875         uint32 *out_type = &r_u->type;
5876         uint32 *out_max_data_len = &r_u->datasize;
5877         uint8  **data_out = &r_u->data;
5878         uint32 *out_data_len = &r_u->realdatasize;
5879
5880         NT_PRINTER_INFO_LEVEL *printer = NULL;
5881         
5882         fstring value;
5883         
5884         uint32 param_index;
5885         uint32 biggest_valuesize;
5886         uint32 biggest_datasize;
5887         uint32 data_len;
5888         Printer_entry *Printer = find_printer_index_by_hnd(handle);
5889         int snum;
5890         uint8 *data=NULL;
5891         uint32 type;
5892
5893         ZERO_STRUCT(printer);
5894         
5895         *out_max_value_len=0;
5896         *out_value=NULL;
5897         *out_value_len=0;
5898
5899         *out_type=0;
5900
5901         *out_max_data_len=0;
5902         *data_out=NULL;
5903         *out_data_len=0;
5904
5905         DEBUG(5,("spoolss_enumprinterdata\n"));
5906
5907         if (!OPEN_HANDLE(Printer)) {
5908                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5909                 return ERROR_INVALID_HANDLE;
5910         }
5911
5912         if (!get_printer_snum(handle, &snum))
5913                 return ERROR_INVALID_HANDLE;
5914         
5915         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5916                 return ERROR_INVALID_HANDLE;
5917
5918         /*
5919          * The NT machine wants to know the biggest size of value and data
5920          *
5921          * cf: MSDN EnumPrinterData remark section
5922          */
5923         if ( (in_value_len==0) && (in_data_len==0) ) {
5924                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5925
5926 #if 0
5927                 /*
5928                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5929                  * if this parameter size doesn't exist.
5930                  * Ok - my opinion here is that the client is not asking for the greatest
5931                  * possible size of all the parameters, but is asking specifically for the size needed
5932                  * for this specific parameter. In that case we can remove the loop below and
5933                  * simplify this lookup code considerably. JF - comments welcome. JRA.
5934                  */
5935
5936                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5937                         safe_free(data);
5938                         free_a_printer(&printer, 2);
5939                         return ERROR_NO_MORE_ITEMS;
5940                 }
5941 #endif
5942
5943                 safe_free(data);
5944                 data = NULL;
5945
5946                 param_index=0;
5947                 biggest_valuesize=0;
5948                 biggest_datasize=0;
5949                 
5950                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5951                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5952                         if (data_len > biggest_datasize) biggest_datasize=data_len;
5953
5954                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5955
5956                         safe_free(data);
5957                         data = NULL;
5958                         param_index++;
5959                 }
5960
5961                 /*
5962                  * I think this is correct, it doesn't break APW and
5963                  * allows Gerald's Win32 test programs to work correctly,
5964                  * but may need altering.... JRA.
5965                  */
5966
5967                 if (param_index == 0) {
5968                         /* No parameters found. */
5969                         free_a_printer(&printer, 2);
5970                         return ERROR_NO_MORE_ITEMS;
5971                 }
5972
5973                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5974                 *out_value_len=2*(1+biggest_valuesize);
5975                 *out_data_len=biggest_datasize;
5976
5977                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5978
5979                 free_a_printer(&printer, 2);
5980                 return NT_STATUS_NO_PROBLEMO;
5981         }
5982         
5983         /*
5984          * the value len is wrong in NT sp3
5985          * that's the number of bytes not the number of unicode chars
5986          */
5987
5988         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5989                 safe_free(data);
5990                 free_a_printer(&printer, 2);
5991                 return ERROR_NO_MORE_ITEMS;
5992         }
5993
5994         free_a_printer(&printer, 2);
5995
5996         /*
5997          * the value is:
5998          * - counted in bytes in the request
5999          * - counted in UNICODE chars in the max reply
6000          * - counted in bytes in the real size
6001          *
6002          * take a pause *before* coding not *during* coding
6003          */
6004         
6005         *out_max_value_len=(in_value_len/sizeof(uint16));
6006         if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6007                 safe_free(data);
6008                 return ERROR_NOT_ENOUGH_MEMORY;
6009         }
6010         
6011         *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
6012
6013         *out_type=type;
6014
6015         /* the data is counted in bytes */
6016         *out_max_data_len=in_data_len;
6017         if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6018                 safe_free(data);
6019                 return ERROR_NOT_ENOUGH_MEMORY;
6020         }
6021         
6022         memcpy(*data_out, data, (size_t)data_len);
6023         *out_data_len=data_len;
6024
6025         safe_free(data);
6026         
6027         return NT_STATUS_NO_PROBLEMO;
6028 }
6029
6030 /****************************************************************************
6031 ****************************************************************************/
6032
6033 uint32 _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6034 {
6035         POLICY_HND *handle = &q_u->handle;
6036         UNISTR2 *value = &q_u->value;
6037         uint32 type = q_u->type;
6038 /*      uint32 max_len = q_u->max_len; - notused. */
6039         uint8 *data = q_u->data;
6040         uint32 real_len = q_u->real_len;
6041 /*      uint32 numeric_data = q_u->numeric_data; - notused. */
6042
6043         NT_PRINTER_INFO_LEVEL *printer = NULL;
6044         NT_PRINTER_PARAM *param = NULL, old_param;
6045         int snum=0;
6046         uint32 status = 0x0;
6047         Printer_entry *Printer=find_printer_index_by_hnd(handle);
6048         
6049         DEBUG(5,("spoolss_setprinterdata\n"));
6050
6051         if (!OPEN_HANDLE(Printer)) {
6052                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6053                 return ERROR_INVALID_HANDLE;
6054         }
6055
6056         if (!get_printer_snum(handle, &snum))
6057                 return ERROR_INVALID_HANDLE;
6058
6059         status = get_a_printer(&printer, 2, lp_servicename(snum));
6060         if (status != 0x0)
6061                 return ERROR_INVALID_NAME;
6062
6063         convert_specific_param(&param, value , type, data, real_len);
6064
6065     /* Check if we are making any changes or not.  Return true if
6066            nothing is actually changing. */
6067         
6068     ZERO_STRUCT(old_param);
6069
6070         if (get_specific_param(*printer, 2, param->value, &old_param.data,
6071                                &old_param.type, (unsigned int *)&old_param.data_len)) {
6072
6073                 if (param->type == old_param.type &&
6074                     param->data_len == old_param.data_len &&
6075                     memcmp(param->data, old_param.data,
6076                            old_param.data_len) == 0) {
6077
6078                         DEBUG(3, ("setprinterdata hasn't changed\n"));
6079                         status = NT_STATUS_NO_PROBLEMO;
6080                         goto done;
6081                 }
6082         }
6083
6084         /* Access check */
6085
6086         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6087                 DEBUG(3, ("security descriptor change denied by existing "
6088                           "security descriptor\n"));
6089                 status = ERROR_ACCESS_DENIED;
6090                 goto done;
6091         }
6092
6093         unlink_specific_param_if_exist(printer->info_2, param);
6094         
6095         add_a_specific_param(printer->info_2, &param);
6096         status = mod_a_printer(*printer, 2);
6097
6098  done:
6099         free_a_printer(&printer, 2);
6100         if (param)
6101                 free_nt_printer_param(&param);
6102         safe_free(old_param.data);
6103
6104         return status;
6105 }
6106
6107 /****************************************************************************
6108 ****************************************************************************/
6109
6110 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6111 {
6112         POLICY_HND *handle = &q_u->handle;
6113         UNISTR2 *value = &q_u->valuename;
6114
6115         NT_PRINTER_INFO_LEVEL *printer = NULL;
6116         NT_PRINTER_PARAM param;
6117         int snum=0;
6118         uint32 status = 0x0;
6119         Printer_entry *Printer=find_printer_index_by_hnd(handle);
6120         
6121         DEBUG(5,("spoolss_deleteprinterdata\n"));
6122         
6123         if (!OPEN_HANDLE(Printer)) {
6124                 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6125                 return ERROR_INVALID_HANDLE;
6126         }
6127
6128         if (!get_printer_snum(handle, &snum))
6129                 return ERROR_INVALID_HANDLE;
6130
6131         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6132                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6133                           "change denied by existing security descriptor\n"));
6134                 return ERROR_ACCESS_DENIED;
6135         }
6136
6137         status = get_a_printer(&printer, 2, lp_servicename(snum));
6138         if (status != 0x0)
6139                 return ERROR_INVALID_NAME;
6140
6141         ZERO_STRUCTP(&param);
6142         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6143
6144         if(!unlink_specific_param_if_exist(printer->info_2, &param))
6145                 status = ERROR_INVALID_PARAMETER;
6146         else
6147                 status = mod_a_printer(*printer, 2);
6148
6149         free_a_printer(&printer, 2);
6150         return status;
6151 }
6152
6153 /****************************************************************************
6154 ****************************************************************************/
6155
6156 uint32 _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6157 {
6158         POLICY_HND *handle = &q_u->handle;
6159 /*      uint32 level = q_u->level; - notused. */
6160         FORM *form = &q_u->form;
6161
6162         int count=0;
6163         nt_forms_struct *list=NULL;
6164         Printer_entry *Printer = find_printer_index_by_hnd(handle);
6165
6166         DEBUG(5,("spoolss_addform\n"));
6167
6168         if (!OPEN_HANDLE(Printer)) {
6169                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6170                 return ERROR_INVALID_HANDLE;
6171         }
6172
6173         count=get_ntforms(p->mem_ctx, &list);
6174         if(!add_a_form(p->mem_ctx, &list, form, &count))
6175                 return ERROR_NOT_ENOUGH_MEMORY;
6176         write_ntforms(&list, count);
6177
6178         return NT_STATUS_NOPROBLEMO;
6179 }
6180
6181 /****************************************************************************
6182 ****************************************************************************/
6183
6184 uint32 _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6185 {
6186         POLICY_HND *handle = &q_u->handle;
6187         UNISTR2 *form_name = &q_u->name;
6188
6189         int count=0;
6190         uint32 ret = 0;
6191         nt_forms_struct *list=NULL;
6192         Printer_entry *Printer = find_printer_index_by_hnd(handle);
6193
6194         DEBUG(5,("spoolss_deleteform\n"));
6195
6196         if (!OPEN_HANDLE(Printer)) {
6197                 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6198                 return ERROR_INVALID_HANDLE;
6199         }
6200
6201         count = get_ntforms(p->mem_ctx, &list);
6202         if(!delete_a_form(&list, form_name, &count, &ret))
6203                 return ERROR_INVALID_PARAMETER;
6204
6205         return ret;
6206 }
6207
6208 /****************************************************************************
6209 ****************************************************************************/
6210
6211 uint32 _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6212 {
6213         POLICY_HND *handle = &q_u->handle;
6214 /*      UNISTR2 *uni_name = &q_u->name; - notused. */
6215 /*      uint32 level = q_u->level; - notused. */
6216         FORM *form = &q_u->form;
6217
6218         int count=0;
6219         nt_forms_struct *list=NULL;
6220         Printer_entry *Printer = find_printer_index_by_hnd(handle);
6221
6222         DEBUG(5,("spoolss_setform\n"));
6223
6224         if (!OPEN_HANDLE(Printer)) {
6225                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6226                 return ERROR_INVALID_HANDLE;
6227         }
6228         count=get_ntforms(p->mem_ctx, &list);
6229         update_a_form(&list, form, count);
6230         write_ntforms(&list, count);
6231
6232         return 0x0;
6233 }
6234
6235 /****************************************************************************
6236  enumprintprocessors level 1.
6237 ****************************************************************************/
6238 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6239 {
6240         PRINTPROCESSOR_1 *info_1=NULL;
6241         
6242         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6243                 return ERROR_NOT_ENOUGH_MEMORY;
6244
6245         (*returned) = 0x1;
6246         
6247         init_unistr(&info_1->name, "winprint");
6248
6249         *needed += spoolss_size_printprocessor_info_1(info_1);
6250
6251         if (!alloc_buffer_size(buffer, *needed))
6252                 return ERROR_INSUFFICIENT_BUFFER;
6253
6254         smb_io_printprocessor_info_1("", buffer, info_1, 0);
6255
6256         safe_free(info_1);
6257
6258         if (*needed > offered) {
6259                 *returned=0;
6260                 return ERROR_INSUFFICIENT_BUFFER;
6261         }
6262         else
6263                 return NT_STATUS_NO_PROBLEMO;
6264 }
6265
6266 /****************************************************************************
6267 ****************************************************************************/
6268
6269 uint32 _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6270 {
6271 /*      UNISTR2 *name = &q_u->name; - notused. */
6272 /*      UNISTR2 *environment = &q_u->environment; - notused. */
6273         uint32 level = q_u->level;
6274     NEW_BUFFER *buffer = NULL;
6275         uint32 offered = q_u->offered;
6276     uint32 *needed = &r_u->needed;
6277         uint32 *returned = &r_u->returned;
6278
6279         /* that's an [in out] buffer */
6280         new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6281         buffer = r_u->buffer;
6282
6283         DEBUG(5,("spoolss_enumprintprocessors\n"));
6284
6285         /*
6286          * Enumerate the print processors ...
6287          *
6288          * Just reply with "winprint", to keep NT happy
6289          * and I can use my nice printer checker.
6290          */
6291         
6292         *returned=0;
6293         *needed=0;
6294         
6295         switch (level) {
6296         case 1:
6297                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6298         default:
6299                 return ERROR_INVALID_LEVEL;
6300         }
6301 }
6302
6303 /****************************************************************************
6304  enumprintprocdatatypes level 1.
6305 ****************************************************************************/
6306 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6307 {
6308         PRINTPROCDATATYPE_1 *info_1=NULL;
6309         
6310         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6311                 return ERROR_NOT_ENOUGH_MEMORY;
6312
6313         (*returned) = 0x1;
6314         
6315         init_unistr(&info_1->name, "RAW");
6316
6317         *needed += spoolss_size_printprocdatatype_info_1(info_1);
6318
6319         if (!alloc_buffer_size(buffer, *needed))
6320                 return ERROR_INSUFFICIENT_BUFFER;
6321
6322         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6323
6324         safe_free(info_1);
6325
6326         if (*needed > offered) {
6327                 *returned=0;
6328                 return ERROR_INSUFFICIENT_BUFFER;
6329         }
6330         else
6331                 return NT_STATUS_NO_PROBLEMO;
6332 }
6333
6334 /****************************************************************************
6335 ****************************************************************************/
6336
6337 uint32 _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6338 {
6339 /*      UNISTR2 *name = &q_u->name; - notused. */
6340 /*      UNISTR2 *processor = &q_u->processor; - notused. */
6341         uint32 level = q_u->level;
6342         NEW_BUFFER *buffer = NULL;
6343         uint32 offered = q_u->offered;
6344         uint32 *needed = &r_u->needed;
6345         uint32 *returned = &r_u->returned;
6346
6347         /* that's an [in out] buffer */
6348         new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6349         buffer = r_u->buffer;
6350
6351         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6352         
6353         *returned=0;
6354         *needed=0;
6355         
6356         switch (level) {
6357         case 1:
6358                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6359         default:
6360                 return ERROR_INVALID_LEVEL;
6361         }
6362 }
6363
6364 /****************************************************************************
6365  enumprintmonitors level 1.
6366 ****************************************************************************/
6367
6368 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6369 {
6370         PRINTMONITOR_1 *info_1=NULL;
6371         
6372         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6373                 return ERROR_NOT_ENOUGH_MEMORY;
6374
6375         (*returned) = 0x1;
6376         
6377         init_unistr(&info_1->name, "Local Port");
6378
6379         *needed += spoolss_size_printmonitor_info_1(info_1);
6380
6381         if (!alloc_buffer_size(buffer, *needed))
6382                 return ERROR_INSUFFICIENT_BUFFER;
6383
6384         smb_io_printmonitor_info_1("", buffer, info_1, 0);
6385
6386         safe_free(info_1);
6387
6388         if (*needed > offered) {
6389                 *returned=0;
6390                 return ERROR_INSUFFICIENT_BUFFER;
6391         }
6392         else
6393                 return NT_STATUS_NO_PROBLEMO;
6394 }
6395
6396 /****************************************************************************
6397  enumprintmonitors level 2.
6398 ****************************************************************************/
6399 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6400 {
6401         PRINTMONITOR_2 *info_2=NULL;
6402         
6403         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6404                 return ERROR_NOT_ENOUGH_MEMORY;
6405
6406         (*returned) = 0x1;
6407         
6408         init_unistr(&info_2->name, "Local Port");
6409         init_unistr(&info_2->environment, "Windows NT X86");
6410         init_unistr(&info_2->dll_name, "localmon.dll");
6411
6412         *needed += spoolss_size_printmonitor_info_2(info_2);
6413
6414         if (!alloc_buffer_size(buffer, *needed))
6415                 return ERROR_INSUFFICIENT_BUFFER;
6416
6417         smb_io_printmonitor_info_2("", buffer, info_2, 0);
6418
6419         safe_free(info_2);
6420
6421         if (*needed > offered) {
6422                 *returned=0;
6423                 return ERROR_INSUFFICIENT_BUFFER;
6424         }
6425         else
6426                 return NT_STATUS_NO_PROBLEMO;
6427 }
6428
6429 /****************************************************************************
6430 ****************************************************************************/
6431
6432 uint32 _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6433 {
6434 /*      UNISTR2 *name = &q_u->name; - notused. */
6435         uint32 level = q_u->level;
6436     NEW_BUFFER *buffer = NULL;
6437         uint32 offered = q_u->offered;
6438     uint32 *needed = &r_u->needed;
6439         uint32 *returned = &r_u->returned;
6440
6441         /* that's an [in out] buffer */
6442         new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6443         buffer = r_u->buffer;
6444
6445         DEBUG(5,("spoolss_enumprintmonitors\n"));
6446
6447         /*
6448          * Enumerate the print monitors ...
6449          *
6450          * Just reply with "Local Port", to keep NT happy
6451          * and I can use my nice printer checker.
6452          */
6453         
6454         *returned=0;
6455         *needed=0;
6456         
6457         switch (level) {
6458         case 1:
6459                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6460         case 2:
6461                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6462         default:
6463                 return ERROR_INVALID_LEVEL;
6464         }
6465 }
6466
6467 /****************************************************************************
6468 ****************************************************************************/
6469 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6470 {
6471         int i=0;
6472         BOOL found=False;
6473         JOB_INFO_1 *info_1=NULL;
6474
6475         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6476
6477         if (info_1 == NULL) {
6478                 safe_free(queue);
6479                 return ERROR_NOT_ENOUGH_MEMORY;
6480         }
6481                 
6482         for (i=0; i<count && found==False; i++) {
6483                 if (queue[i].job==(int)jobid)
6484                         found=True;
6485         }
6486         
6487         if (found==False) {
6488                 safe_free(queue);
6489                 safe_free(info_1);
6490                 /* I shoud reply something else ... I can't find the good one */
6491                 return NT_STATUS_NO_PROBLEMO;
6492         }
6493         
6494         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6495         
6496         safe_free(queue);
6497         
6498         *needed += spoolss_size_job_info_1(info_1);
6499
6500         if (!alloc_buffer_size(buffer, *needed)) {
6501                 safe_free(info_1);
6502                 return ERROR_INSUFFICIENT_BUFFER;
6503         }
6504
6505         new_smb_io_job_info_1("", buffer, info_1, 0);
6506
6507         safe_free(info_1);
6508
6509         if (*needed > offered)
6510                 return ERROR_INSUFFICIENT_BUFFER;
6511         else
6512                 return NT_STATUS_NO_PROBLEMO;
6513 }
6514
6515
6516 /****************************************************************************
6517 ****************************************************************************/
6518 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6519 {
6520         int i=0;
6521         BOOL found=False;
6522         JOB_INFO_2 *info_2;
6523         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6524
6525         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6526
6527         ZERO_STRUCTP(info_2);
6528
6529         if (info_2 == NULL) {
6530                 safe_free(queue);
6531                 return ERROR_NOT_ENOUGH_MEMORY;
6532         }
6533
6534         for (i=0; i<count && found==False; i++) {
6535                 if (queue[i].job==(int)jobid)
6536                         found=True;
6537         }
6538         
6539         if (found==False) {
6540                 safe_free(queue);
6541                 safe_free(info_2);
6542                 /* I shoud reply something else ... I can't find the good one */
6543                 return NT_STATUS_NO_PROBLEMO;
6544         }
6545         
6546         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6547                 safe_free(queue);
6548                 return ERROR_NOT_ENOUGH_MEMORY;
6549         }
6550
6551         fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6552         
6553         free_a_printer(&ntprinter, 2);
6554         safe_free(queue);
6555         
6556         *needed += spoolss_size_job_info_2(info_2);
6557
6558         if (!alloc_buffer_size(buffer, *needed)) {
6559                 safe_free(info_2);
6560                 return ERROR_INSUFFICIENT_BUFFER;
6561         }
6562
6563         new_smb_io_job_info_2("", buffer, info_2, 0);
6564
6565         free_job_info_2(info_2);
6566         free(info_2);
6567
6568         if (*needed > offered)
6569                 return ERROR_INSUFFICIENT_BUFFER;
6570         else
6571                 return NT_STATUS_NO_PROBLEMO;
6572 }
6573
6574 /****************************************************************************
6575 ****************************************************************************/
6576
6577 uint32 _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6578 {
6579         POLICY_HND *handle = &q_u->handle;
6580         uint32 jobid = q_u->jobid;
6581         uint32 level = q_u->level;
6582         NEW_BUFFER *buffer = NULL;
6583         uint32 offered = q_u->offered;
6584         uint32 *needed = &r_u->needed;
6585
6586         int snum;
6587         int count;
6588         print_queue_struct *queue=NULL;
6589         print_status_struct prt_status;
6590
6591         /* that's an [in out] buffer */
6592         new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6593         buffer = r_u->buffer;
6594
6595         DEBUG(5,("spoolss_getjob\n"));
6596         
6597         memset(&prt_status, 0, sizeof(prt_status));
6598
6599         *needed=0;
6600         
6601         if (!get_printer_snum(handle, &snum))
6602                 return ERROR_INVALID_HANDLE;
6603         
6604         count = print_queue_status(snum, &queue, &prt_status);
6605         
6606         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6607                      count, prt_status.status, prt_status.message));
6608                 
6609         switch (level) {
6610         case 1:
6611                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6612         case 2:
6613                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6614         default:
6615                 safe_free(queue);
6616                 return ERROR_INVALID_LEVEL;
6617         }
6618 }
6619 #undef OLD_NTDOMAIN