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