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