2b41efcbf60844d7f10d92d2f67e0f6e912189fb
[ira/wip.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_pipe(); p; p = get_next_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 static void spoolss_notify_job_position(int snum, 
2015                                         SPOOL_NOTIFY_INFO_DATA *data,
2016                                         print_queue_struct *queue,
2017                                         NT_PRINTER_INFO_LEVEL *printer,
2018                                         TALLOC_CTX *mem_ctx)
2019 {
2020         data->notify_data.value[0]=queue->job;
2021         data->notify_data.value[1]=0;
2022 }
2023
2024 /*******************************************************************
2025  * fill a notify_info_data with submitted time
2026  ********************************************************************/
2027 static void spoolss_notify_submitted_time(int snum, 
2028                                           SPOOL_NOTIFY_INFO_DATA *data,
2029                                           print_queue_struct *queue,
2030                                           NT_PRINTER_INFO_LEVEL *printer,
2031                                           TALLOC_CTX *mem_ctx)
2032 {
2033         struct tm *t;
2034         uint32 len;
2035         SYSTEMTIME st;
2036
2037         t=gmtime(&queue->time);
2038
2039         len = sizeof(SYSTEMTIME);
2040
2041         data->notify_data.data.length = len;
2042         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2043
2044         if (!data->notify_data.data.string) {
2045                 data->notify_data.data.length = 0;
2046                 return;
2047         }
2048         
2049         make_systemtime(&st, t);
2050         memcpy(data->notify_data.data.string,&st,len);
2051 }
2052
2053 #define END 65535
2054
2055 struct s_notify_info_data_table
2056 {
2057         uint16 type;
2058         uint16 field;
2059         char *name;
2060         uint32 size;
2061         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2062                     print_queue_struct *queue,
2063                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2064 };
2065
2066 struct s_notify_info_data_table notify_info_data_table[] =
2067 {
2068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         POINTER,   spoolss_notify_server_name },
2069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        POINTER,   spoolss_notify_printer_name },
2070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          POINTER,   spoolss_notify_share_name },
2071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           POINTER,   spoolss_notify_port_name },
2072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         POINTER,   spoolss_notify_driver_name },
2073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             POINTER,   spoolss_notify_comment },
2074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            POINTER,   spoolss_notify_location },
2075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             POINTER,   spoolss_notify_devmode },
2076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             POINTER,   spoolss_notify_sepfile },
2077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     POINTER,   spoolss_notify_print_processor },
2078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          POINTER,   spoolss_notify_parameters },
2079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            POINTER,   spoolss_notify_datatype },
2080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER,   spoolss_notify_security_desc },
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          ONE_VALUE, spoolss_notify_attributes },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            ONE_VALUE, spoolss_notify_priority },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    ONE_VALUE, spoolss_notify_default_priority },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          ONE_VALUE, spoolss_notify_start_time },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          ONE_VALUE, spoolss_notify_until_time },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              ONE_VALUE, spoolss_notify_status },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       POINTER,   NULL },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               ONE_VALUE, spoolss_notify_cjobs },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         ONE_VALUE, spoolss_notify_average_ppm },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         POINTER,   NULL },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       POINTER,   NULL },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         POINTER,   NULL },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       POINTER,   NULL },
2094 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            POINTER,   spoolss_notify_printer_name },
2095 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            POINTER,   spoolss_notify_server_name },
2096 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               POINTER,   spoolss_notify_port_name },
2097 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               POINTER,   spoolss_notify_username },
2098 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             POINTER,   spoolss_notify_username },
2099 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                POINTER,   spoolss_notify_datatype },
2100 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         POINTER,   spoolss_notify_print_processor },
2101 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              POINTER,   spoolss_notify_parameters },
2102 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             POINTER,   spoolss_notify_driver_name },
2103 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 POINTER,   spoolss_notify_devmode },
2104 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  ONE_VALUE, spoolss_notify_job_status },
2105 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           POINTER,   spoolss_notify_job_status_string },
2106 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     POINTER,   NULL },
2107 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                POINTER,   spoolss_notify_job_name },
2108 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                ONE_VALUE, spoolss_notify_priority },
2109 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                ONE_VALUE, spoolss_notify_job_position },
2110 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               POINTER,   spoolss_notify_submitted_time },
2111 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              ONE_VALUE, spoolss_notify_start_time },
2112 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              ONE_VALUE, spoolss_notify_until_time },
2113 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    ONE_VALUE, spoolss_notify_job_time },
2114 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             ONE_VALUE, NULL },
2115 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           ONE_VALUE, NULL },
2116 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             ONE_VALUE, spoolss_notify_job_size },
2117 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_BYTES_PRINTED,           "JOB_NOTIFY_BYTES_PRINTED",           ONE_VALUE, NULL },
2118 { END,                 END,                                "",                                   END,       NULL }
2119 };
2120
2121 /*******************************************************************
2122 return the size of info_data structure
2123 ********************************************************************/
2124 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2125 {
2126         int i=0;
2127
2128         while (notify_info_data_table[i].type != END)
2129         {
2130                 if ( (notify_info_data_table[i].type == type ) &&
2131                      (notify_info_data_table[i].field == field ) )
2132                 {
2133                         return (notify_info_data_table[i].size);
2134                 }
2135                 i++;
2136         }
2137         return (65535);
2138 }
2139
2140 /*******************************************************************
2141 return the type of notify_info_data
2142 ********************************************************************/
2143 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2144 {
2145         int i=0;
2146
2147         while (notify_info_data_table[i].type != END)
2148         {
2149                 if ( (notify_info_data_table[i].type == type ) &&
2150                      (notify_info_data_table[i].field == field ) )
2151                 {
2152                         if (notify_info_data_table[i].size == POINTER)
2153                         {
2154                                 return (False);
2155                         }
2156                         else
2157                         {
2158                                 return (True);
2159                         }
2160                 }
2161                 i++;
2162         }
2163         return (False);
2164 }
2165
2166 /****************************************************************************
2167 ****************************************************************************/
2168 static int search_notify(uint16 type, uint16 field, int *value)
2169 {       
2170         int j;
2171         BOOL found;
2172
2173         for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2174         {
2175                 if ( (notify_info_data_table[j].type  == type  ) &&
2176                      (notify_info_data_table[j].field == field ) )
2177                         found=True;
2178         }
2179         *value=--j;
2180
2181         if ( found && (notify_info_data_table[j].fn != NULL) )
2182                 return True;
2183         else
2184                 return False;   
2185 }
2186
2187 /****************************************************************************
2188 ****************************************************************************/
2189 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2190 {
2191         info_data->type     = type;
2192         info_data->field    = field;
2193         info_data->reserved = 0;
2194         info_data->id       = id;
2195         info_data->size     = size_of_notify_info_data(type, field);
2196         info_data->enc_type = type_of_notify_info_data(type, field);
2197 }
2198
2199
2200 /*******************************************************************
2201  *
2202  * fill a notify_info struct with info asked
2203  *
2204  ********************************************************************/
2205 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2206                                           snum, SPOOL_NOTIFY_OPTION_TYPE
2207                                           *option_type, uint32 id,
2208                                           TALLOC_CTX *mem_ctx) 
2209 {
2210         int field_num,j;
2211         uint16 type;
2212         uint16 field;
2213
2214         SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2215         NT_PRINTER_INFO_LEVEL *printer = NULL;
2216         print_queue_struct *queue=NULL;
2217
2218         type=option_type->type;
2219
2220         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2221                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2222                 option_type->count, lp_servicename(snum)));
2223         
2224         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2225                 return False;
2226
2227         for(field_num=0; field_num<option_type->count; field_num++) {
2228                 field = option_type->fields[field_num];
2229                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2230
2231                 if (!search_notify(type, field, &j) )
2232                         continue;
2233
2234                 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2235                         DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2236                         return False;
2237                 }
2238                 else info->data = tid;
2239
2240                 current_data=&info->data[info->count];
2241
2242                 construct_info_data(current_data, type, field, id);             
2243
2244                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
2245                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2246
2247                 notify_info_data_table[j].fn(snum, current_data, queue,
2248                                              printer, mem_ctx);
2249
2250                 info->count++;
2251         }
2252
2253         free_a_printer(&printer, 2);
2254         return True;
2255 }
2256
2257 /*******************************************************************
2258  *
2259  * fill a notify_info struct with info asked
2260  *
2261  ********************************************************************/
2262 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2263                                        SPOOL_NOTIFY_INFO *info,
2264                                        NT_PRINTER_INFO_LEVEL *printer,
2265                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
2266                                        *option_type, uint32 id,
2267                                        TALLOC_CTX *mem_ctx) 
2268 {
2269         int field_num,j;
2270         uint16 type;
2271         uint16 field;
2272
2273         SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2274         
2275         DEBUG(4,("construct_notify_jobs_info\n"));
2276         
2277         type = option_type->type;
2278
2279         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2280                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2281                 option_type->count));
2282
2283         for(field_num=0; field_num<option_type->count; field_num++) {
2284                 field = option_type->fields[field_num];
2285
2286                 if (!search_notify(type, field, &j) )
2287                         continue;
2288
2289                 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2290                         DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2291                         return False;
2292                 }
2293                 else info->data = tid;
2294
2295                 current_data=&(info->data[info->count]);
2296
2297                 construct_info_data(current_data, type, field, id);
2298                 notify_info_data_table[j].fn(snum, current_data, queue,
2299                                              printer, mem_ctx);
2300                 info->count++;
2301         }
2302
2303         return True;
2304 }
2305
2306 /*
2307  * JFM: The enumeration is not that simple, it's even non obvious.
2308  *
2309  * let's take an example: I want to monitor the PRINTER SERVER for
2310  * the printer's name and the number of jobs currently queued.
2311  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2312  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2313  *
2314  * I have 3 printers on the back of my server.
2315  *
2316  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2317  * structures.
2318  *   Number     Data                    Id
2319  *      1       printer 1 name          1
2320  *      2       printer 1 cjob          1
2321  *      3       printer 2 name          2
2322  *      4       printer 2 cjob          2
2323  *      5       printer 3 name          3
2324  *      6       printer 3 name          3
2325  *
2326  * that's the print server case, the printer case is even worse.
2327  */
2328
2329 /*******************************************************************
2330  *
2331  * enumerate all printers on the printserver
2332  * fill a notify_info struct with info asked
2333  *
2334  ********************************************************************/
2335
2336 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, 
2337                                       SPOOL_NOTIFY_INFO *info,
2338                                       TALLOC_CTX *mem_ctx)
2339 {
2340         int snum;
2341         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2342         int n_services=lp_numservices();
2343         int i;
2344         uint32 id;
2345         SPOOL_NOTIFY_OPTION *option;
2346         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2347
2348         DEBUG(4,("printserver_notify_info\n"));
2349         
2350         option=Printer->notify.option;
2351         id=1;
2352         info->version=2;
2353         info->data=NULL;
2354         info->count=0;
2355
2356         for (i=0; i<option->count; i++) {
2357                 option_type=&(option->ctr.type[i]);
2358                 
2359                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2360                         continue;
2361                 
2362                 for (snum=0; snum<n_services; snum++)
2363                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2364                                 if (construct_notify_printer_info
2365                                     (info, snum, option_type, id, mem_ctx))
2366                                         id++;
2367         }
2368                         
2369         /*
2370          * Debugging information, don't delete.
2371          */
2372         /*
2373         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2374         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2375         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2376         
2377         for (i=0; i<info->count; i++) {
2378                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2379                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2380                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2381         }
2382         */
2383         
2384         return WERR_OK;
2385 }
2386
2387 /*******************************************************************
2388  *
2389  * fill a notify_info struct with info asked
2390  *
2391  ********************************************************************/
2392 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2393                                   TALLOC_CTX *mem_ctx)
2394 {
2395         int snum;
2396         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2397         int i;
2398         uint32 id;
2399         SPOOL_NOTIFY_OPTION *option;
2400         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2401         int count,j;
2402         print_queue_struct *queue=NULL;
2403         print_status_struct status;
2404         
2405         DEBUG(4,("printer_notify_info\n"));
2406
2407         option=Printer->notify.option;
2408         id=0xffffffff;
2409         info->version=2;
2410         info->data=NULL;
2411         info->count=0;
2412
2413         get_printer_snum(p, hnd, &snum);
2414
2415         for (i=0; i<option->count; i++) {
2416                 option_type=&option->ctr.type[i];
2417                 
2418                 switch ( option_type->type ) {
2419                 case PRINTER_NOTIFY_TYPE:
2420                         if(construct_notify_printer_info(info, snum, 
2421                                                          option_type, id,
2422                                                          mem_ctx))  
2423                                 id--;
2424                         break;
2425                         
2426                 case JOB_NOTIFY_TYPE: {
2427                         NT_PRINTER_INFO_LEVEL *printer = NULL;
2428
2429                         count = print_queue_status(snum, &queue, &status);
2430
2431                         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, 
2432                                                          lp_servicename(snum))))
2433                                 goto done;
2434
2435                         for (j=0; j<count; j++) {
2436                                 construct_notify_jobs_info(&queue[j], info,
2437                                                            printer, snum,
2438                                                            option_type,
2439                                                            queue[j].job,
2440                                                            mem_ctx); 
2441                         }
2442
2443                         free_a_printer(&printer, 2);
2444                         
2445                 done:
2446                         SAFE_FREE(queue);
2447                         break;
2448                 }
2449                 }
2450         }
2451         
2452         /*
2453          * Debugging information, don't delete.
2454          */
2455         /*
2456         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2457         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2458         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2459         
2460         for (i=0; i<info->count; i++) {
2461                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2462                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2463                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2464         }
2465         */
2466         return WERR_OK;
2467 }
2468
2469 /********************************************************************
2470  * spoolss_rfnpcnex
2471  ********************************************************************/
2472
2473 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2474 {
2475         POLICY_HND *handle = &q_u->handle;
2476 /*      uint32 change = q_u->change; - notused. */
2477 /*      SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2478         SPOOL_NOTIFY_INFO *info = &r_u->info;
2479
2480         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2481         WERROR result = WERR_BADFID;
2482
2483         /* we always have a NOTIFY_INFO struct */
2484         r_u->info_ptr=0x1;
2485
2486         if (!Printer) {
2487                 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2488                          OUR_HANDLE(handle)));
2489                 goto done;
2490         }
2491
2492         DEBUG(4,("Printer type %x\n",Printer->printer_type));
2493
2494         /* jfm: the change value isn't used right now.
2495          *      we will honour it when
2496          *      a) we'll be able to send notification to the client
2497          *      b) we'll have a way to communicate between the spoolss process.
2498          *
2499          *      same thing for option->flags
2500          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2501          *      I don't have a global notification system, I'm sending back all the
2502          *      informations even when _NOTHING_ has changed.
2503          */
2504
2505         /* just ignore the SPOOL_NOTIFY_OPTION */
2506         
2507         switch (Printer->printer_type) {
2508                 case PRINTER_HANDLE_IS_PRINTSERVER:
2509                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
2510                         break;
2511                         
2512                 case PRINTER_HANDLE_IS_PRINTER:
2513                         result = printer_notify_info(p, handle, info, p->mem_ctx);
2514                         break;
2515         }
2516         
2517  done:
2518         return result;
2519 }
2520
2521 /********************************************************************
2522  * construct_printer_info_0
2523  * fill a printer_info_0 struct
2524  ********************************************************************/
2525 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2526 {
2527         pstring chaine;
2528         int count;
2529         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2530         counter_printer_0 *session_counter;
2531         uint32 global_counter;
2532         struct tm *t;
2533         time_t setuptime;
2534         print_status_struct status;
2535         
2536         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2537                 return False;
2538
2539         count = print_queue_length(snum, &status);
2540
2541         /* check if we already have a counter for this printer */       
2542         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2543
2544         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2545                 if (session_counter->snum == snum)
2546                         break;
2547         }
2548
2549         /* it's the first time, add it to the list */
2550         if (session_counter==NULL) {
2551                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2552                         free_a_printer(&ntprinter, 2);
2553                         return False;
2554                 }
2555                 ZERO_STRUCTP(session_counter);
2556                 session_counter->snum=snum;
2557                 session_counter->counter=0;
2558                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2559         }
2560         
2561         /* increment it */
2562         session_counter->counter++;
2563         
2564         /* JFM:
2565          * the global_counter should be stored in a TDB as it's common to all the clients
2566          * and should be zeroed on samba startup
2567          */
2568         global_counter=session_counter->counter;
2569         
2570         pstrcpy(chaine,ntprinter->info_2->printername);
2571
2572         init_unistr(&printer->printername, chaine);
2573         
2574         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2575         init_unistr(&printer->servername, chaine);
2576         
2577         printer->cjobs = count;
2578         printer->total_jobs = 0;
2579         printer->total_bytes = 0;
2580
2581         setuptime = (time_t)ntprinter->info_2->setuptime;
2582         t=gmtime(&setuptime);
2583
2584         printer->year = t->tm_year+1900;
2585         printer->month = t->tm_mon+1;
2586         printer->dayofweek = t->tm_wday;
2587         printer->day = t->tm_mday;
2588         printer->hour = t->tm_hour;
2589         printer->minute = t->tm_min;
2590         printer->second = t->tm_sec;
2591         printer->milliseconds = 0;
2592
2593         printer->global_counter = global_counter;
2594         printer->total_pages = 0;
2595         printer->major_version = 0x0004;        /* NT 4 */
2596         printer->build_version = 0x0565;        /* build 1381 */
2597         printer->unknown7 = 0x1;
2598         printer->unknown8 = 0x0;
2599         printer->unknown9 = 0x0;
2600         printer->session_counter = session_counter->counter;
2601         printer->unknown11 = 0x0;
2602         printer->printer_errors = 0x0;          /* number of print failure */
2603         printer->unknown13 = 0x0;
2604         printer->unknown14 = 0x1;
2605         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
2606         printer->unknown16 =  0x0;
2607         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2608         printer->unknown18 =  0x0;
2609         printer->status = nt_printq_status(status.status);
2610         printer->unknown20 =  0x0;
2611         printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2612         printer->unknown22 = 0x0;
2613         printer->unknown23 = 0x6;               /* 6  ???*/
2614         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
2615         printer->unknown25 = 0;
2616         printer->unknown26 = 0;
2617         printer->unknown27 = 0;
2618         printer->unknown28 = 0;
2619         printer->unknown29 = 0;
2620         
2621         free_a_printer(&ntprinter,2);
2622         return (True);  
2623 }
2624
2625 /********************************************************************
2626  * construct_printer_info_1
2627  * fill a printer_info_1 struct
2628  ********************************************************************/
2629 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2630 {
2631         pstring chaine;
2632         pstring chaine2;
2633         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2634
2635         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2636                 return False;
2637
2638         printer->flags=flags;
2639
2640         if (*ntprinter->info_2->comment == '\0') {
2641                 init_unistr(&printer->comment, lp_comment(snum));
2642                 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2643                         ntprinter->info_2->drivername, lp_comment(snum));
2644         }
2645         else {
2646                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2647                 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2648                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
2649         }
2650                 
2651         slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2652
2653         init_unistr(&printer->description, chaine);
2654         init_unistr(&printer->name, chaine2);   
2655         
2656         free_a_printer(&ntprinter,2);
2657
2658         return True;
2659 }
2660
2661 /****************************************************************************
2662  Free a DEVMODE struct.
2663 ****************************************************************************/
2664
2665 static void free_dev_mode(DEVICEMODE *dev)
2666 {
2667         if (dev == NULL)
2668                 return;
2669
2670         SAFE_FREE(dev->private);
2671         SAFE_FREE(dev); 
2672 }
2673
2674 /****************************************************************************
2675  Create a DEVMODE struct. Returns malloced memory.
2676 ****************************************************************************/
2677
2678 static DEVICEMODE *construct_dev_mode(int snum)
2679 {
2680         char adevice[32];
2681         char aform[32];
2682         NT_PRINTER_INFO_LEVEL *printer = NULL;
2683         NT_DEVICEMODE *ntdevmode = NULL;
2684         DEVICEMODE *devmode = NULL;
2685
2686         DEBUG(7,("construct_dev_mode\n"));
2687         
2688         DEBUGADD(8,("getting printer characteristics\n"));
2689
2690         if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2691                 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2692                 return NULL;
2693         }
2694
2695         ZERO_STRUCTP(devmode);  
2696
2697         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2698                 goto fail;
2699
2700         if (printer->info_2->devmode)
2701                 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2702
2703         if (ntdevmode == NULL)
2704                 goto fail;
2705
2706         DEBUGADD(8,("loading DEVICEMODE\n"));
2707
2708         slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2709         init_unistr(&devmode->devicename, adevice);
2710
2711         slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2712         init_unistr(&devmode->formname, aform);
2713
2714         devmode->specversion      = ntdevmode->specversion;
2715         devmode->driverversion    = ntdevmode->driverversion;
2716         devmode->size             = ntdevmode->size;
2717         devmode->driverextra      = ntdevmode->driverextra;
2718         devmode->fields           = ntdevmode->fields;
2719                                 
2720         devmode->orientation      = ntdevmode->orientation;     
2721         devmode->papersize        = ntdevmode->papersize;
2722         devmode->paperlength      = ntdevmode->paperlength;
2723         devmode->paperwidth       = ntdevmode->paperwidth;
2724         devmode->scale            = ntdevmode->scale;
2725         devmode->copies           = ntdevmode->copies;
2726         devmode->defaultsource    = ntdevmode->defaultsource;
2727         devmode->printquality     = ntdevmode->printquality;
2728         devmode->color            = ntdevmode->color;
2729         devmode->duplex           = ntdevmode->duplex;
2730         devmode->yresolution      = ntdevmode->yresolution;
2731         devmode->ttoption         = ntdevmode->ttoption;
2732         devmode->collate          = ntdevmode->collate;
2733         devmode->icmmethod        = ntdevmode->icmmethod;
2734         devmode->icmintent        = ntdevmode->icmintent;
2735         devmode->mediatype        = ntdevmode->mediatype;
2736         devmode->dithertype       = ntdevmode->dithertype;
2737
2738         if (ntdevmode->private != NULL) {
2739                 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2740                         goto fail;
2741         }
2742
2743         free_nt_devicemode(&ntdevmode);
2744         free_a_printer(&printer,2);
2745
2746         return devmode;
2747
2748   fail:
2749
2750         if (ntdevmode)
2751                 free_nt_devicemode(&ntdevmode);
2752         if (printer)
2753                 free_a_printer(&printer,2);
2754         free_dev_mode(devmode);
2755
2756         return NULL;
2757 }
2758
2759 /********************************************************************
2760  * construct_printer_info_2
2761  * fill a printer_info_2 struct
2762  ********************************************************************/
2763
2764 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2765 {
2766         int count;
2767         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2768
2769         print_status_struct status;
2770
2771         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2772                 return False;
2773                 
2774         count = print_queue_length(snum, &status);
2775
2776         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2777         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2778         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
2779         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
2780         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
2781
2782         if (*ntprinter->info_2->comment == '\0')
2783                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
2784         else
2785                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2786
2787         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
2788         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
2789         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2790         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
2791         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
2792
2793         printer->attributes = ntprinter->info_2->attributes;
2794
2795         printer->priority = ntprinter->info_2->priority;                                /* priority */  
2796         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
2797         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
2798         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
2799         printer->status = nt_printq_status(status.status);                      /* status */
2800         printer->cjobs = count;                                                 /* jobs */
2801         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
2802                         
2803         if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2804                 DEBUG(8, ("Returning NULL Devicemode!\n"));
2805         }
2806
2807         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2808                 /* steal the printer info sec_desc structure.  [badly done]. */
2809                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2810                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2811                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2812                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2813         }
2814         else {
2815                 printer->secdesc = NULL;
2816         }
2817
2818         free_a_printer(&ntprinter, 2);
2819         return True;
2820 }
2821
2822 /********************************************************************
2823  * construct_printer_info_3
2824  * fill a printer_info_3 struct
2825  ********************************************************************/
2826 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2827 {
2828         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2829         PRINTER_INFO_3 *printer = NULL;
2830
2831         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2832                 return False;
2833
2834         *pp_printer = NULL;
2835         if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2836                 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2837                 return False;
2838         }
2839
2840         ZERO_STRUCTP(printer);
2841         
2842         printer->flags = 4; /* These are the components of the SD we are returning. */
2843         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2844                 /* steal the printer info sec_desc structure.  [badly done]. */
2845                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2846
2847 #if 0
2848                 /*
2849                  * Set the flags for the components we are returning.
2850                  */
2851
2852                 if (printer->secdesc->owner_sid)
2853                         printer->flags |= OWNER_SECURITY_INFORMATION;
2854
2855                 if (printer->secdesc->grp_sid)
2856                         printer->flags |= GROUP_SECURITY_INFORMATION;
2857
2858                 if (printer->secdesc->dacl)
2859                         printer->flags |= DACL_SECURITY_INFORMATION;
2860
2861                 if (printer->secdesc->sacl)
2862                         printer->flags |= SACL_SECURITY_INFORMATION;
2863 #endif
2864
2865                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2866                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2867                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2868         }
2869
2870         free_a_printer(&ntprinter, 2);
2871
2872         *pp_printer = printer;
2873         return True;
2874 }
2875
2876 /********************************************************************
2877  * construct_printer_info_4
2878  * fill a printer_info_4 struct
2879  ********************************************************************/
2880
2881 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
2882 {
2883         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2884
2885         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2886                 return False;
2887                 
2888         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2889         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2890         printer->attributes = ntprinter->info_2->attributes;
2891
2892         free_a_printer(&ntprinter, 2);
2893         return True;
2894 }
2895
2896 /********************************************************************
2897  * construct_printer_info_5
2898  * fill a printer_info_5 struct
2899  ********************************************************************/
2900
2901 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
2902 {
2903         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2904
2905         if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2906                 return False;
2907                 
2908         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2909         init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
2910         printer->attributes = ntprinter->info_2->attributes;
2911         printer->device_not_selected_timeout = 0x3a98;
2912         printer->transmission_retry_timeout = 0xafc8;
2913
2914         free_a_printer(&ntprinter, 2);
2915         return True;
2916 }
2917
2918
2919 /********************************************************************
2920  Spoolss_enumprinters.
2921 ********************************************************************/
2922 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2923 {
2924         int snum;
2925         int i;
2926         int n_services=lp_numservices();
2927         PRINTER_INFO_1 *tp, *printers=NULL;
2928         PRINTER_INFO_1 current_prt;
2929         
2930         DEBUG(4,("enum_all_printers_info_1\n"));        
2931
2932         for (snum=0; snum<n_services; snum++) {
2933                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2934                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2935                                 
2936                         if (construct_printer_info_1(flags, &current_prt, snum)) {
2937                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2938                                         DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2939                                         SAFE_FREE(printers);
2940                                         *returned=0;
2941                                         return WERR_NOMEM;
2942                                 }
2943                                 else printers = tp;
2944                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
2945                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2946                                 (*returned)++;
2947                         }
2948                 }
2949         }
2950                 
2951         /* check the required size. */  
2952         for (i=0; i<*returned; i++)
2953                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2954
2955         if (!alloc_buffer_size(buffer, *needed))
2956                 return WERR_INSUFFICIENT_BUFFER;
2957
2958         /* fill the buffer with the structures */
2959         for (i=0; i<*returned; i++)
2960                 smb_io_printer_info_1("", buffer, &printers[i], 0);     
2961
2962         /* clear memory */
2963         SAFE_FREE(printers);
2964
2965         if (*needed > offered) {
2966                 *returned=0;
2967                 return WERR_INSUFFICIENT_BUFFER;
2968         }
2969         else
2970                 return WERR_OK;
2971 }
2972
2973 /********************************************************************
2974  enum_all_printers_info_1_local.
2975 *********************************************************************/
2976 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2977 {
2978         DEBUG(4,("enum_all_printers_info_1_local\n"));  
2979         
2980         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2981 }
2982
2983 /********************************************************************
2984  enum_all_printers_info_1_name.
2985 *********************************************************************/
2986 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2987 {
2988         char *s = name;
2989         
2990         DEBUG(4,("enum_all_printers_info_1_name\n"));   
2991         
2992         if ((name[0] == '\\') && (name[1] == '\\'))
2993                 s = name + 2;
2994
2995         if (is_myname_or_ipaddr(s)) {
2996                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2997         }
2998         else
2999                 return WERR_INVALID_NAME;
3000 }
3001
3002 /********************************************************************
3003  enum_all_printers_info_1_remote.
3004 *********************************************************************/
3005 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3006 {
3007         PRINTER_INFO_1 *printer;
3008         fstring printername;
3009         fstring desc;
3010         fstring comment;
3011         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
3012
3013         /* JFM: currently it's more a place holder than anything else.
3014          * In the spooler world there is a notion of server registration.
3015          * the print servers are registring (sp ?) on the PDC (in the same domain)
3016          *
3017          * We should have a TDB here. The registration is done thru an undocumented RPC call.
3018          */
3019         
3020         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3021                 return WERR_NOMEM;
3022
3023         *returned=1;
3024         
3025         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());           
3026         slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3027         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3028
3029         init_unistr(&printer->description, desc);
3030         init_unistr(&printer->name, printername);       
3031         init_unistr(&printer->comment, comment);
3032         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3033                 
3034         /* check the required size. */  
3035         *needed += spoolss_size_printer_info_1(printer);
3036
3037         if (!alloc_buffer_size(buffer, *needed)) {
3038                 SAFE_FREE(printer);
3039                 return WERR_INSUFFICIENT_BUFFER;
3040         }
3041
3042         /* fill the buffer with the structures */
3043         smb_io_printer_info_1("", buffer, printer, 0);  
3044
3045         /* clear memory */
3046         SAFE_FREE(printer);
3047
3048         if (*needed > offered) {
3049                 *returned=0;
3050                 return WERR_INSUFFICIENT_BUFFER;
3051         }
3052         else
3053                 return WERR_OK;
3054 }
3055
3056 /********************************************************************
3057  enum_all_printers_info_1_network.
3058 *********************************************************************/
3059
3060 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3061 {
3062         DEBUG(4,("enum_all_printers_info_1_network\n"));        
3063         
3064         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3065 }
3066
3067 /********************************************************************
3068  * api_spoolss_enumprinters
3069  *
3070  * called from api_spoolss_enumprinters (see this to understand)
3071  ********************************************************************/
3072
3073 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3074 {
3075         int snum;
3076         int i;
3077         int n_services=lp_numservices();
3078         PRINTER_INFO_2 *tp, *printers=NULL;
3079         PRINTER_INFO_2 current_prt;
3080
3081         for (snum=0; snum<n_services; snum++) {
3082                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3083                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3084                                 
3085                         if (construct_printer_info_2(&current_prt, snum)) {
3086                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3087                                         DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3088                                         SAFE_FREE(printers);
3089                                         *returned = 0;
3090                                         return WERR_NOMEM;
3091                                 }
3092                                 else printers = tp;
3093                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
3094                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3095                                 (*returned)++;
3096                         }
3097                 }
3098         }
3099         
3100         /* check the required size. */  
3101         for (i=0; i<*returned; i++)
3102                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3103
3104         if (!alloc_buffer_size(buffer, *needed)) {
3105                 for (i=0; i<*returned; i++) {
3106                         free_devmode(printers[i].devmode);
3107                 }
3108                 SAFE_FREE(printers);
3109                 return WERR_INSUFFICIENT_BUFFER;
3110         }
3111
3112         /* fill the buffer with the structures */
3113         for (i=0; i<*returned; i++)
3114                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);   
3115         
3116         /* clear memory */
3117         for (i=0; i<*returned; i++) {
3118                 free_devmode(printers[i].devmode);
3119         }
3120         SAFE_FREE(printers);
3121
3122         if (*needed > offered) {
3123                 *returned=0;
3124                 return WERR_INSUFFICIENT_BUFFER;
3125         }
3126         else
3127                 return WERR_OK;
3128 }
3129
3130 /********************************************************************
3131  * handle enumeration of printers at level 1
3132  ********************************************************************/
3133 static WERROR enumprinters_level1( uint32 flags, fstring name,
3134                                  NEW_BUFFER *buffer, uint32 offered,
3135                                  uint32 *needed, uint32 *returned)
3136 {
3137         /* Not all the flags are equals */
3138
3139         if (flags & PRINTER_ENUM_LOCAL)
3140                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3141
3142         if (flags & PRINTER_ENUM_NAME)
3143                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3144
3145         if (flags & PRINTER_ENUM_REMOTE)
3146                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3147
3148         if (flags & PRINTER_ENUM_NETWORK)
3149                 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3150
3151         return WERR_OK; /* NT4sp5 does that */
3152 }
3153
3154 /********************************************************************
3155  * handle enumeration of printers at level 2
3156  ********************************************************************/
3157 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3158                                  NEW_BUFFER *buffer, uint32 offered,
3159                                  uint32 *needed, uint32 *returned)
3160 {
3161         char *s = servername;
3162
3163         if (flags & PRINTER_ENUM_LOCAL) {
3164                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3165         }
3166
3167         if (flags & PRINTER_ENUM_NAME) {
3168                 if ((servername[0] == '\\') && (servername[1] == '\\'))
3169                         s = servername + 2;
3170                 if (is_myname_or_ipaddr(s))
3171                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3172                 else
3173                         return WERR_INVALID_NAME;
3174         }
3175
3176         if (flags & PRINTER_ENUM_REMOTE)
3177                 return WERR_UNKNOWN_LEVEL;
3178
3179         return WERR_OK;
3180 }
3181
3182 /********************************************************************
3183  * handle enumeration of printers at level 5
3184  ********************************************************************/
3185 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3186                                  NEW_BUFFER *buffer, uint32 offered,
3187                                  uint32 *needed, uint32 *returned)
3188 {
3189 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3190         return WERR_OK;
3191 }
3192
3193 /********************************************************************
3194  * api_spoolss_enumprinters
3195  *
3196  * called from api_spoolss_enumprinters (see this to understand)
3197  ********************************************************************/
3198
3199 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3200 {
3201         uint32 flags = q_u->flags;
3202         UNISTR2 *servername = &q_u->servername;
3203         uint32 level = q_u->level;
3204         NEW_BUFFER *buffer = NULL;
3205         uint32 offered = q_u->offered;
3206         uint32 *needed = &r_u->needed;
3207         uint32 *returned = &r_u->returned;
3208
3209         fstring name;
3210         
3211         /* that's an [in out] buffer */
3212         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3213         buffer = r_u->buffer;
3214
3215         DEBUG(4,("_spoolss_enumprinters\n"));
3216
3217         *needed=0;
3218         *returned=0;
3219         
3220         /*
3221          * Level 1:
3222          *          flags==PRINTER_ENUM_NAME
3223          *           if name=="" then enumerates all printers
3224          *           if name!="" then enumerate the printer
3225          *          flags==PRINTER_ENUM_REMOTE
3226          *          name is NULL, enumerate printers
3227          * Level 2: name!="" enumerates printers, name can't be NULL
3228          * Level 3: doesn't exist
3229          * Level 4: does a local registry lookup
3230          * Level 5: same as Level 2
3231          */
3232
3233         unistr2_to_ascii(name, servername, sizeof(name)-1);
3234         strupper(name);
3235
3236         switch (level) {
3237         case 1:
3238                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3239         case 2:
3240                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3241         case 5:
3242                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3243         case 3:
3244         case 4:
3245                 break;
3246         }
3247         return WERR_UNKNOWN_LEVEL;
3248 }
3249
3250 /****************************************************************************
3251 ****************************************************************************/
3252 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3253 {
3254         PRINTER_INFO_0 *printer=NULL;
3255
3256         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3257                 return WERR_NOMEM;
3258
3259         construct_printer_info_0(printer, snum);
3260         
3261         /* check the required size. */  
3262         *needed += spoolss_size_printer_info_0(printer);
3263
3264         if (!alloc_buffer_size(buffer, *needed)) {
3265                 SAFE_FREE(printer);
3266                 return WERR_INSUFFICIENT_BUFFER;
3267         }
3268
3269         /* fill the buffer with the structures */
3270         smb_io_printer_info_0("", buffer, printer, 0);  
3271         
3272         /* clear memory */
3273         SAFE_FREE(printer);
3274
3275         if (*needed > offered) {
3276                 return WERR_INSUFFICIENT_BUFFER;
3277         }
3278
3279         return WERR_OK;
3280 }
3281
3282 /****************************************************************************
3283 ****************************************************************************/
3284 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3285 {
3286         PRINTER_INFO_1 *printer=NULL;
3287
3288         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3289                 return WERR_NOMEM;
3290
3291         construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3292         
3293         /* check the required size. */  
3294         *needed += spoolss_size_printer_info_1(printer);
3295
3296         if (!alloc_buffer_size(buffer, *needed)) {
3297                 SAFE_FREE(printer);
3298                 return WERR_INSUFFICIENT_BUFFER;
3299         }
3300
3301         /* fill the buffer with the structures */
3302         smb_io_printer_info_1("", buffer, printer, 0);  
3303         
3304         /* clear memory */
3305         SAFE_FREE(printer);
3306
3307         if (*needed > offered) {
3308                 return WERR_INSUFFICIENT_BUFFER;
3309         }
3310
3311         return WERR_OK; 
3312 }
3313
3314 /****************************************************************************
3315 ****************************************************************************/
3316 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3317 {
3318         PRINTER_INFO_2 *printer=NULL;
3319
3320         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3321                 return WERR_NOMEM;
3322         
3323         construct_printer_info_2(printer, snum);
3324         
3325         /* check the required size. */  
3326         *needed += spoolss_size_printer_info_2(printer);
3327
3328         if (!alloc_buffer_size(buffer, *needed)) {
3329                 free_printer_info_2(printer);
3330                 return WERR_INSUFFICIENT_BUFFER;
3331         }
3332
3333         /* fill the buffer with the structures */
3334         if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3335                 free_printer_info_2(printer);
3336                 return WERR_NOMEM;
3337         }
3338         
3339         /* clear memory */
3340         free_printer_info_2(printer);
3341
3342         if (*needed > offered) {
3343                 return WERR_INSUFFICIENT_BUFFER;
3344         }
3345
3346         return WERR_OK; 
3347 }
3348
3349 /****************************************************************************
3350 ****************************************************************************/
3351 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3352 {
3353         PRINTER_INFO_3 *printer=NULL;
3354
3355         if (!construct_printer_info_3(&printer, snum))
3356                 return WERR_NOMEM;
3357         
3358         /* check the required size. */  
3359         *needed += spoolss_size_printer_info_3(printer);
3360
3361         if (!alloc_buffer_size(buffer, *needed)) {
3362                 free_printer_info_3(printer);
3363                 return WERR_INSUFFICIENT_BUFFER;
3364         }
3365
3366         /* fill the buffer with the structures */
3367         smb_io_printer_info_3("", buffer, printer, 0);  
3368         
3369         /* clear memory */
3370         free_printer_info_3(printer);
3371         
3372         if (*needed > offered) {
3373                 return WERR_INSUFFICIENT_BUFFER;
3374         }
3375
3376         return WERR_OK; 
3377 }
3378
3379 /****************************************************************************
3380 ****************************************************************************/
3381 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3382 {
3383         PRINTER_INFO_4 *printer=NULL;
3384
3385         if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3386                 return WERR_NOMEM;
3387
3388         if (!construct_printer_info_4(printer, snum))
3389                 return WERR_NOMEM;
3390         
3391         /* check the required size. */  
3392         *needed += spoolss_size_printer_info_4(printer);
3393
3394         if (!alloc_buffer_size(buffer, *needed)) {
3395                 free_printer_info_4(printer);
3396                 return WERR_INSUFFICIENT_BUFFER;
3397         }
3398
3399         /* fill the buffer with the structures */
3400         smb_io_printer_info_4("", buffer, printer, 0);  
3401         
3402         /* clear memory */
3403         free_printer_info_4(printer);
3404         
3405         if (*needed > offered) {
3406                 return WERR_INSUFFICIENT_BUFFER;
3407         }
3408
3409         return WERR_OK; 
3410 }
3411
3412 /****************************************************************************
3413 ****************************************************************************/
3414 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3415 {
3416         PRINTER_INFO_5 *printer=NULL;
3417
3418         if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3419                 return WERR_NOMEM;
3420
3421         if (!construct_printer_info_5(printer, snum))
3422                 return WERR_NOMEM;
3423         
3424         /* check the required size. */  
3425         *needed += spoolss_size_printer_info_5(printer);
3426
3427         if (!alloc_buffer_size(buffer, *needed)) {
3428                 free_printer_info_5(printer);
3429                 return WERR_INSUFFICIENT_BUFFER;
3430         }
3431
3432         /* fill the buffer with the structures */
3433         smb_io_printer_info_5("", buffer, printer, 0);  
3434         
3435         /* clear memory */
3436         free_printer_info_5(printer);
3437         
3438         if (*needed > offered) {
3439                 return WERR_INSUFFICIENT_BUFFER;
3440         }
3441
3442         return WERR_OK; 
3443 }
3444
3445 /****************************************************************************
3446 ****************************************************************************/
3447
3448 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3449 {
3450         POLICY_HND *handle = &q_u->handle;
3451         uint32 level = q_u->level;
3452         NEW_BUFFER *buffer = NULL;
3453         uint32 offered = q_u->offered;
3454         uint32 *needed = &r_u->needed;
3455
3456         int snum;
3457
3458         /* that's an [in out] buffer */
3459         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3460         buffer = r_u->buffer;
3461
3462         *needed=0;
3463
3464         if (!get_printer_snum(p, handle, &snum))
3465                 return WERR_BADFID;
3466
3467         switch (level) {
3468         case 0:
3469                 return getprinter_level_0(snum, buffer, offered, needed);
3470         case 1:
3471                 return getprinter_level_1(snum, buffer, offered, needed);
3472         case 2:         
3473                 return getprinter_level_2(snum, buffer, offered, needed);
3474         case 3:         
3475                 return getprinter_level_3(snum, buffer, offered, needed);
3476         case 4:         
3477                 return getprinter_level_4(snum, buffer, offered, needed);
3478         case 5:         
3479                 return getprinter_level_5(snum, buffer, offered, needed);
3480         }
3481         return WERR_UNKNOWN_LEVEL;
3482 }       
3483                 
3484 /********************************************************************
3485  * fill a DRIVER_INFO_1 struct
3486  ********************************************************************/
3487 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3488 {
3489         init_unistr( &info->name, driver.info_3->name);
3490 }
3491
3492 /********************************************************************
3493  * construct_printer_driver_info_1
3494  ********************************************************************/
3495 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3496 {       
3497         NT_PRINTER_INFO_LEVEL *printer = NULL;
3498         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3499
3500         ZERO_STRUCT(driver);
3501
3502         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3503                 return WERR_INVALID_PRINTER_NAME;
3504
3505         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3506                 return WERR_UNKNOWN_PRINTER_DRIVER;
3507
3508         fill_printer_driver_info_1(info, driver, servername, architecture);
3509
3510         free_a_printer(&printer,2);
3511
3512         return WERR_OK;
3513 }
3514
3515 /********************************************************************
3516  * construct_printer_driver_info_2
3517  * fill a printer_info_2 struct
3518  ********************************************************************/
3519 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3520 {
3521         pstring temp;
3522
3523         info->version=driver.info_3->cversion;
3524
3525         init_unistr( &info->name, driver.info_3->name );
3526         init_unistr( &info->architecture, driver.info_3->environment );
3527
3528
3529     if (strlen(driver.info_3->driverpath)) {
3530                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3531                 init_unistr( &info->driverpath, temp );
3532     } else
3533         init_unistr( &info->driverpath, "" );
3534
3535         if (strlen(driver.info_3->datafile)) {
3536                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3537                 init_unistr( &info->datafile, temp );
3538         } else
3539                 init_unistr( &info->datafile, "" );
3540         
3541         if (strlen(driver.info_3->configfile)) {
3542                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3543                 init_unistr( &info->configfile, temp ); 
3544         } else
3545                 init_unistr( &info->configfile, "" );
3546 }
3547
3548 /********************************************************************
3549  * construct_printer_driver_info_2
3550  * fill a printer_info_2 struct
3551  ********************************************************************/
3552 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3553 {
3554         NT_PRINTER_INFO_LEVEL *printer = NULL;
3555         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3556
3557         ZERO_STRUCT(printer);
3558         ZERO_STRUCT(driver);
3559
3560         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3561                 return WERR_INVALID_PRINTER_NAME;
3562
3563         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3564                 return WERR_UNKNOWN_PRINTER_DRIVER;
3565
3566         fill_printer_driver_info_2(info, driver, servername);
3567
3568         free_a_printer(&printer,2);
3569
3570         return WERR_OK;
3571 }
3572
3573 /********************************************************************
3574  * copy a strings array and convert to UNICODE
3575  *
3576  * convert an array of ascii string to a UNICODE string
3577  ********************************************************************/
3578 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3579 {
3580         int i=0;
3581         int j=0;
3582         char *v;
3583         pstring line;
3584         uint16 *tuary;
3585
3586         DEBUG(6,("init_unistr_array\n"));
3587         *uni_array=NULL;
3588
3589         while (1) {
3590                 if (char_array == NULL)
3591                         v = "";
3592                 else {
3593                         v = char_array[i];
3594                         if (!v) v = ""; /* hack to handle null lists */
3595                 }
3596                 if (strlen(v) == 0) break;
3597                 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3598                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3599                 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3600                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
3601                         return;
3602                 }
3603                 else *uni_array = tuary;
3604                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3605                 i++;
3606         }
3607         
3608         if (*uni_array) {
3609                 (*uni_array)[j]=0x0000;
3610         }
3611         
3612         DEBUGADD(6,("last one:done\n"));
3613 }
3614
3615 /********************************************************************
3616  * construct_printer_info_3
3617  * fill a printer_info_3 struct
3618  ********************************************************************/
3619 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3620 {
3621         pstring temp;
3622
3623         ZERO_STRUCTP(info);
3624
3625         info->version=driver.info_3->cversion;
3626
3627         init_unistr( &info->name, driver.info_3->name );        
3628         init_unistr( &info->architecture, driver.info_3->environment );
3629
3630     if (strlen(driver.info_3->driverpath)) {
3631         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3632         init_unistr( &info->driverpath, temp );
3633     } else
3634         init_unistr( &info->driverpath, "" );
3635     
3636     if (strlen(driver.info_3->datafile)) {
3637         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3638         init_unistr( &info->datafile, temp );
3639     } else
3640         init_unistr( &info->datafile, "" );
3641
3642     if (strlen(driver.info_3->configfile)) {
3643         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3644         init_unistr( &info->configfile, temp ); 
3645     } else
3646         init_unistr( &info->configfile, "" );
3647
3648     if (strlen(driver.info_3->helpfile)) {
3649         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3650         init_unistr( &info->helpfile, temp );
3651     } else
3652         init_unistr( &info->helpfile, "" );
3653
3654         init_unistr( &info->monitorname, driver.info_3->monitorname );
3655         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3656
3657         info->dependentfiles=NULL;
3658         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3659 }
3660
3661 /********************************************************************
3662  * construct_printer_info_3
3663  * fill a printer_info_3 struct
3664  ********************************************************************/
3665 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3666 {       
3667         NT_PRINTER_INFO_LEVEL *printer = NULL;
3668         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3669         WERROR status;
3670         ZERO_STRUCT(driver);
3671
3672         status=get_a_printer(&printer, 2, lp_servicename(snum) );
3673         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3674         if (!W_ERROR_IS_OK(status))
3675                 return WERR_INVALID_PRINTER_NAME;
3676
3677         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3678         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3679         if (!W_ERROR_IS_OK(status)) {
3680                 free_a_printer(&printer,2);
3681                 return WERR_UNKNOWN_PRINTER_DRIVER;
3682         }
3683
3684         fill_printer_driver_info_3(info, driver, servername);
3685
3686         free_a_printer(&printer,2);
3687
3688         return WERR_OK;
3689 }
3690
3691 /********************************************************************
3692  * construct_printer_info_6
3693  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3694  ********************************************************************/
3695
3696 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3697 {
3698         pstring temp;
3699         fstring nullstr;
3700
3701         ZERO_STRUCTP(info);
3702         memset(&nullstr, '\0', sizeof(fstring));
3703
3704         info->version=driver.info_3->cversion;
3705
3706         init_unistr( &info->name, driver.info_3->name );        
3707         init_unistr( &info->architecture, driver.info_3->environment );
3708
3709         if (strlen(driver.info_3->driverpath)) {
3710                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3711                 init_unistr( &info->driverpath, temp );
3712         } else
3713                 init_unistr( &info->driverpath, "" );
3714
3715         if (strlen(driver.info_3->datafile)) {
3716                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3717                 init_unistr( &info->datafile, temp );
3718         } else
3719                 init_unistr( &info->datafile, "" );
3720
3721         if (strlen(driver.info_3->configfile)) {
3722                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3723                 init_unistr( &info->configfile, temp ); 
3724         } else
3725                 init_unistr( &info->configfile, "" );
3726
3727         if (strlen(driver.info_3->helpfile)) {
3728                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3729                 init_unistr( &info->helpfile, temp );
3730         } else
3731                 init_unistr( &info->helpfile, "" );
3732         
3733         init_unistr( &info->monitorname, driver.info_3->monitorname );
3734         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3735
3736         info->dependentfiles=NULL;
3737         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3738
3739         info->previousdrivernames=NULL;
3740         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3741
3742         info->driver_date.low=0;
3743         info->driver_date.high=0;
3744
3745         info->padding=0;
3746         info->driver_version_low=0;
3747         info->driver_version_high=0;
3748
3749         init_unistr( &info->mfgname, "");
3750         init_unistr( &info->oem_url, "");
3751         init_unistr( &info->hardware_id, "");
3752         init_unistr( &info->provider, "");
3753 }
3754
3755 /********************************************************************
3756  * construct_printer_info_6
3757  * fill a printer_info_6 struct
3758  ********************************************************************/
3759 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3760 {       
3761         NT_PRINTER_INFO_LEVEL *printer = NULL;
3762         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3763         WERROR status;
3764         ZERO_STRUCT(driver);
3765
3766         status=get_a_printer(&printer, 2, lp_servicename(snum) );
3767         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3768         if (!W_ERROR_IS_OK(status))
3769                 return WERR_INVALID_PRINTER_NAME;
3770
3771         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3772         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3773         if (!W_ERROR_IS_OK(status)) {
3774                 /*
3775                  * Is this a W2k client ?
3776                  */
3777
3778                 if (version < 3) {
3779                         free_a_printer(&printer,2);
3780                         return WERR_UNKNOWN_PRINTER_DRIVER;
3781                 }
3782
3783                 /* Yes - try again with a WinNT driver. */
3784                 version = 2;
3785                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3786                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3787                 if (!W_ERROR_IS_OK(status)) {
3788                         free_a_printer(&printer,2);
3789                         return WERR_UNKNOWN_PRINTER_DRIVER;
3790                 }
3791         }
3792
3793         fill_printer_driver_info_6(info, driver, servername);
3794
3795         free_a_printer(&printer,2);
3796
3797         return WERR_OK;
3798 }
3799
3800 /****************************************************************************
3801 ****************************************************************************/
3802
3803 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3804 {
3805         SAFE_FREE(info->dependentfiles);
3806 }
3807
3808 /****************************************************************************
3809 ****************************************************************************/
3810
3811 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3812 {
3813         SAFE_FREE(info->dependentfiles);
3814         
3815 }
3816
3817 /****************************************************************************
3818 ****************************************************************************/
3819 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3820 {
3821         DRIVER_INFO_1 *info=NULL;
3822         WERROR status;
3823         
3824         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3825                 return WERR_NOMEM;
3826         
3827         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3828         if (!W_ERROR_IS_OK(status)) {
3829                 SAFE_FREE(info);
3830                 return status;
3831         }
3832
3833         /* check the required size. */  
3834         *needed += spoolss_size_printer_driver_info_1(info);
3835
3836         if (!alloc_buffer_size(buffer, *needed)) {
3837                 SAFE_FREE(info);
3838                 return WERR_INSUFFICIENT_BUFFER;
3839         }
3840
3841         /* fill the buffer with the structures */
3842         smb_io_printer_driver_info_1("", buffer, info, 0);      
3843
3844         /* clear memory */
3845         SAFE_FREE(info);
3846
3847         if (*needed > offered)
3848                 return WERR_INSUFFICIENT_BUFFER;
3849
3850         return WERR_OK;
3851 }
3852
3853 /****************************************************************************
3854 ****************************************************************************/
3855 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3856 {
3857         DRIVER_INFO_2 *info=NULL;
3858         WERROR status;
3859         
3860         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3861                 return WERR_NOMEM;
3862         
3863         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3864         if (!W_ERROR_IS_OK(status)) {
3865                 SAFE_FREE(info);
3866                 return status;
3867         }
3868
3869         /* check the required size. */  
3870         *needed += spoolss_size_printer_driver_info_2(info);
3871
3872         if (!alloc_buffer_size(buffer, *needed)) {
3873                 SAFE_FREE(info);
3874                 return WERR_INSUFFICIENT_BUFFER;
3875         }
3876
3877         /* fill the buffer with the structures */
3878         smb_io_printer_driver_info_2("", buffer, info, 0);      
3879
3880         /* clear memory */
3881         SAFE_FREE(info);
3882
3883         if (*needed > offered)
3884                 return WERR_INSUFFICIENT_BUFFER;
3885         
3886         return WERR_OK;
3887 }
3888
3889 /****************************************************************************
3890 ****************************************************************************/
3891 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3892 {
3893         DRIVER_INFO_3 info;
3894         WERROR status;
3895
3896         ZERO_STRUCT(info);
3897
3898         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3899         if (!W_ERROR_IS_OK(status)) {
3900                 return status;
3901         }
3902
3903         /* check the required size. */  
3904         *needed += spoolss_size_printer_driver_info_3(&info);
3905
3906         if (!alloc_buffer_size(buffer, *needed)) {
3907                 free_printer_driver_info_3(&info);
3908                 return WERR_INSUFFICIENT_BUFFER;
3909         }
3910
3911         /* fill the buffer with the structures */
3912         smb_io_printer_driver_info_3("", buffer, &info, 0);
3913
3914         free_printer_driver_info_3(&info);
3915
3916         if (*needed > offered)
3917                 return WERR_INSUFFICIENT_BUFFER;
3918
3919         return WERR_OK;
3920 }
3921
3922 /****************************************************************************
3923 ****************************************************************************/
3924 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3925 {
3926         DRIVER_INFO_6 info;
3927         WERROR status;
3928
3929         ZERO_STRUCT(info);
3930
3931         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3932         if (!W_ERROR_IS_OK(status)) {
3933                 return status;
3934         }
3935
3936         /* check the required size. */  
3937         *needed += spoolss_size_printer_driver_info_6(&info);
3938
3939         if (!alloc_buffer_size(buffer, *needed)) {
3940                 free_printer_driver_info_6(&info);
3941                 return WERR_INSUFFICIENT_BUFFER;
3942         }
3943
3944         /* fill the buffer with the structures */
3945         smb_io_printer_driver_info_6("", buffer, &info, 0);
3946
3947         free_printer_driver_info_6(&info);
3948
3949         if (*needed > offered)
3950                 return WERR_INSUFFICIENT_BUFFER;
3951         
3952         return WERR_OK;
3953 }
3954
3955 /****************************************************************************
3956 ****************************************************************************/
3957
3958 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3959 {
3960         POLICY_HND *handle = &q_u->handle;
3961         UNISTR2 *uni_arch = &q_u->architecture;
3962         uint32 level = q_u->level;
3963         uint32 clientmajorversion = q_u->clientmajorversion;
3964 /*      uint32 clientminorversion = q_u->clientminorversion; - notused. */
3965         NEW_BUFFER *buffer = NULL;
3966         uint32 offered = q_u->offered;
3967         uint32 *needed = &r_u->needed;
3968         uint32 *servermajorversion = &r_u->servermajorversion;
3969         uint32 *serverminorversion = &r_u->serverminorversion;
3970
3971         fstring servername;
3972         fstring architecture;
3973         int snum;
3974
3975         /* that's an [in out] buffer */
3976         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3977         buffer = r_u->buffer;
3978
3979         DEBUG(4,("_spoolss_getprinterdriver2\n"));
3980
3981         *needed=0;
3982         *servermajorversion=0;
3983         *serverminorversion=0;
3984
3985         pstrcpy(servername, get_called_name());
3986         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3987
3988         if (!get_printer_snum(p, handle, &snum))
3989                 return WERR_BADFID;
3990
3991         switch (level) {
3992         case 1:
3993                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3994         case 2:
3995                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3996         case 3:
3997                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3998         case 6:
3999                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4000         }
4001
4002         return WERR_UNKNOWN_LEVEL;
4003 }
4004
4005 /****************************************************************************
4006 ****************************************************************************/
4007
4008 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4009 {
4010         POLICY_HND *handle = &q_u->handle;
4011
4012         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4013
4014         if (Printer) {
4015                 Printer->page_started=True;
4016                 return WERR_OK;
4017         }
4018
4019         DEBUG(3,("Error in startpageprinter printer handle\n"));
4020         return WERR_BADFID;
4021 }
4022
4023 /****************************************************************************
4024 ****************************************************************************/
4025
4026 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4027 {
4028         POLICY_HND *handle = &q_u->handle;
4029
4030         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4031
4032         if (!Printer) {
4033                 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
4034                 return WERR_BADFID;
4035         }
4036         
4037         Printer->page_started=False;
4038
4039         return WERR_OK;
4040 }
4041
4042 /********************************************************************
4043  * api_spoolss_getprinter
4044  * called from the spoolss dispatcher
4045  *
4046  ********************************************************************/
4047
4048 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4049 {
4050         POLICY_HND *handle = &q_u->handle;
4051 /*      uint32 level = q_u->doc_info_container.level; - notused. */
4052         DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4053         uint32 *jobid = &r_u->jobid;
4054
4055         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4056         int snum;
4057         pstring jobname;
4058         fstring datatype;
4059         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4060         struct current_user user;
4061
4062         if (!Printer) {
4063                 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4064                 return WERR_BADFID;
4065         }
4066
4067         get_current_user(&user, p);
4068
4069         /*
4070          * a nice thing with NT is it doesn't listen to what you tell it.
4071          * when asked to send _only_ RAW datas, it tries to send datas
4072          * in EMF format.
4073          *
4074          * So I add checks like in NT Server ...
4075          *
4076          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
4077          * there's a bug in NT client-side code, so we'll fix it in the
4078          * server-side code. *nnnnnggggh!*
4079          */
4080         
4081         if (info_1->p_datatype != 0) {
4082                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4083                 if (strcmp(datatype, "RAW") != 0) {
4084                         (*jobid)=0;
4085                         return WERR_INVALID_DATATYPE;
4086                 }               
4087         }               
4088         
4089         /* get the share number of the printer */
4090         if (!get_printer_snum(p, handle, &snum)) {
4091                 return WERR_BADFID;
4092         }
4093
4094         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4095         
4096         Printer->jobid = print_job_start(&user, snum, jobname);
4097
4098         /* An error occured in print_job_start() so return an appropriate
4099            NT error code. */
4100
4101         if (Printer->jobid == -1) {
4102                 return map_werror_from_unix(errno);
4103         }
4104         
4105         Printer->document_started=True;
4106         (*jobid) = Printer->jobid;
4107
4108         return WERR_OK;
4109 }
4110
4111 /********************************************************************
4112  * api_spoolss_getprinter
4113  * called from the spoolss dispatcher
4114  *
4115  ********************************************************************/
4116
4117 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4118 {
4119         POLICY_HND *handle = &q_u->handle;
4120
4121         return _spoolss_enddocprinter_internal(p, handle);
4122 }
4123
4124 /****************************************************************************
4125 ****************************************************************************/
4126
4127 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4128 {
4129         POLICY_HND *handle = &q_u->handle;
4130         uint32 buffer_size = q_u->buffer_size;
4131         uint8 *buffer = q_u->buffer;
4132         uint32 *buffer_written = &q_u->buffer_size2;
4133
4134         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4135         
4136         if (!Printer) {
4137                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4138                 r_u->buffer_written = q_u->buffer_size2;
4139                 return WERR_BADFID;
4140         }
4141
4142         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4143
4144
4145         r_u->buffer_written = q_u->buffer_size2;
4146
4147         return WERR_OK;
4148 }
4149
4150 /********************************************************************
4151  * api_spoolss_getprinter
4152  * called from the spoolss dispatcher
4153  *
4154  ********************************************************************/
4155 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4156                               pipes_struct *p)
4157 {
4158         struct current_user user;
4159         int snum;
4160         WERROR errcode = WERR_BADFUNC;
4161         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4162
4163         get_current_user(&user, p);
4164
4165         if (!Printer) {
4166                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4167                 return WERR_BADFID;
4168         }
4169
4170         if (!get_printer_snum(p, handle, &snum))
4171                 return WERR_BADFID;
4172
4173         switch (command) {
4174         case PRINTER_CONTROL_PAUSE:
4175                 if (print_queue_pause(&user, snum, &errcode)) {
4176                         errcode = WERR_OK;
4177                 }
4178                 break;
4179         case PRINTER_CONTROL_RESUME:
4180         case PRINTER_CONTROL_UNPAUSE:
4181                 if (print_queue_resume(&user, snum, &errcode)) {
4182                         errcode = WERR_OK;
4183                 }
4184                 break;
4185         case PRINTER_CONTROL_PURGE:
4186                 if (print_queue_purge(&user, snum, &errcode)) {
4187                         errcode = WERR_OK;
4188                 }
4189                 break;
4190         default:
4191                 return WERR_UNKNOWN_LEVEL;
4192         }
4193
4194         return errcode;
4195 }
4196
4197 /********************************************************************
4198  * api_spoolss_abortprinter
4199  ********************************************************************/
4200
4201 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4202 {
4203         POLICY_HND *handle = &q_u->handle;
4204
4205         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4206 }
4207
4208 /********************************************************************
4209  * called by spoolss_api_setprinter
4210  * when updating a printer description
4211  ********************************************************************/
4212 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4213                                  const SPOOL_PRINTER_INFO_LEVEL *info,
4214                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4215 {
4216         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4217         struct current_user user;
4218         WERROR result;
4219         int snum;
4220
4221         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4222
4223         if (!Printer || !get_printer_snum(p, handle, &snum)) {
4224                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4225                          OUR_HANDLE(handle)));
4226
4227                 result = WERR_BADFID;
4228                 goto done;
4229         }
4230
4231         /* NT seems to like setting the security descriptor even though
4232            nothing may have actually changed.  This causes annoying
4233            dialog boxes when the user doesn't have permission to change
4234            the security descriptor. */
4235
4236         nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4237
4238         if (DEBUGLEVEL >= 10) {
4239                 SEC_ACL *the_acl;
4240                 int i;
4241
4242                 the_acl = old_secdesc_ctr->sec->dacl;
4243                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
4244                            PRINTERNAME(snum), the_acl->num_aces));
4245
4246                 for (i = 0; i < the_acl->num_aces; i++) {
4247                         fstring sid_str;
4248
4249                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4250
4251                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
4252                                   the_acl->ace[i].info.mask));
4253                 }
4254
4255                 the_acl = secdesc_ctr->sec->dacl;
4256
4257                 if (the_acl) {
4258                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4259                                    PRINTERNAME(snum), the_acl->num_aces));
4260
4261                         for (i = 0; i < the_acl->num_aces; i++) {
4262                                 fstring sid_str;
4263                                 
4264                                 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4265                                 
4266                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
4267                                            the_acl->ace[i].info.mask));
4268                         }
4269                 } else {
4270                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4271                 }
4272         }
4273
4274         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4275
4276         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4277                 result = WERR_OK;
4278                 goto done;
4279         }
4280
4281         /* Work out which user is performing the operation */
4282
4283         get_current_user(&user, p);
4284
4285         /* Check the user has permissions to change the security
4286            descriptor.  By experimentation with two NT machines, the user
4287            requires Full Access to the printer to change security
4288            information. */
4289
4290         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4291                 result = WERR_ACCESS_DENIED;
4292                 goto done;
4293         }
4294
4295         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4296
4297  done:
4298
4299         return result;
4300 }
4301
4302 /********************************************************************
4303  Do Samba sanity checks on a printer info struct.
4304  this has changed purpose: it now "canonicalises" printer
4305  info from a client rather than just checking it is correct
4306  ********************************************************************/
4307
4308 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4309 {
4310         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4311                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4312
4313         /* we force some elements to "correct" values */
4314         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4315         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4316                  get_called_name(), lp_servicename(snum));
4317         fstrcpy(info->sharename, lp_servicename(snum));
4318         info->attributes = PRINTER_ATTRIBUTE_SHARED   \
4319                 | PRINTER_ATTRIBUTE_LOCAL  \
4320                 | PRINTER_ATTRIBUTE_RAW_ONLY \
4321                 | PRINTER_ATTRIBUTE_QUEUED ;
4322         
4323         return True;
4324 }
4325
4326 /****************************************************************************
4327 ****************************************************************************/
4328 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4329 {
4330         char *cmd = lp_addprinter_cmd();
4331         char **qlines;
4332         pstring command;
4333         pstring driverlocation;
4334         int numlines;
4335         int ret;
4336         int fd;
4337
4338         /* build driver path... only 9X architecture is needed for legacy reasons */
4339         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4340                         get_called_name());
4341         /* change \ to \\ for the shell */
4342         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4343
4344         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4345                         cmd, printer->info_2->printername, printer->info_2->sharename,
4346                         printer->info_2->portname, printer->info_2->drivername,
4347                         printer->info_2->location, driverlocation);
4348
4349         DEBUG(10,("Running [%s]\n", command));
4350         ret = smbrun(command, &fd);
4351         DEBUGADD(10,("returned [%d]\n", ret));
4352
4353         if ( ret != 0 ) {
4354                 if (fd != -1)
4355                         close(fd);
4356                 return False;
4357         }
4358
4359         numlines = 0;
4360         /* Get lines and convert them back to dos-codepage */
4361         qlines = fd_lines_load(fd, &numlines);
4362         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4363         close(fd);
4364
4365         if(numlines) {
4366                 /* Set the portname to what the script says the portname should be. */
4367                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4368                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4369
4370                 /* Send SIGHUP to process group... is there a better way? */
4371                 kill(0, SIGHUP);
4372                 add_all_printers();
4373         }
4374
4375         file_lines_free(qlines);
4376         return True;
4377 }
4378
4379 /* Return true if two devicemodes are equal */
4380
4381 #define DEVMODE_CHECK_INT(field) \
4382     if (d1->field != d2->field) { \
4383         DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4384             d1->field, d2->field)); \
4385         return False; \
4386     }
4387
4388 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4389 {
4390         if (!d1 && !d2) goto equal;  /* if both are NULL they are equal */
4391
4392         if (!d1 ^ !d2) {
4393                 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4394                 return False; /* if either is exclusively NULL are not equal */
4395         }
4396
4397         if (!strequal(d1->devicename, d2->devicename)) {
4398                 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4399                 return False;
4400         }
4401
4402         if (!strequal(d1->formname, d2->formname)) {
4403                 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4404                 return False;
4405         }
4406
4407         DEVMODE_CHECK_INT(specversion);
4408         DEVMODE_CHECK_INT(driverversion);
4409         DEVMODE_CHECK_INT(driverextra);
4410         DEVMODE_CHECK_INT(orientation);
4411         DEVMODE_CHECK_INT(papersize);
4412         DEVMODE_CHECK_INT(paperlength);
4413         DEVMODE_CHECK_INT(paperwidth);
4414         DEVMODE_CHECK_INT(scale);
4415         DEVMODE_CHECK_INT(copies);
4416         DEVMODE_CHECK_INT(defaultsource);
4417         DEVMODE_CHECK_INT(printquality);
4418         DEVMODE_CHECK_INT(color);
4419         DEVMODE_CHECK_INT(duplex);
4420         DEVMODE_CHECK_INT(yresolution);
4421         DEVMODE_CHECK_INT(ttoption);
4422         DEVMODE_CHECK_INT(collate);
4423         DEVMODE_CHECK_INT(logpixels);
4424
4425         DEVMODE_CHECK_INT(fields);
4426         DEVMODE_CHECK_INT(bitsperpel);
4427         DEVMODE_CHECK_INT(pelswidth);
4428         DEVMODE_CHECK_INT(pelsheight);
4429         DEVMODE_CHECK_INT(displayflags);
4430         DEVMODE_CHECK_INT(displayfrequency);
4431         DEVMODE_CHECK_INT(icmmethod);
4432         DEVMODE_CHECK_INT(icmintent);
4433         DEVMODE_CHECK_INT(mediatype);
4434         DEVMODE_CHECK_INT(dithertype);
4435         DEVMODE_CHECK_INT(reserved1);
4436         DEVMODE_CHECK_INT(reserved2);
4437         DEVMODE_CHECK_INT(panningwidth);
4438         DEVMODE_CHECK_INT(panningheight);
4439
4440         /* compare the private data if it exists */
4441         if (!d1->driverextra && !d2->driverextra) goto equal;
4442
4443
4444         DEVMODE_CHECK_INT(driverextra);
4445
4446         if (memcmp(d1->private, d2->private, d1->driverextra)) {
4447                 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4448                 return False;
4449         }
4450
4451  equal:
4452         DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4453         return True;
4454 }
4455
4456 /* Return true if two NT_PRINTER_PARAM structures are equal */
4457
4458 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4459                                    NT_PRINTER_PARAM *p2)
4460 {
4461         if (!p1 && !p2) goto equal;
4462
4463         if ((!p1 && p2) || (p1 && !p2)) {
4464                 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4465                 return False;
4466         }
4467
4468         /* Compare lists of printer parameters */
4469
4470         while (p1) {
4471                 BOOL found = False;
4472                 NT_PRINTER_PARAM *q = p1;
4473
4474                 /* Find the parameter in the second structure */
4475
4476                 while(q) {
4477
4478                         if (strequal(p1->value, q->value)) {
4479
4480                                 if (p1->type != q->type) {
4481                                         DEBUG(10, ("nt_printer_param_equal():"
4482                                                    "types for %s differ (%d != %d)\n",
4483                                                    p1->value, p1->type,
4484                                                    q->type));
4485                                         break;
4486                                 }
4487
4488                                 if (p1->data_len != q->data_len) {
4489                                         DEBUG(10, ("nt_printer_param_equal():"
4490                                                    "len for %s differs (%d != %d)\n",
4491                                                    p1->value, p1->data_len,
4492                                                    q->data_len));
4493                                         break;
4494                                 }
4495
4496                                 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4497                                         found = True;
4498                                 } else {
4499                                         DEBUG(10, ("nt_printer_param_equal():"
4500                                                    "data for %s differs\n", p1->value));
4501                                 }
4502
4503                                 break;
4504                         }
4505
4506                         q = q->next;
4507                 }
4508
4509                 if (!found) {
4510                         DEBUG(10, ("nt_printer_param_equal(): param %s "
4511                                    "does not exist\n", p1->value));
4512                         return False;
4513                 }
4514
4515                 p1 = p1->next;
4516         }
4517
4518         equal:
4519
4520         DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4521         return True;
4522 }
4523
4524 /********************************************************************
4525  * Called by update_printer when trying to work out whether to
4526  * actually update printer info.
4527  ********************************************************************/
4528
4529 #define PI_CHECK_INT(field) \
4530     if (pi1->field != pi2->field) { \
4531         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4532             pi1->field, pi2->field)); \
4533         return False; \
4534     }
4535
4536 #define PI_CHECK_STR(field) \
4537     if (!strequal(pi1->field, pi2->field)) { \
4538         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4539             pi1->field, pi2->field)); \
4540         return False; \
4541     }
4542
4543 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4544                                         NT_PRINTER_INFO_LEVEL *p2)
4545 {
4546         NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4547
4548         /* Trivial conditions */
4549
4550         if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4551                 goto equal;
4552         }
4553
4554         if ((!p1 && p2) || (p1 && !p2) ||
4555             (!p1->info_2 && p2->info_2) ||
4556             (p1->info_2 && !p2->info_2)) {
4557                 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4558                            "differ\n"));
4559                 return False;
4560         }
4561
4562         /* Compare two nt_printer_info_level structures.  Don't compare
4563            status or cjobs as they seem to have something to do with the
4564            printer queue. */
4565
4566         pi1 = p1->info_2;
4567         pi2 = p2->info_2;
4568
4569         /* Don't check the attributes as we stomp on the value in
4570            check_printer_ok() anyway. */
4571
4572 #if 0
4573         PI_CHECK_INT(attributes);
4574 #endif
4575
4576         PI_CHECK_INT(priority);
4577         PI_CHECK_INT(default_priority);
4578         PI_CHECK_INT(starttime);
4579         PI_CHECK_INT(untiltime);
4580         PI_CHECK_INT(averageppm);
4581
4582         /* Yuck - don't check the printername or servername as the
4583            add_a_printer() code plays games with them.  You can't
4584            change the printername or the sharename through this interface
4585            in Samba. */
4586
4587         PI_CHECK_STR(sharename);
4588         PI_CHECK_STR(portname);
4589         PI_CHECK_STR(drivername);
4590         PI_CHECK_STR(comment);
4591         PI_CHECK_STR(location);
4592
4593         if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4594                 return False;
4595         }
4596
4597         PI_CHECK_STR(sepfile);
4598         PI_CHECK_STR(printprocessor);
4599         PI_CHECK_STR(datatype);
4600         PI_CHECK_STR(parameters);
4601
4602         if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4603                 return False;
4604         }
4605
4606         if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4607                 return False;
4608         }
4609
4610         PI_CHECK_INT(changeid);
4611         PI_CHECK_INT(c_setprinter);
4612         PI_CHECK_INT(setuptime);
4613
4614  equal:
4615         DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4616         return True;
4617 }
4618
4619 /********************************************************************
4620  * called by spoolss_api_setprinter
4621  * when updating a printer description
4622  ********************************************************************/
4623
4624 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4625                            const SPOOL_PRINTER_INFO_LEVEL *info,
4626                            DEVICEMODE *devmode)
4627 {
4628         int snum;
4629         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4630         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4631         WERROR result;
4632
4633         DEBUG(8,("update_printer\n"));
4634         
4635         result = WERR_OK;
4636
4637         if (level!=2) {
4638                 DEBUG(0,("Send a mail to samba@samba.org\n"));
4639                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4640                 result = WERR_UNKNOWN_LEVEL;
4641                 goto done;
4642         }
4643
4644         if (!Printer) {
4645                 result = WERR_BADFID;
4646                 goto done;
4647         }
4648
4649         if (!get_printer_snum(p, handle, &snum)) {
4650                 result = WERR_BADFID;
4651                 goto done;
4652         }
4653
4654         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4655             (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4656                 result = WERR_BADFID;
4657                 goto done;
4658         }
4659
4660         DEBUGADD(8,("Converting info_2 struct\n"));
4661
4662         /*
4663          * convert_printer_info converts the incoming
4664          * info from the client and overwrites the info
4665          * just read from the tdb in the pointer 'printer'.
4666          */
4667
4668         if (!convert_printer_info(info, printer, level)) {
4669                 result =  WERR_NOMEM;
4670                 goto done;
4671         }
4672
4673         if (info->info_2->devmode_ptr != 0) {
4674                 /* we have a valid devmode
4675                    convert it and link it*/
4676
4677                 DEBUGADD(8,("Converting the devicemode struct\n"));
4678                 if (!convert_devicemode(printer->info_2->printername, devmode,
4679                                 &printer->info_2->devmode)) {
4680                         result =  WERR_NOMEM;
4681                         goto done;
4682                 }
4683         }
4684
4685         /* Do sanity check on the requested changes for Samba */
4686
4687         if (!check_printer_ok(printer->info_2, snum)) {
4688                 result = WERR_INVALID_PARAM;
4689                 goto done;
4690         }
4691
4692         /* NT likes to call this function even though nothing has actually
4693            changed.  Check this so the user doesn't end up with an
4694            annoying permission denied dialog box. */
4695
4696         if (nt_printer_info_level_equal(printer, old_printer)) {
4697                 DEBUG(3, ("printer info has not changed\n"));
4698                 result = WERR_OK;
4699                 goto done;
4700         }
4701
4702         /* Check calling user has permission to update printer description */
4703
4704         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4705                 DEBUG(3, ("printer property change denied by security "
4706                           "descriptor\n"));
4707                 result = WERR_ACCESS_DENIED;
4708                 goto done;
4709         }
4710
4711         /* Call addprinter hook */
4712
4713         if (*lp_addprinter_cmd()) {
4714                 if (!add_printer_hook(printer)) {
4715                         result = WERR_ACCESS_DENIED;
4716                         goto done;
4717                 }
4718         }
4719         
4720         /* Update printer info */
4721         result = add_a_printer(*printer, 2);
4722
4723  done:
4724         free_a_printer(&printer, 2);
4725         free_a_printer(&old_printer, 2);
4726
4727         srv_spoolss_sendnotify(p, handle);
4728
4729         return result;
4730 }
4731
4732 /****************************************************************************
4733 ****************************************************************************/
4734
4735 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4736 {
4737         POLICY_HND *handle = &q_u->handle;
4738         uint32 level = q_u->level;
4739         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4740         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4741         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4742         uint32 command = q_u->command;
4743
4744         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4745         
4746         if (!Printer) {
4747                 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4748                 return WERR_BADFID;
4749         }
4750
4751         /* check the level */   
4752         switch (level) {
4753                 case 0:
4754                         return control_printer(handle, command, p);
4755                 case 2:
4756                         return update_printer(p, handle, level, info, devmode_ctr.devmode);
4757                 case 3:
4758                         return update_printer_sec(handle, level, info, p,
4759                                                   secdesc_ctr);
4760                 default:
4761                         return WERR_UNKNOWN_LEVEL;
4762         }
4763 }
4764
4765 /****************************************************************************
4766 ****************************************************************************/
4767
4768 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4769 {
4770         POLICY_HND *handle = &q_u->handle;
4771
4772         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4773         
4774         if (!Printer) {
4775                 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4776                 return WERR_BADFID;
4777         }
4778
4779         if (Printer->notify.client_connected==True)
4780                 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4781
4782         Printer->notify.flags=0;
4783         Printer->notify.options=0;
4784         Printer->notify.localmachine[0]='\0';
4785         Printer->notify.printerlocal=0;
4786         if (Printer->notify.option)
4787                 free_spool_notify_option(&Printer->notify.option);
4788         Printer->notify.client_connected=False;
4789
4790         return WERR_OK;
4791 }
4792
4793 /****************************************************************************
4794 ****************************************************************************/
4795
4796 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4797 {
4798         /* that's an [in out] buffer (despite appearences to the contrary) */
4799         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4800
4801         r_u->needed = 0;
4802         return WERR_INVALID_PARAM; /* this is what a NT server
4803                                            returns for AddJob. AddJob
4804                                            must fail on non-local
4805                                            printers */
4806 }
4807
4808 /****************************************************************************
4809 ****************************************************************************/
4810 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4811                             int position, int snum)
4812 {
4813         pstring temp_name;
4814         
4815         struct tm *t;
4816         
4817         t=gmtime(&queue->time);
4818         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4819
4820         job_info->jobid=queue->job;     
4821         init_unistr(&job_info->printername, lp_servicename(snum));
4822         init_unistr(&job_info->machinename, temp_name);
4823         init_unistr(&job_info->username, queue->user);
4824         init_unistr(&job_info->document, queue->file);
4825         init_unistr(&job_info->datatype, "RAW");
4826         init_unistr(&job_info->text_status, "");
4827         job_info->status=nt_printj_status(queue->status);
4828         job_info->priority=queue->priority;
4829         job_info->position=position;
4830         job_info->totalpages=0;
4831         job_info->pagesprinted=0;
4832
4833         make_systemtime(&job_info->submitted, t);
4834 }
4835
4836 /****************************************************************************
4837 ****************************************************************************/
4838 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4839                             int position, int snum, 
4840                             NT_PRINTER_INFO_LEVEL *ntprinter)
4841 {
4842         pstring temp_name;
4843         pstring chaine;
4844         struct tm *t;
4845
4846         t=gmtime(&queue->time);
4847         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4848
4849         job_info->jobid=queue->job;
4850         
4851         slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
4852
4853         init_unistr(&job_info->printername, chaine);
4854         
4855         init_unistr(&job_info->machinename, temp_name);
4856         init_unistr(&job_info->username, queue->user);
4857         init_unistr(&job_info->document, queue->file);
4858         init_unistr(&job_info->notifyname, queue->user);
4859         init_unistr(&job_info->datatype, "RAW");
4860         init_unistr(&job_info->printprocessor, "winprint");
4861         init_unistr(&job_info->parameters, "");
4862         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4863         init_unistr(&job_info->text_status, "");
4864         
4865 /* and here the security descriptor */
4866
4867         job_info->status=nt_printj_status(queue->status);
4868         job_info->priority=queue->priority;
4869         job_info->position=position;
4870         job_info->starttime=0;
4871         job_info->untiltime=0;
4872         job_info->totalpages=0;
4873         job_info->size=queue->size;
4874         make_systemtime(&(job_info->submitted), t);
4875         job_info->timeelapsed=0;
4876         job_info->pagesprinted=0;
4877
4878         if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4879                 return False;
4880         }
4881
4882         return (True);
4883 }
4884
4885 /****************************************************************************
4886  Enumjobs at level 1.
4887 ****************************************************************************/
4888 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4889                               NEW_BUFFER *buffer, uint32 offered,
4890                               uint32 *needed, uint32 *returned)
4891 {
4892         JOB_INFO_1 *info;
4893         int i;
4894         
4895         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4896         if (info==NULL) {
4897                 SAFE_FREE(queue);
4898                 *returned=0;
4899                 return WERR_NOMEM;
4900         }
4901         
4902         for (i=0; i<*returned; i++)
4903                 fill_job_info_1(&info[i], &queue[i], i, snum);
4904
4905         SAFE_FREE(queue);
4906
4907         /* check the required size. */  
4908         for (i=0; i<*returned; i++)
4909                 (*needed) += spoolss_size_job_info_1(&info[i]);
4910
4911         if (!alloc_buffer_size(buffer, *needed)) {
4912                 SAFE_FREE(info);
4913                 return WERR_INSUFFICIENT_BUFFER;
4914         }
4915
4916         /* fill the buffer with the structures */
4917         for (i=0; i<*returned; i++)
4918                 smb_io_job_info_1("", buffer, &info[i], 0);     
4919
4920         /* clear memory */
4921         SAFE_FREE(info);
4922
4923         if (*needed > offered) {
4924                 *returned=0;
4925                 return WERR_INSUFFICIENT_BUFFER;
4926         }
4927
4928         return WERR_OK;
4929 }
4930
4931 /****************************************************************************
4932  Enumjobs at level 2.
4933 ****************************************************************************/
4934 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4935                               NEW_BUFFER *buffer, uint32 offered,
4936                               uint32 *needed, uint32 *returned)
4937 {
4938         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4939         JOB_INFO_2 *info;
4940         int i;
4941         WERROR result;
4942         
4943         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4944         if (info==NULL) {
4945                 *returned=0;
4946                 return WERR_NOMEM;
4947         }
4948
4949         result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4950         if (!W_ERROR_IS_OK(result)) {
4951                 *returned = 0;
4952                 return result;
4953         }
4954                 
4955         for (i=0; i<*returned; i++)
4956                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4957
4958         free_a_printer(&ntprinter, 2);
4959         SAFE_FREE(queue);
4960
4961         /* check the required size. */  
4962         for (i=0; i<*returned; i++)
4963                 (*needed) += spoolss_size_job_info_2(&info[i]);
4964
4965         if (!alloc_buffer_size(buffer, *needed)) {
4966                 SAFE_FREE(info);
4967                 return WERR_INSUFFICIENT_BUFFER;
4968         }
4969
4970         /* fill the buffer with the structures */
4971         for (i=0; i<*returned; i++)
4972                 smb_io_job_info_2("", buffer, &info[i], 0);     
4973
4974         /* clear memory */
4975         for (i = 0; i < *returned; i++)
4976                 free_job_info_2(&info[i]);
4977
4978         SAFE_FREE(info);
4979
4980         if (*needed > offered) {
4981                 *returned=0;
4982                 return WERR_INSUFFICIENT_BUFFER;
4983         }
4984
4985         return WERR_OK;
4986 }
4987
4988 /****************************************************************************
4989  Enumjobs.
4990 ****************************************************************************/
4991
4992 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4993 {       
4994         POLICY_HND *handle = &q_u->handle;
4995 /*      uint32 firstjob = q_u->firstjob; - notused. */
4996 /*      uint32 numofjobs = q_u->numofjobs; - notused. */
4997         uint32 level = q_u->level;
4998         NEW_BUFFER *buffer = NULL;
4999         uint32 offered = q_u->offered;
5000         uint32 *needed = &r_u->needed;
5001         uint32 *returned = &r_u->returned;
5002
5003         int snum;
5004         print_status_struct prt_status;
5005         print_queue_struct *queue=NULL;
5006
5007         /* that's an [in out] buffer */
5008         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5009         buffer = r_u->buffer;
5010
5011         DEBUG(4,("_spoolss_enumjobs\n"));
5012
5013         *needed=0;
5014         *returned=0;
5015
5016         if (!get_printer_snum(p, handle, &snum))
5017                 return WERR_BADFID;
5018
5019         *returned = print_queue_status(snum, &queue, &prt_status);
5020         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5021
5022         if (*returned == 0) {
5023                 SAFE_FREE(queue);
5024                 return WERR_OK;
5025         }
5026
5027         switch (level) {
5028         case 1:
5029                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5030         case 2:
5031                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5032         default:
5033                 SAFE_FREE(queue);
5034                 *returned=0;
5035                 return WERR_UNKNOWN_LEVEL;
5036         }
5037 }
5038
5039 /****************************************************************************
5040 ****************************************************************************/
5041
5042 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5043 {
5044         return WERR_OK;
5045 }
5046
5047 /****************************************************************************
5048 ****************************************************************************/
5049
5050 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5051 {
5052         POLICY_HND *handle = &q_u->handle;
5053         uint32 jobid = q_u->jobid;
5054 /*      uint32 level = q_u->level; - notused. */
5055 /*      JOB_INFO *ctr = &q_u->ctr; - notused. */
5056         uint32 command = q_u->command;
5057
5058         struct current_user user;
5059         int snum;
5060         WERROR errcode = WERR_BADFUNC;
5061                 
5062         if (!get_printer_snum(p, handle, &snum)) {
5063                 return WERR_BADFID;
5064         }
5065
5066         if (!print_job_exists(jobid)) {
5067                 return WERR_INVALID_PRINTER_NAME;
5068         }
5069
5070         get_current_user(&user, p);     
5071
5072         switch (command) {
5073         case JOB_CONTROL_CANCEL:
5074         case JOB_CONTROL_DELETE:
5075                 if (print_job_delete(&user, jobid, &errcode)) {
5076                         errcode = WERR_OK;
5077                 }
5078                 break;
5079         case JOB_CONTROL_PAUSE:
5080                 if (print_job_pause(&user, jobid, &errcode)) {
5081                         errcode = WERR_OK;
5082                 }               
5083                 break;
5084         case JOB_CONTROL_RESTART:
5085         case JOB_CONTROL_RESUME:
5086                 if (print_job_resume(&user, jobid, &errcode)) {
5087                         errcode = WERR_OK;
5088                 }
5089                 break;
5090         default:
5091                 return WERR_UNKNOWN_LEVEL;
5092         }
5093
5094         return errcode;
5095 }
5096
5097 /****************************************************************************
5098  Enumerates all printer drivers at level 1.
5099 ****************************************************************************/
5100 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5101 {
5102         int i;
5103         int ndrivers;
5104         uint32 version;
5105         fstring *list = NULL;
5106
5107         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5108         DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5109
5110         *returned=0;
5111
5112 #define MAX_VERSION 4
5113
5114         for (version=0; version<MAX_VERSION; version++) {
5115                 list=NULL;
5116                 ndrivers=get_ntdrivers(&list, architecture, version);
5117                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5118
5119                 if(ndrivers == -1)
5120                         return WERR_NOMEM;
5121
5122                 if(ndrivers != 0) {
5123                         if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5124                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5125                                 SAFE_FREE(driver_info_1);
5126                                 SAFE_FREE(list);
5127                                 return WERR_NOMEM;
5128                         }
5129                         else driver_info_1 = tdi1;
5130                 }
5131
5132                 for (i=0; i<ndrivers; i++) {
5133                         WERROR status;
5134                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5135                         ZERO_STRUCT(driver);
5136                         status = get_a_printer_driver(&driver, 3, list[i], 
5137                                                       architecture, version);
5138                         if (!W_ERROR_IS_OK(status)) {
5139                                 SAFE_FREE(list);
5140                                 return status;
5141                         }
5142                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
5143                         free_a_printer_driver(driver, 3);
5144                 }       
5145
5146                 *returned+=ndrivers;
5147                 SAFE_FREE(list);
5148         }
5149         
5150         /* check the required size. */
5151         for (i=0; i<*returned; i++) {
5152                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5153                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5154         }
5155
5156         if (!alloc_buffer_size(buffer, *needed)) {
5157                 SAFE_FREE(driver_info_1);
5158                 return WERR_INSUFFICIENT_BUFFER;
5159         }
5160
5161         /* fill the buffer with the driver structures */
5162         for (i=0; i<*returned; i++) {
5163                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5164                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5165         }
5166
5167         SAFE_FREE(driver_info_1);
5168
5169         if (*needed > offered) {
5170                 *returned=0;
5171                 return WERR_INSUFFICIENT_BUFFER;
5172         }
5173
5174         return WERR_OK;
5175 }
5176
5177 /****************************************************************************
5178  Enumerates all printer drivers at level 2.
5179 ****************************************************************************/
5180 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5181 {
5182         int i;
5183         int ndrivers;
5184         uint32 version;
5185         fstring *list = NULL;
5186
5187         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5188         DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5189
5190         *returned=0;
5191
5192 #define MAX_VERSION 4
5193
5194         for (version=0; version<MAX_VERSION; version++) {
5195                 list=NULL;
5196                 ndrivers=get_ntdrivers(&list, architecture, version);
5197                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5198
5199                 if(ndrivers == -1)
5200                         return WERR_NOMEM;
5201
5202                 if(ndrivers != 0) {
5203                         if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5204                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5205                                 SAFE_FREE(driver_info_2);
5206                                 SAFE_FREE(list);
5207                                 return WERR_NOMEM;
5208                         }
5209                         else driver_info_2 = tdi2;
5210                 }
5211                 
5212                 for (i=0; i<ndrivers; i++) {
5213                         WERROR status;
5214
5215                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5216                         ZERO_STRUCT(driver);
5217                         status = get_a_printer_driver(&driver, 3, list[i], 
5218                                                       architecture, version);
5219                         if (!W_ERROR_IS_OK(status)) {
5220                                 SAFE_FREE(list);
5221                                 return status;
5222                         }
5223                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
5224                         free_a_printer_driver(driver, 3);
5225                 }       
5226
5227                 *returned+=ndrivers;
5228                 SAFE_FREE(list);
5229         }
5230         
5231         /* check the required size. */
5232         for (i=0; i<*returned; i++) {
5233                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5234                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5235         }
5236
5237         if (!alloc_buffer_size(buffer, *needed)) {
5238                 SAFE_FREE(driver_info_2);
5239                 return WERR_INSUFFICIENT_BUFFER;
5240         }
5241
5242         /* fill the buffer with the form structures */
5243         for (i=0; i<*returned; i++) {
5244                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5245                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5246         }
5247
5248         SAFE_FREE(driver_info_2);
5249
5250         if (*needed > offered) {
5251                 *returned=0;
5252                 return WERR_INSUFFICIENT_BUFFER;
5253         }
5254
5255         return WERR_OK;
5256 }
5257
5258 /****************************************************************************
5259  Enumerates all printer drivers at level 3.
5260 ****************************************************************************/
5261 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5262 {
5263         int i;
5264         int ndrivers;
5265         uint32 version;
5266         fstring *list = NULL;
5267
5268         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5269         DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5270
5271         *returned=0;
5272
5273 #define MAX_VERSION 4
5274
5275         for (version=0; version<MAX_VERSION; version++) {
5276                 list=NULL;
5277                 ndrivers=get_ntdrivers(&list, architecture, version);
5278                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5279
5280                 if(ndrivers == -1)
5281                         return WERR_NOMEM;
5282
5283                 if(ndrivers != 0) {
5284                         if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5285                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5286                                 SAFE_FREE(driver_info_3);
5287                                 SAFE_FREE(list);
5288                                 return WERR_NOMEM;
5289                         }
5290                         else driver_info_3 = tdi3;
5291                 }
5292
5293                 for (i=0; i<ndrivers; i++) {
5294                         WERROR status;
5295
5296                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5297                         ZERO_STRUCT(driver);
5298                         status = get_a_printer_driver(&driver, 3, list[i], 
5299                                                       architecture, version);
5300                         if (!W_ERROR_IS_OK(status)) {
5301                                 SAFE_FREE(list);
5302                                 return status;
5303                         }
5304                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
5305                         free_a_printer_driver(driver, 3);
5306                 }       
5307
5308                 *returned+=ndrivers;
5309                 SAFE_FREE(list);
5310         }
5311
5312         /* check the required size. */
5313         for (i=0; i<*returned; i++) {
5314                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5315                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5316         }
5317
5318         if (!alloc_buffer_size(buffer, *needed)) {
5319                 SAFE_FREE(driver_info_3);
5320                 return WERR_INSUFFICIENT_BUFFER;
5321         }
5322         
5323         /* fill the buffer with the driver structures */
5324         for (i=0; i<*returned; i++) {
5325                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5326                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5327         }
5328
5329         for (i=0; i<*returned; i++)
5330                 SAFE_FREE(driver_info_3[i].dependentfiles);
5331         
5332         SAFE_FREE(driver_info_3);
5333         
5334         if (*needed > offered) {
5335                 *returned=0;
5336                 return WERR_INSUFFICIENT_BUFFER;
5337         }
5338
5339         return WERR_OK;
5340 }
5341
5342 /****************************************************************************
5343  Enumerates all printer drivers.
5344 ****************************************************************************/
5345
5346 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5347 {
5348 /*      UNISTR2 *name = &q_u->name; - notused. */
5349         UNISTR2 *environment = &q_u->environment;
5350         uint32 level = q_u->level;
5351         NEW_BUFFER *buffer = NULL;
5352         uint32 offered = q_u->offered;
5353         uint32 *needed = &r_u->needed;
5354         uint32 *returned = &r_u->returned;
5355
5356         fstring *list = NULL;
5357         fstring servername;
5358         fstring architecture;
5359
5360         /* that's an [in out] buffer */
5361         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5362         buffer = r_u->buffer;
5363
5364         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5365         fstrcpy(servername, get_called_name());
5366         *needed=0;
5367         *returned=0;
5368
5369         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5370
5371         switch (level) {
5372         case 1:
5373                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5374         case 2:
5375                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5376         case 3:
5377                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5378         default:
5379                 *returned=0;
5380                 SAFE_FREE(list);
5381                 return WERR_UNKNOWN_LEVEL;
5382         }
5383 }
5384
5385 /****************************************************************************
5386 ****************************************************************************/
5387
5388 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5389 {
5390         form->flag=list->flag;
5391         init_unistr(&form->name, list->name);
5392         form->width=list->width;
5393         form->length=list->length;
5394         form->left=list->left;
5395         form->top=list->top;
5396         form->right=list->right;
5397         form->bottom=list->bottom;      
5398 }
5399         
5400 /****************************************************************************
5401 ****************************************************************************/
5402
5403 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5404 {
5405 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5406         uint32 level = q_u->level;
5407         NEW_BUFFER *buffer = NULL;
5408         uint32 offered = q_u->offered;
5409         uint32 *needed = &r_u->needed;
5410         uint32 *numofforms = &r_u->numofforms;
5411         uint32 numbuiltinforms;
5412
5413         nt_forms_struct *list=NULL;
5414         nt_forms_struct *builtinlist=NULL;
5415         FORM_1 *forms_1;
5416         int buffer_size=0;
5417         int i;
5418
5419         /* that's an [in out] buffer */
5420         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5421         buffer = r_u->buffer;
5422
5423         DEBUG(4,("_spoolss_enumforms\n"));
5424         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5425         DEBUGADD(5,("Info level [%d]\n",          level));
5426
5427         numbuiltinforms = get_builtin_ntforms(&builtinlist);
5428         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
5429         *numofforms = get_ntforms(&list);
5430         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
5431         *numofforms += numbuiltinforms;
5432
5433         if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5434
5435         switch (level) {
5436         case 1:
5437                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5438                         *numofforms=0;
5439                         return WERR_NOMEM;
5440                 }
5441
5442                 /* construct the list of form structures */
5443                 for (i=0; i<numbuiltinforms; i++) {
5444                         DEBUGADD(6,("Filling form number [%d]\n",i));
5445                         fill_form_1(&forms_1[i], &builtinlist[i]);
5446                 }
5447                 
5448                 SAFE_FREE(builtinlist);
5449
5450                 for (; i<*numofforms; i++) {
5451                         DEBUGADD(6,("Filling form number [%d]\n",i));
5452                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5453                 }
5454                 
5455                 SAFE_FREE(list);
5456
5457                 /* check the required size. */
5458                 for (i=0; i<numbuiltinforms; i++) {
5459                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5460                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5461                 }
5462                 for (; i<*numofforms; i++) {
5463                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5464                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5465                 }
5466
5467                 *needed=buffer_size;            
5468                 
5469                 if (!alloc_buffer_size(buffer, buffer_size)){
5470                         SAFE_FREE(forms_1);
5471                         return WERR_INSUFFICIENT_BUFFER;
5472                 }
5473
5474                 /* fill the buffer with the form structures */
5475                 for (i=0; i<numbuiltinforms; i++) {
5476                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5477                         smb_io_form_1("", buffer, &forms_1[i], 0);
5478                 }
5479                 for (; i<*numofforms; i++) {
5480                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5481                         smb_io_form_1("", buffer, &forms_1[i], 0);
5482                 }
5483
5484                 SAFE_FREE(forms_1);
5485
5486                 if (*needed > offered) {
5487                         *numofforms=0;
5488                         return WERR_INSUFFICIENT_BUFFER;
5489                 }
5490                 else
5491                         return WERR_OK;
5492                         
5493         default:
5494                 SAFE_FREE(list);
5495                 SAFE_FREE(builtinlist);
5496                 return WERR_UNKNOWN_LEVEL;
5497         }
5498
5499 }
5500
5501 /****************************************************************************
5502 ****************************************************************************/
5503
5504 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5505 {
5506 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5507         uint32 level = q_u->level;
5508         UNISTR2 *uni_formname = &q_u->formname;
5509         NEW_BUFFER *buffer = NULL;
5510         uint32 offered = q_u->offered;
5511         uint32 *needed = &r_u->needed;
5512
5513         nt_forms_struct *list=NULL;
5514         nt_forms_struct builtin_form;
5515         BOOL foundBuiltin;
5516         FORM_1 form_1;
5517         fstring form_name;
5518         int buffer_size=0;
5519         int numofforms=0, i=0;
5520
5521         /* that's an [in out] buffer */
5522         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5523         buffer = r_u->buffer;
5524
5525         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5526
5527         DEBUG(4,("_spoolss_getform\n"));
5528         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5529         DEBUGADD(5,("Info level [%d]\n",          level));
5530
5531         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5532         if (!foundBuiltin) {
5533                 numofforms = get_ntforms(&list);
5534                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
5535
5536                 if (numofforms == 0)
5537                         return WERR_BADFID;
5538         }
5539
5540         switch (level) {
5541         case 1:
5542                 if (foundBuiltin) {
5543                         fill_form_1(&form_1, &builtin_form);
5544                 } else {
5545
5546                         /* Check if the requested name is in the list of form structures */
5547                         for (i=0; i<numofforms; i++) {
5548
5549                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5550
5551                                 if (strequal(form_name, list[i].name)) {
5552                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5553                                         fill_form_1(&form_1, &list[i]);
5554                                         break;
5555                                 }
5556                         }
5557                         
5558                         SAFE_FREE(list);
5559                         if (i == numofforms) {
5560                                 return WERR_BADFID;
5561                         }
5562                 }
5563                 /* check the required size. */
5564
5565                 *needed=spoolss_size_form_1(&form_1);
5566                 
5567                 if (!alloc_buffer_size(buffer, buffer_size)){
5568                         return WERR_INSUFFICIENT_BUFFER;
5569                 }
5570
5571                 if (*needed > offered) {
5572                         return WERR_INSUFFICIENT_BUFFER;
5573                 }
5574
5575                 /* fill the buffer with the form structures */
5576                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5577                 smb_io_form_1("", buffer, &form_1, 0);
5578
5579                 return WERR_OK;
5580                         
5581         default:
5582                 SAFE_FREE(list);
5583                 return WERR_UNKNOWN_LEVEL;
5584         }
5585 }
5586
5587 /****************************************************************************
5588 ****************************************************************************/
5589 static void fill_port_1(PORT_INFO_1 *port, char *name)
5590 {
5591         init_unistr(&port->port_name, name);
5592 }
5593
5594 /****************************************************************************
5595 ****************************************************************************/
5596 static void fill_port_2(PORT_INFO_2 *port, char *name)
5597 {
5598         init_unistr(&port->port_name, name);
5599         init_unistr(&port->monitor_name, "Local Monitor");
5600         init_unistr(&port->description, "Local Port");
5601 #define PORT_TYPE_WRITE 1
5602         port->port_type=PORT_TYPE_WRITE;
5603         port->reserved=0x0;     
5604 }
5605
5606 /****************************************************************************
5607  enumports level 1.
5608 ****************************************************************************/
5609 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5610 {
5611         PORT_INFO_1 *ports=NULL;
5612         int i=0;
5613
5614         if (*lp_enumports_cmd()) {
5615                 char *cmd = lp_enumports_cmd();
5616                 char **qlines;
5617                 pstring command;
5618                 int numlines;
5619                 int ret;
5620                 int fd;
5621
5622                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5623
5624                 DEBUG(10,("Running [%s]\n", command));
5625                 ret = smbrun(command, &fd);
5626                 DEBUG(10,("Returned [%d]\n", ret));
5627                 if (ret != 0) {
5628                         if (fd != -1)
5629                                 close(fd);
5630                         /* Is this the best error to return here? */
5631                         return WERR_ACCESS_DENIED;
5632                 }
5633
5634                 numlines = 0;
5635                 qlines = fd_lines_load(fd, &numlines);
5636                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5637                 close(fd);
5638
5639                 if(numlines) {
5640                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5641                                 DEBUG(10,("Returning WERR_NOMEM [%s]\n", 
5642                                           werror_str(WERR_NOMEM)));
5643                                 file_lines_free(qlines);
5644                                 return WERR_NOMEM;
5645                         }
5646
5647                         for (i=0; i<numlines; i++) {
5648                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5649                                 fill_port_1(&ports[i], qlines[i]);
5650                         }
5651
5652                         file_lines_free(qlines);
5653                 }
5654
5655                 *returned = numlines;
5656
5657         } else {
5658                 *returned = 1; /* Sole Samba port returned. */
5659
5660                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5661                         return WERR_NOMEM;
5662         
5663                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5664
5665                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5666         }
5667
5668         /* check the required size. */
5669         for (i=0; i<*returned; i++) {
5670                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5671                 *needed += spoolss_size_port_info_1(&ports[i]);
5672         }
5673                 
5674         if (!alloc_buffer_size(buffer, *needed)) {
5675                 SAFE_FREE(ports);
5676                 return WERR_INSUFFICIENT_BUFFER;
5677         }
5678
5679         /* fill the buffer with the ports structures */
5680         for (i=0; i<*returned; i++) {
5681                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5682                 smb_io_port_1("", buffer, &ports[i], 0);
5683         }
5684
5685         SAFE_FREE(ports);
5686
5687         if (*needed > offered) {
5688                 *returned=0;
5689                 return WERR_INSUFFICIENT_BUFFER;
5690         }
5691
5692         return WERR_OK;
5693 }
5694
5695 /****************************************************************************
5696  enumports level 2.
5697 ****************************************************************************/
5698
5699 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5700 {
5701         PORT_INFO_2 *ports=NULL;
5702         int i=0;
5703
5704         if (*lp_enumports_cmd()) {
5705                 char *cmd = lp_enumports_cmd();
5706                 char *path;
5707                 char **qlines;
5708                 pstring tmp_file;
5709                 pstring command;
5710                 int numlines;
5711                 int ret;
5712                 int fd;
5713
5714                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5715                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5716                 else
5717                         path = lp_lockdir();
5718
5719                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5720                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5721
5722                 unlink(tmp_file);
5723                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5724                 ret = smbrun(command, &fd);
5725                 DEBUGADD(10,("returned [%d]\n", ret));
5726                 if (ret != 0) {
5727                         if (fd != -1)
5728                                 close(fd);
5729                         /* Is this the best error to return here? */
5730                         return WERR_ACCESS_DENIED;
5731                 }
5732
5733                 numlines = 0;
5734                 qlines = fd_lines_load(fd, &numlines);
5735                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5736                 close(fd);
5737
5738                 if(numlines) {
5739                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5740                                 file_lines_free(qlines);
5741                                 return WERR_NOMEM;
5742                         }
5743
5744                         for (i=0; i<numlines; i++) {
5745                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5746                                 fill_port_2(&(ports[i]), qlines[i]);
5747                         }
5748
5749                         file_lines_free(qlines);
5750                 }
5751
5752                 *returned = numlines;
5753
5754         } else {
5755
5756                 *returned = 1;
5757
5758                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5759                         return WERR_NOMEM;
5760         
5761                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5762
5763                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5764         }
5765
5766         /* check the required size. */
5767         for (i=0; i<*returned; i++) {
5768                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5769                 *needed += spoolss_size_port_info_2(&ports[i]);
5770         }
5771                 
5772         if (!alloc_buffer_size(buffer, *needed)) {
5773                 SAFE_FREE(ports);
5774                 return WERR_INSUFFICIENT_BUFFER;
5775         }
5776
5777         /* fill the buffer with the ports structures */
5778         for (i=0; i<*returned; i++) {
5779                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5780                 smb_io_port_2("", buffer, &ports[i], 0);
5781         }
5782
5783         SAFE_FREE(ports);
5784
5785         if (*needed > offered) {
5786                 *returned=0;
5787                 return WERR_INSUFFICIENT_BUFFER;
5788         }
5789
5790         return WERR_OK;
5791 }
5792
5793 /****************************************************************************
5794  enumports.
5795 ****************************************************************************/
5796
5797 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5798 {
5799 /*      UNISTR2 *name = &q_u->name; - notused. */
5800         uint32 level = q_u->level;
5801         NEW_BUFFER *buffer = NULL;
5802         uint32 offered = q_u->offered;
5803         uint32 *needed = &r_u->needed;
5804         uint32 *returned = &r_u->returned;
5805
5806         /* that's an [in out] buffer */
5807         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5808         buffer = r_u->buffer;
5809
5810         DEBUG(4,("_spoolss_enumports\n"));
5811         
5812         *returned=0;
5813         *needed=0;
5814         
5815         switch (level) {
5816         case 1:
5817                 return enumports_level_1(buffer, offered, needed, returned);
5818         case 2:
5819                 return enumports_level_2(buffer, offered, needed, returned);
5820         default:
5821                 return WERR_UNKNOWN_LEVEL;
5822         }
5823 }
5824
5825 /****************************************************************************
5826 ****************************************************************************/
5827 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5828                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5829                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5830                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5831                                 POLICY_HND *handle)
5832 {
5833         NT_PRINTER_INFO_LEVEL *printer = NULL;
5834         fstring name;
5835         int     snum;
5836         WERROR err = WERR_OK;
5837
5838         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5839                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5840                 return WERR_NOMEM;
5841         }
5842
5843         ZERO_STRUCTP(printer);
5844
5845         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5846         if (!convert_printer_info(info, printer, 2)) {
5847                 free_a_printer(&printer, 2);
5848                 return WERR_NOMEM;
5849         }
5850
5851         /* check to see if the printer already exists */
5852
5853         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5854                 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n", 
5855                         printer->info_2->sharename));
5856                 free_a_printer(&printer, 2);
5857                 return WERR_PRINTER_ALREADY_EXISTS;
5858         }
5859
5860         if (*lp_addprinter_cmd() )
5861                 if ( !add_printer_hook(printer) ) {
5862                         free_a_printer(&printer,2);
5863                         return WERR_ACCESS_DENIED;
5864         }
5865
5866         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
5867              printer->info_2->sharename);
5868
5869         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5870                 free_a_printer(&printer,2);
5871                 return WERR_ACCESS_DENIED;
5872         }
5873
5874         /* you must be a printer admin to add a new printer */
5875         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5876                 free_a_printer(&printer,2);
5877                 return WERR_ACCESS_DENIED;              
5878         }
5879         
5880         /*
5881          * Do sanity check on the requested changes for Samba.
5882          */
5883
5884         if (!check_printer_ok(printer->info_2, snum)) {
5885                 free_a_printer(&printer,2);
5886                 return WERR_INVALID_PARAM;
5887         }
5888
5889     /*
5890          * When a printer is created, the drivername bound to the printer is used
5891          * to lookup previously saved driver initialization info, which is then 
5892          * bound to the new printer, simulating what happens in the Windows arch.
5893          */
5894         set_driver_init(printer, 2);
5895         
5896         /* write the ASCII on disk */
5897         err = add_a_printer(*printer, 2);
5898         if (!W_ERROR_IS_OK(err)) {
5899                 free_a_printer(&printer,2);
5900                 return err;
5901         }
5902
5903         if (!open_printer_hnd(p, handle, name)) {
5904                 /* Handle open failed - remove addition. */
5905                 del_a_printer(printer->info_2->sharename);
5906                 free_a_printer(&printer,2);
5907                 return WERR_ACCESS_DENIED;
5908         }
5909
5910         free_a_printer(&printer,2);
5911
5912         srv_spoolss_sendnotify(p, handle);
5913
5914         return WERR_OK;
5915 }
5916
5917 /****************************************************************************
5918 ****************************************************************************/
5919
5920 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5921 {
5922         UNISTR2 *uni_srv_name = &q_u->server_name;
5923         uint32 level = q_u->level;
5924         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5925         uint32 unk0 = q_u->unk0;
5926         uint32 unk1 = q_u->unk1;
5927         uint32 unk2 = q_u->unk2;
5928         uint32 unk3 = q_u->unk3;
5929         uint32 user_switch = q_u->user_switch;
5930         SPOOL_USER_CTR *user = &q_u->user_ctr;
5931         POLICY_HND *handle = &r_u->handle;
5932
5933         switch (level) {
5934                 case 1:
5935                         /* we don't handle yet */
5936                         /* but I know what to do ... */
5937                         return WERR_UNKNOWN_LEVEL;
5938                 case 2:
5939                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5940                                                             unk0, unk1, unk2, unk3,
5941                                                             user_switch, user, handle);
5942                 default:
5943                         return WERR_UNKNOWN_LEVEL;
5944         }
5945 }
5946
5947 /****************************************************************************
5948 ****************************************************************************/
5949
5950 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5951 {
5952 /*      UNISTR2 *server_name = &q_u->server_name; - notused. */
5953         uint32 level = q_u->level;
5954         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5955         WERROR err = WERR_OK;
5956         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5957         struct current_user user;
5958         
5959         ZERO_STRUCT(driver);
5960
5961         get_current_user(&user, p);     
5962         
5963         if (!convert_printer_driver_info(info, &driver, level)) {
5964                 err = WERR_NOMEM;
5965                 goto done;
5966         }
5967
5968         DEBUG(5,("Cleaning driver's information\n"));
5969         err = clean_up_driver_struct(driver, level, &user);
5970         if (!W_ERROR_IS_OK(err))
5971                 goto done;
5972
5973         DEBUG(5,("Moving driver to final destination\n"));
5974         if(!move_driver_to_download_area(driver, level, &user, &err)) {
5975                 if (W_ERROR_IS_OK(err))
5976                         err = WERR_ACCESS_DENIED;
5977                 goto done;
5978         }
5979
5980         if (add_a_printer_driver(driver, level)!=0) {
5981                 err = WERR_ACCESS_DENIED;
5982                 goto done;
5983         }
5984
5985  done:
5986         free_a_printer_driver(driver, level);
5987         return err;
5988 }
5989
5990 /****************************************************************************
5991 ****************************************************************************/
5992 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5993 {
5994         init_unistr(&info->name, name);
5995 }
5996
5997 /****************************************************************************
5998 ****************************************************************************/
5999 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6000 {
6001         pstring path;
6002         pstring long_archi;
6003         pstring short_archi;
6004         DRIVER_DIRECTORY_1 *info=NULL;
6005
6006         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6007
6008         if (get_short_archi(short_archi, long_archi)==False)
6009                 return WERR_INVALID_ENVIRONMENT;
6010
6011         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6012                 return WERR_NOMEM;
6013
6014         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6015
6016         DEBUG(4,("printer driver directory: [%s]\n", path));
6017
6018         fill_driverdir_1(info, path);
6019         
6020         *needed += spoolss_size_driverdir_info_1(info);
6021
6022         if (!alloc_buffer_size(buffer, *needed)) {
6023                 SAFE_FREE(info);
6024                 return WERR_INSUFFICIENT_BUFFER;
6025         }
6026
6027         smb_io_driverdir_1("", buffer, info, 0);
6028
6029         SAFE_FREE(info);
6030         
6031         if (*needed > offered)
6032                 return WERR_INSUFFICIENT_BUFFER;
6033
6034         return WERR_OK;
6035 }
6036
6037 /****************************************************************************
6038 ****************************************************************************/
6039
6040 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6041 {
6042         UNISTR2 *name = &q_u->name;
6043         UNISTR2 *uni_environment = &q_u->environment;
6044         uint32 level = q_u->level;
6045         NEW_BUFFER *buffer = NULL;
6046         uint32 offered = q_u->offered;
6047         uint32 *needed = &r_u->needed;
6048
6049         /* that's an [in out] buffer */
6050         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6051         buffer = r_u->buffer;
6052
6053         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6054
6055         *needed=0;
6056
6057         switch(level) {
6058         case 1:
6059                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6060         default:
6061                 return WERR_UNKNOWN_LEVEL;
6062         }
6063 }
6064         
6065 /****************************************************************************
6066 ****************************************************************************/
6067
6068 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6069 {
6070         POLICY_HND *handle = &q_u->handle;
6071         uint32 idx = q_u->index;
6072         uint32 in_value_len = q_u->valuesize;
6073         uint32 in_data_len = q_u->datasize;
6074         uint32 *out_max_value_len = &r_u->valuesize;
6075         uint16 **out_value = &r_u->value;
6076         uint32 *out_value_len = &r_u->realvaluesize;
6077         uint32 *out_type = &r_u->type;
6078         uint32 *out_max_data_len = &r_u->datasize;
6079         uint8  **data_out = &r_u->data;
6080         uint32 *out_data_len = &r_u->realdatasize;
6081
6082         NT_PRINTER_INFO_LEVEL *printer = NULL;
6083         
6084         fstring value;
6085         
6086         uint32 param_index;
6087         uint32 biggest_valuesize;
6088         uint32 biggest_datasize;
6089         uint32 data_len;
6090         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6091         int snum;
6092         uint8 *data=NULL;
6093         uint32 type;
6094         WERROR result;
6095
6096         ZERO_STRUCT(printer);
6097         
6098         *out_type=0;
6099
6100         *out_max_data_len=0;
6101         *data_out=NULL;
6102         *out_data_len=0;
6103
6104         DEBUG(5,("spoolss_enumprinterdata\n"));
6105
6106         if (!Printer) {
6107                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6108                 return WERR_BADFID;
6109         }
6110
6111         if (!get_printer_snum(p,handle, &snum))
6112                 return WERR_BADFID;
6113         
6114         result = get_a_printer(&printer, 2, lp_servicename(snum));
6115         if (!W_ERROR_IS_OK(result))
6116                 return result;
6117
6118         /*
6119          * The NT machine wants to know the biggest size of value and data
6120          *
6121          * cf: MSDN EnumPrinterData remark section
6122          */
6123         if ( (in_value_len==0) && (in_data_len==0) ) {
6124                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6125
6126 #if 0
6127                 /*
6128                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6129                  * if this parameter size doesn't exist.
6130                  * Ok - my opinion here is that the client is not asking for the greatest
6131                  * possible size of all the parameters, but is asking specifically for the size needed
6132                  * for this specific parameter. In that case we can remove the loop below and
6133                  * simplify this lookup code considerably. JF - comments welcome. JRA.
6134                  */
6135
6136                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6137                         SAFE_FREE(data);
6138                         free_a_printer(&printer, 2);
6139                         return WERR_NO_MORE_ITEMS;
6140                 }
6141 #endif
6142
6143                 SAFE_FREE(data);
6144
6145                 param_index=0;
6146                 biggest_valuesize=0;
6147                 biggest_datasize=0;
6148                 
6149                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6150                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6151                         if (data_len > biggest_datasize) biggest_datasize=data_len;
6152
6153                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6154
6155                         SAFE_FREE(data);
6156                         param_index++;
6157                 }
6158
6159                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6160                 *out_value_len=2*(1+biggest_valuesize);
6161                 *out_data_len=biggest_datasize;
6162
6163                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6164
6165                 free_a_printer(&printer, 2);
6166                 return WERR_OK;
6167         }
6168         
6169         /*
6170          * the value len is wrong in NT sp3
6171          * that's the number of bytes not the number of unicode chars
6172          */
6173
6174         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6175
6176                 SAFE_FREE(data);
6177                 free_a_printer(&printer, 2);
6178
6179                 /* out_value should default to "" or else NT4 has
6180                    problems unmarshalling the response */
6181
6182                 *out_max_value_len=(in_value_len/sizeof(uint16));
6183                 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
6184                         return WERR_NOMEM;
6185
6186                 ZERO_STRUCTP(*out_value);
6187                 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6188
6189                 /* the data is counted in bytes */
6190                 *out_max_data_len = in_data_len;
6191                 *out_data_len = in_data_len;
6192                 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
6193                         return WERR_NOMEM;
6194
6195                 memset(*data_out,'\0',in_data_len);
6196
6197                 return WERR_NO_MORE_ITEMS;
6198         }
6199
6200         free_a_printer(&printer, 2);
6201
6202         /*
6203          * the value is:
6204          * - counted in bytes in the request
6205          * - counted in UNICODE chars in the max reply
6206          * - counted in bytes in the real size
6207          *
6208          * take a pause *before* coding not *during* coding
6209          */
6210         
6211         *out_max_value_len=(in_value_len/sizeof(uint16));
6212         if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6213                 SAFE_FREE(data);
6214                 return WERR_NOMEM;
6215         }
6216         
6217         *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6218
6219         *out_type=type;
6220
6221         /* the data is counted in bytes */
6222         *out_max_data_len=in_data_len;
6223         if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6224                 SAFE_FREE(data);
6225                 return WERR_NOMEM;
6226         }
6227         
6228         memcpy(*data_out, data, (size_t)data_len);
6229         *out_data_len=data_len;
6230
6231         SAFE_FREE(data);
6232         
6233         return WERR_OK;
6234 }
6235
6236 /****************************************************************************
6237 ****************************************************************************/
6238
6239 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6240 {
6241         POLICY_HND *handle = &q_u->handle;
6242         UNISTR2 *value = &q_u->value;
6243         uint32 type = q_u->type;
6244 /*      uint32 max_len = q_u->max_len; - notused. */
6245         uint8 *data = q_u->data;
6246         uint32 real_len = q_u->real_len;
6247 /*      uint32 numeric_data = q_u->numeric_data; - notused. */
6248
6249         NT_PRINTER_INFO_LEVEL *printer = NULL;
6250         NT_PRINTER_PARAM *param = NULL, old_param;
6251         int snum=0;
6252         WERROR status = WERR_OK;
6253         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6254         
6255         DEBUG(5,("spoolss_setprinterdata\n"));
6256
6257         if (!Printer) {
6258                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6259                 return WERR_BADFID;
6260         }
6261
6262         if (!get_printer_snum(p,handle, &snum))
6263                 return WERR_BADFID;
6264
6265         ZERO_STRUCT(old_param);
6266
6267         /* 
6268          * Access check : NT returns "access denied" if you make a 
6269          * SetPrinterData call without the necessary privildge.
6270          * we were originally returning OK if nothing changed
6271          * which made Win2k issue **a lot** of SetPrinterData
6272          * when connecting to a printer  --jerry
6273          */
6274
6275         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6276                 DEBUG(3, ("security descriptor change denied by existing "
6277                           "security descriptor\n"));
6278                 status = WERR_ACCESS_DENIED;
6279                 goto done;
6280         }
6281
6282         /* Check if we are making any changes or not.  Return true if
6283            nothing is actually changing.  This is not needed anymore but
6284            has been left in as an optimization to keep from from
6285            writing to disk as often  --jerry  */
6286
6287         status = get_a_printer(&printer, 2, lp_servicename(snum));
6288         if (!W_ERROR_IS_OK(status))
6289                 return status;
6290
6291         convert_specific_param(&param, value , type, data, real_len);
6292
6293 #if 0
6294         if (get_specific_param(*printer, 2, param->value, &old_param.data,
6295                                &old_param.type, (uint32 *)&old_param.data_len)) {
6296
6297                 if (param->type == old_param.type &&
6298                     param->data_len == old_param.data_len &&
6299                     memcmp(param->data, old_param.data,
6300                            old_param.data_len) == 0) {
6301
6302                         DEBUG(3, ("setprinterdata hasn't changed\n"));
6303                         status = WERR_OK;
6304                         goto done;
6305                 }
6306         }
6307 #endif
6308
6309         unlink_specific_param_if_exist(printer->info_2, param);
6310         
6311         /*
6312          * When client side code sets a magic printer data key, detect it and save
6313          * the current printer data and the magic key's data (its the DEVMODE) for
6314          * future printer/driver initializations.
6315          */
6316         if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6317                 /*
6318                  * Set devmode and printer initialization info
6319                  */
6320                 status = save_driver_init(printer, 2, param);
6321         }
6322         else {
6323                 add_a_specific_param(printer->info_2, &param);
6324                 status = mod_a_printer(*printer, 2);
6325         }
6326
6327  done:
6328         free_a_printer(&printer, 2);
6329         if (param)
6330                 free_nt_printer_param(&param);
6331         SAFE_FREE(old_param.data);
6332
6333         return status;
6334 }
6335
6336 /****************************************************************************
6337 ****************************************************************************/
6338
6339 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6340 {
6341         POLICY_HND *handle = &q_u->handle;
6342         UNISTR2 *value = &q_u->valuename;
6343
6344         NT_PRINTER_INFO_LEVEL *printer = NULL;
6345         NT_PRINTER_PARAM param;
6346         int snum=0;
6347         WERROR status = WERR_OK;
6348         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6349         
6350         DEBUG(5,("spoolss_deleteprinterdata\n"));
6351         
6352         if (!Printer) {
6353                 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6354                 return WERR_BADFID;
6355         }
6356
6357         if (!get_printer_snum(p, handle, &snum))
6358                 return WERR_BADFID;
6359
6360         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6361                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6362                           "change denied by existing security descriptor\n"));
6363                 return WERR_ACCESS_DENIED;
6364         }
6365
6366         status = get_a_printer(&printer, 2, lp_servicename(snum));
6367         if (!W_ERROR_IS_OK(status))
6368                 return status;
6369
6370         ZERO_STRUCTP(&param);
6371         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6372
6373         if(!unlink_specific_param_if_exist(printer->info_2, &param))
6374                 status = WERR_INVALID_PARAM;
6375         else
6376                 status = mod_a_printer(*printer, 2);
6377
6378         free_a_printer(&printer, 2);
6379         return status;
6380 }
6381
6382 /****************************************************************************
6383 ****************************************************************************/
6384
6385 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6386 {
6387         POLICY_HND *handle = &q_u->handle;
6388 /*      uint32 level = q_u->level; - notused. */
6389         FORM *form = &q_u->form;
6390         nt_forms_struct tmpForm;
6391
6392         int count=0;
6393         nt_forms_struct *list=NULL;
6394         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6395
6396         DEBUG(5,("spoolss_addform\n"));
6397
6398         if (!Printer) {
6399                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6400                 return WERR_BADFID;
6401         }
6402
6403         /* 
6404          * FIXME!!  Feels like there should be an access check here, but haven't
6405          * had time to verify.  --jerry
6406          */
6407
6408         /* can't add if builtin */
6409         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6410                 return WERR_INVALID_PARAM;
6411         }
6412
6413         count=get_ntforms(&list);
6414         if(!add_a_form(&list, form, &count))
6415                 return WERR_NOMEM;
6416         write_ntforms(&list, count);
6417
6418         SAFE_FREE(list);
6419
6420         return WERR_OK;
6421 }
6422
6423 /****************************************************************************
6424 ****************************************************************************/
6425
6426 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6427 {
6428         POLICY_HND *handle = &q_u->handle;
6429         UNISTR2 *form_name = &q_u->name;
6430         nt_forms_struct tmpForm;
6431         int count=0;
6432         WERROR ret = WERR_OK;
6433         nt_forms_struct *list=NULL;
6434         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6435
6436         DEBUG(5,("spoolss_deleteform\n"));
6437
6438         if (!Printer) {
6439                 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6440                 return WERR_BADFID;
6441         }
6442
6443         /* can't delete if builtin */
6444         if (get_a_builtin_ntform(form_name,&tmpForm)) {
6445                 return WERR_INVALID_PARAM;
6446         }
6447
6448         count = get_ntforms(&list);
6449         if(!delete_a_form(&list, form_name, &count, &ret))
6450                 return WERR_INVALID_PARAM;
6451
6452         SAFE_FREE(list);
6453
6454         return ret;
6455 }
6456
6457 /****************************************************************************
6458 ****************************************************************************/
6459
6460 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6461 {
6462         POLICY_HND *handle = &q_u->handle;
6463 /*      UNISTR2 *uni_name = &q_u->name; - notused. */
6464 /*      uint32 level = q_u->level; - notused. */
6465         FORM *form = &q_u->form;
6466         nt_forms_struct tmpForm;
6467
6468         int count=0;
6469         nt_forms_struct *list=NULL;
6470         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6471
6472         DEBUG(5,("spoolss_setform\n"));
6473
6474         if (!Printer) {
6475                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6476                 return WERR_BADFID;
6477         }
6478         /* can't set if builtin */
6479         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6480                 return WERR_INVALID_PARAM;
6481         }
6482
6483         count=get_ntforms(&list);
6484         update_a_form(&list, form, count);
6485         write_ntforms(&list, count);
6486
6487         SAFE_FREE(list);
6488
6489         return WERR_OK;
6490 }
6491
6492 /****************************************************************************
6493  enumprintprocessors level 1.
6494 ****************************************************************************/
6495 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6496 {
6497         PRINTPROCESSOR_1 *info_1=NULL;
6498         
6499         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6500                 return WERR_NOMEM;
6501
6502         (*returned) = 0x1;
6503         
6504         init_unistr(&info_1->name, "winprint");
6505
6506         *needed += spoolss_size_printprocessor_info_1(info_1);
6507
6508         if (!alloc_buffer_size(buffer, *needed))
6509                 return WERR_INSUFFICIENT_BUFFER;
6510
6511         smb_io_printprocessor_info_1("", buffer, info_1, 0);
6512
6513         SAFE_FREE(info_1);
6514
6515         if (*needed > offered) {
6516                 *returned=0;
6517                 return WERR_INSUFFICIENT_BUFFER;
6518         }
6519
6520         return WERR_OK;
6521 }
6522
6523 /****************************************************************************
6524 ****************************************************************************/
6525
6526 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6527 {
6528 /*      UNISTR2 *name = &q_u->name; - notused. */
6529 /*      UNISTR2 *environment = &q_u->environment; - notused. */
6530         uint32 level = q_u->level;
6531     NEW_BUFFER *buffer = NULL;
6532         uint32 offered = q_u->offered;
6533     uint32 *needed = &r_u->needed;
6534         uint32 *returned = &r_u->returned;
6535
6536         /* that's an [in out] buffer */
6537         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6538         buffer = r_u->buffer;
6539
6540         DEBUG(5,("spoolss_enumprintprocessors\n"));
6541
6542         /*
6543          * Enumerate the print processors ...
6544          *
6545          * Just reply with "winprint", to keep NT happy
6546          * and I can use my nice printer checker.
6547          */
6548         
6549         *returned=0;
6550         *needed=0;
6551         
6552         switch (level) {
6553         case 1:
6554                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6555         default:
6556                 return WERR_UNKNOWN_LEVEL;
6557         }
6558 }
6559
6560 /****************************************************************************
6561  enumprintprocdatatypes level 1.
6562 ****************************************************************************/
6563 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6564 {
6565         PRINTPROCDATATYPE_1 *info_1=NULL;
6566         
6567         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6568                 return WERR_NOMEM;
6569
6570         (*returned) = 0x1;
6571         
6572         init_unistr(&info_1->name, "RAW");
6573
6574         *needed += spoolss_size_printprocdatatype_info_1(info_1);
6575
6576         if (!alloc_buffer_size(buffer, *needed))
6577                 return WERR_INSUFFICIENT_BUFFER;
6578
6579         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6580
6581         SAFE_FREE(info_1);
6582
6583         if (*needed > offered) {
6584                 *returned=0;
6585                 return WERR_INSUFFICIENT_BUFFER;
6586         }
6587
6588         return WERR_OK;
6589 }
6590
6591 /****************************************************************************
6592 ****************************************************************************/
6593
6594 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6595 {
6596 /*      UNISTR2 *name = &q_u->name; - notused. */
6597 /*      UNISTR2 *processor = &q_u->processor; - notused. */
6598         uint32 level = q_u->level;
6599         NEW_BUFFER *buffer = NULL;
6600         uint32 offered = q_u->offered;
6601         uint32 *needed = &r_u->needed;
6602         uint32 *returned = &r_u->returned;
6603
6604         /* that's an [in out] buffer */
6605         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6606         buffer = r_u->buffer;
6607
6608         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6609         
6610         *returned=0;
6611         *needed=0;
6612         
6613         switch (level) {
6614         case 1:
6615                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6616         default:
6617                 return WERR_UNKNOWN_LEVEL;
6618         }
6619 }
6620
6621 /****************************************************************************
6622  enumprintmonitors level 1.
6623 ****************************************************************************/
6624
6625 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6626 {
6627         PRINTMONITOR_1 *info_1=NULL;
6628         
6629         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6630                 return WERR_NOMEM;
6631
6632         (*returned) = 0x1;
6633         
6634         init_unistr(&info_1->name, "Local Port");
6635
6636         *needed += spoolss_size_printmonitor_info_1(info_1);
6637
6638         if (!alloc_buffer_size(buffer, *needed))
6639                 return WERR_INSUFFICIENT_BUFFER;
6640
6641         smb_io_printmonitor_info_1("", buffer, info_1, 0);
6642
6643         SAFE_FREE(info_1);
6644
6645         if (*needed > offered) {
6646                 *returned=0;
6647                 return WERR_INSUFFICIENT_BUFFER;
6648         }
6649
6650         return WERR_OK;
6651 }
6652
6653 /****************************************************************************
6654  enumprintmonitors level 2.
6655 ****************************************************************************/
6656 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6657 {
6658         PRINTMONITOR_2 *info_2=NULL;
6659         
6660         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6661                 return WERR_NOMEM;
6662
6663         (*returned) = 0x1;
6664         
6665         init_unistr(&info_2->name, "Local Port");
6666         init_unistr(&info_2->environment, "Windows NT X86");
6667         init_unistr(&info_2->dll_name, "localmon.dll");
6668
6669         *needed += spoolss_size_printmonitor_info_2(info_2);
6670
6671         if (!alloc_buffer_size(buffer, *needed))
6672                 return WERR_INSUFFICIENT_BUFFER;
6673
6674         smb_io_printmonitor_info_2("", buffer, info_2, 0);
6675
6676         SAFE_FREE(info_2);
6677
6678         if (*needed > offered) {
6679                 *returned=0;
6680                 return WERR_INSUFFICIENT_BUFFER;
6681         }
6682
6683         return WERR_OK;
6684 }
6685
6686 /****************************************************************************
6687 ****************************************************************************/
6688
6689 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6690 {
6691 /*      UNISTR2 *name = &q_u->name; - notused. */
6692         uint32 level = q_u->level;
6693     NEW_BUFFER *buffer = NULL;
6694         uint32 offered = q_u->offered;
6695     uint32 *needed = &r_u->needed;
6696         uint32 *returned = &r_u->returned;
6697
6698         /* that's an [in out] buffer */
6699         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6700         buffer = r_u->buffer;
6701
6702         DEBUG(5,("spoolss_enumprintmonitors\n"));
6703
6704         /*
6705          * Enumerate the print monitors ...
6706          *
6707          * Just reply with "Local Port", to keep NT happy
6708          * and I can use my nice printer checker.
6709          */
6710         
6711         *returned=0;
6712         *needed=0;
6713         
6714         switch (level) {
6715         case 1:
6716                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6717         case 2:
6718                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6719         default:
6720                 return WERR_UNKNOWN_LEVEL;
6721         }
6722 }
6723
6724 /****************************************************************************
6725 ****************************************************************************/
6726 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6727 {
6728         int i=0;
6729         BOOL found=False;
6730         JOB_INFO_1 *info_1=NULL;
6731
6732         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6733
6734         if (info_1 == NULL) {
6735                 SAFE_FREE(queue);
6736                 return WERR_NOMEM;
6737         }
6738                 
6739         for (i=0; i<count && found==False; i++) {
6740                 if (queue[i].job==(int)jobid)
6741                         found=True;
6742         }
6743         
6744         if (found==False) {
6745                 SAFE_FREE(queue);
6746                 SAFE_FREE(info_1);
6747                 /* NT treats not found as bad param... yet another bad choice */
6748                 return WERR_INVALID_PARAM;
6749         }
6750         
6751         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6752         
6753         SAFE_FREE(queue);
6754         
6755         *needed += spoolss_size_job_info_1(info_1);
6756
6757         if (!alloc_buffer_size(buffer, *needed)) {
6758                 SAFE_FREE(info_1);
6759                 return WERR_INSUFFICIENT_BUFFER;
6760         }
6761
6762         smb_io_job_info_1("", buffer, info_1, 0);
6763
6764         SAFE_FREE(info_1);
6765
6766         if (*needed > offered)
6767                 return WERR_INSUFFICIENT_BUFFER;
6768
6769         return WERR_OK;
6770 }
6771
6772
6773 /****************************************************************************
6774 ****************************************************************************/
6775 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6776 {
6777         int i=0;
6778         BOOL found=False;
6779         JOB_INFO_2 *info_2;
6780         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6781         WERROR ret;
6782
6783         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6784
6785         ZERO_STRUCTP(info_2);
6786
6787         if (info_2 == NULL) {
6788                 SAFE_FREE(queue);
6789                 return WERR_NOMEM;
6790         }
6791
6792         for (i=0; i<count && found==False; i++) {
6793                 if (queue[i].job==(int)jobid)
6794                         found=True;
6795         }
6796         
6797         if (found==False) {
6798                 SAFE_FREE(queue);
6799                 SAFE_FREE(info_2);
6800                 /* NT treats not found as bad param... yet another bad choice */
6801                 return WERR_INVALID_PARAM;
6802         }
6803         
6804         ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6805         if (!W_ERROR_IS_OK(ret)) {
6806                 SAFE_FREE(queue);
6807                 return ret;
6808         }
6809
6810         fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6811         
6812         free_a_printer(&ntprinter, 2);
6813         SAFE_FREE(queue);
6814         
6815         *needed += spoolss_size_job_info_2(info_2);
6816
6817         if (!alloc_buffer_size(buffer, *needed)) {
6818                 SAFE_FREE(info_2);
6819                 return WERR_INSUFFICIENT_BUFFER;
6820         }
6821
6822         smb_io_job_info_2("", buffer, info_2, 0);
6823
6824         free_job_info_2(info_2);
6825         SAFE_FREE(info_2);
6826
6827         if (*needed > offered)
6828                 return WERR_INSUFFICIENT_BUFFER;
6829
6830         return WERR_OK;
6831 }
6832
6833 /****************************************************************************
6834 ****************************************************************************/
6835
6836 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6837 {
6838         POLICY_HND *handle = &q_u->handle;
6839         uint32 jobid = q_u->jobid;
6840         uint32 level = q_u->level;
6841         NEW_BUFFER *buffer = NULL;
6842         uint32 offered = q_u->offered;
6843         uint32 *needed = &r_u->needed;
6844
6845         int snum;
6846         int count;
6847         print_queue_struct *queue=NULL;
6848         print_status_struct prt_status;
6849
6850         /* that's an [in out] buffer */
6851         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6852         buffer = r_u->buffer;
6853
6854         DEBUG(5,("spoolss_getjob\n"));
6855         
6856         *needed=0;
6857         
6858         if (!get_printer_snum(p, handle, &snum))
6859                 return WERR_BADFID;
6860         
6861         count = print_queue_status(snum, &queue, &prt_status);
6862         
6863         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6864                      count, prt_status.status, prt_status.message));
6865                 
6866         switch (level) {
6867         case 1:
6868                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6869         case 2:
6870                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6871         default:
6872                 SAFE_FREE(queue);
6873                 return WERR_UNKNOWN_LEVEL;
6874         }
6875 }
6876
6877 /********************************************************************
6878  * spoolss_getprinterdataex
6879  ********************************************************************/
6880
6881 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6882 {
6883         POLICY_HND      *handle = &q_u->handle;
6884         uint32          in_size = q_u->size;
6885         uint32          *type = &r_u->type;
6886         uint32          *out_size = &r_u->size;
6887         uint8           **data = &r_u->data;
6888         uint32          *needed = &r_u->needed;
6889
6890         fstring         key, value;
6891         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6892         BOOL            found = False;
6893
6894         DEBUG(4,("_spoolss_getprinterdataex\n"));
6895
6896         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6897         unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6898
6899         /* in case of problem, return some default values */
6900         *needed=0;
6901         *type=0;
6902         *out_size=0;
6903
6904                 
6905         if (!Printer) {
6906                 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6907                         return WERR_NOMEM;
6908                 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6909                 return WERR_BADFID;
6910         }
6911
6912                 
6913         /* Is the handle to a printer or to the server? */
6914
6915         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6916         {
6917                 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6918                 return WERR_INVALID_PARAM;
6919         }
6920         else
6921         {
6922                 /* 
6923                  * From MSDN documentation of GetPrinterDataEx: pass request
6924                  * to GetPrinterData if key is "PrinterDriverData". This is 
6925                  * the only key we really support. Other keys to implement:
6926                  * (a) DsDriver
6927                  * (b) DsSpooler
6928                  * (c) PnPData
6929                  */
6930            
6931                 if (strcmp(key, "PrinterDriverData") != 0)
6932                         return WERR_INVALID_PARAM;
6933
6934                 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6935                 found = getprinterdata_printer(p, p->mem_ctx, handle, value, 
6936                         type, data, needed, in_size);
6937                 
6938         }
6939          
6940         if (!found) {
6941                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6942                 
6943                 /* reply this param doesn't exist */
6944                 if (*out_size) {
6945                         if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6946                                 return WERR_NOMEM;
6947                 } else {
6948                         *data = NULL;
6949                 }
6950
6951                 return WERR_INVALID_PARAM;
6952         }
6953         
6954         if (*needed > *out_size)
6955                 return WERR_MORE_DATA;
6956         else
6957                 return WERR_OK;
6958 }
6959
6960 /********************************************************************
6961  * spoolss_setprinterdata
6962  ********************************************************************/
6963
6964 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6965 {
6966         SPOOL_Q_SETPRINTERDATA q_u_local;
6967         SPOOL_R_SETPRINTERDATA r_u_local;
6968         fstring key;
6969
6970         DEBUG(4,("_spoolss_setprinterdataex\n"));
6971
6972         /* From MSDN documentation of SetPrinterDataEx: pass request to
6973            SetPrinterData if key is "PrinterDriverData" */
6974
6975         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6976
6977         if (strcmp(key, "PrinterDriverData") == 0)
6978                 return WERR_INVALID_PARAM;
6979                 
6980         ZERO_STRUCT(q_u_local); 
6981         ZERO_STRUCT(r_u_local); 
6982         
6983         /* make a copy to call _spoolss_setprinterdata() */
6984
6985         memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
6986         copy_unistr2(&q_u_local.value, &q_u->value);
6987         q_u_local.type = q_u->type;
6988         q_u_local.max_len = q_u->max_len;
6989         q_u_local.data = q_u->data;
6990         q_u_local.real_len = q_u->real_len;
6991         q_u_local.numeric_data = q_u->numeric_data;
6992                 
6993         return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
6994 }
6995
6996 /********************************************************************
6997  * spoolss_enumprinterkey
6998  ********************************************************************/
6999
7000 /* constants for EnumPrinterKey() */
7001 #define ENUMERATED_KEY_SIZE     19
7002
7003 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7004 {
7005         fstring key;
7006         uint16  enumkeys[ENUMERATED_KEY_SIZE+1];
7007         char*   ptr = NULL;
7008         int     i;
7009         char    *PrinterKey = "PrinterDriverData";
7010
7011         DEBUG(4,("_spoolss_enumprinterkey\n"));
7012
7013         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7014
7015         /* 
7016          * we only support enumating all keys (key == "")
7017          * Of course, the only key we support is the "PrinterDriverData" 
7018          * key
7019          */     
7020         if (strlen(key) == 0)
7021         {
7022                 r_u->needed = ENUMERATED_KEY_SIZE *2;
7023                 if (q_u->size < r_u->needed)
7024                         return WERR_MORE_DATA;
7025         
7026                 ptr = PrinterKey;
7027                 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7028                 {
7029                         enumkeys[i] = (uint16)(*ptr);
7030                         ptr++;
7031                 }
7032
7033                 /* tag of with 2 '\0's */
7034                 enumkeys[i++] = '\0';
7035                 enumkeys[i] = '\0';
7036         
7037                 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7038                         return WERR_BADFILE;
7039                         
7040                 return WERR_OK;
7041         }
7042         
7043         /* The "PrinterDriverData" key should have no subkeys */
7044         if (strcmp(key, PrinterKey) == 0)
7045         {
7046                 r_u-> needed = 2;
7047                 if (q_u->size < r_u->needed)
7048                         return WERR_MORE_DATA;
7049                 enumkeys[0] = 0x0;
7050                 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7051                         return WERR_BADFILE;
7052                         
7053                 return WERR_OK;
7054         }
7055         
7056
7057         /* The return value for an unknown key is documented in MSDN
7058            EnumPrinterKey description */
7059         return WERR_BADFILE;
7060 }
7061
7062 /********************************************************************
7063  * spoolss_enumprinterdataex
7064  ********************************************************************/
7065
7066 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7067 {
7068         POLICY_HND      *handle = &q_u->handle; 
7069         uint32          in_size = q_u->size;
7070         uint32          num_entries, 
7071                         needed;
7072         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7073         PRINTER_ENUM_VALUES     *enum_values = NULL;
7074         fstring         key, value;
7075         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7076         int             snum;
7077         uint32          param_index, 
7078                         data_len,
7079                         type;
7080         WERROR          result;
7081         uint8           *data=NULL;
7082         
7083
7084         DEBUG(4,("_spoolss_enumprinterdataex\n"));
7085
7086         if (!Printer) {
7087                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
7088                 return WERR_BADFID;
7089         }
7090
7091                 
7092         /* 
7093          * The only key we support is "PrinterDriverData". This should return 
7094          > an array of all the key/value pairs returned by EnumPrinterDataSee 
7095          * _spoolss_getprinterdataex() for details    --jerry
7096          */
7097    
7098         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7099         if (strcmp(key, "PrinterDriverData") != 0)
7100         {
7101                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7102                 return WERR_INVALID_PARAM;
7103         }
7104
7105
7106         if (!get_printer_snum(p,handle, &snum))
7107                 return WERR_BADFID;
7108         
7109         ZERO_STRUCT(printer);
7110         result = get_a_printer(&printer, 2, lp_servicename(snum));
7111         if (!W_ERROR_IS_OK(result))
7112                 return result;
7113
7114         
7115         /* 
7116          * loop through all params and build the array to pass 
7117          * back to the  client 
7118          */
7119         result = WERR_OK;
7120         param_index             = 0;
7121         needed                  = 0;
7122         num_entries             = 0;
7123         
7124         while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) 
7125         {
7126                 PRINTER_ENUM_VALUES     *ptr;
7127                 uint32                  add_len = 0;
7128
7129                 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7130
7131                 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7132                 {
7133                         DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7134                         result = WERR_NOMEM;
7135                         goto done;
7136                 }
7137                 enum_values = ptr;
7138
7139                 /* copy the data */
7140                 init_unistr(&enum_values[num_entries].valuename, value);
7141                 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7142                 enum_values[num_entries].type      = type;
7143                 
7144                 /* 
7145                  * NULL terminate REG_SZ
7146                  * FIXME!!!  We should not be correctly problems in the way
7147                  * we store PrinterData here.  Need to investogate 
7148                  * SetPrinterData[Ex]   --jerry
7149                  */
7150                 
7151                 if (type == REG_SZ) {
7152                         /* fix alignment if the string was stored 
7153                            in a bizarre fashion */
7154                         if ((data_len % 2) == 0)
7155                                 add_len = 2;
7156                         else
7157                                 add_len = data_len % 2;
7158                 }
7159                 
7160                 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7161                         DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7162                         result = WERR_NOMEM;
7163                         goto done;
7164                 }
7165                 memcpy(enum_values[num_entries].data, data, data_len);
7166                 enum_values[num_entries].data_len = data_len + add_len;
7167
7168                 /* keep track of the size of the array in bytes */
7169                 
7170                 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7171                 
7172                 num_entries++;
7173                 param_index++;
7174         }
7175         
7176         r_u->needed             = needed;
7177         r_u->returned           = num_entries;
7178
7179         if (needed > in_size) {
7180                 result = WERR_MORE_DATA;
7181                 goto done;
7182         }
7183                 
7184         /* copy data into the reply */
7185         
7186         r_u->ctr.size           = r_u->needed;
7187         r_u->ctr.size_of_array  = r_u->returned;
7188         r_u->ctr.values         = enum_values;
7189         
7190         
7191                 
7192 done:   
7193         free_a_printer(&printer, 2);
7194
7195         return result;
7196 }
7197
7198 /****************************************************************************
7199 ****************************************************************************/
7200
7201 /* Disabled because it doesn't fix the bug I am looking at but it would be
7202    a shame to throw away the code. -tpot */
7203
7204 #if 0
7205
7206 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7207 {
7208         init_unistr(&info->name, name);
7209 }
7210
7211 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
7212                                                  UNISTR2 *environment, 
7213                                                  NEW_BUFFER *buffer, 
7214                                                  uint32 offered, 
7215                                                  uint32 *needed)
7216 {
7217         pstring path;
7218         pstring long_archi;
7219         pstring short_archi;
7220         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7221
7222         unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7223
7224         if (get_short_archi(short_archi, long_archi)==False)
7225                 return WERR_INVALID_ENVIRONMENT;
7226
7227         if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7228                 return WERR_NOMEM;
7229
7230         /* Not sure what to return here - are UNC names valid here?.
7231            Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7232            which is pretty bogus for a RPC. */
7233
7234         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7235
7236         DEBUG(4,("print processor directory: [%s]\n", path));
7237
7238         fill_printprocessordirectory_1(info, path);
7239         
7240         *needed += spoolss_size_printprocessordirectory_info_1(info);
7241
7242         if (!alloc_buffer_size(buffer, *needed)) {
7243                 safe_free(info);
7244                 return WERR_INSUFFICIENT_BUFFER;
7245         }
7246
7247         smb_io_printprocessordirectory_1("", buffer, info, 0);
7248
7249         safe_free(info);
7250         
7251         if (*needed > offered)
7252                 return WERR_INSUFFICIENT_BUFFER;
7253         else
7254                 return WERR_OK;
7255 }
7256
7257 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7258 {
7259         uint32 level = q_u->level;
7260         NEW_BUFFER *buffer = NULL;
7261         uint32 offered = q_u->offered;
7262         uint32 *needed = &r_u->needed;
7263
7264         /* that's an [in out] buffer */
7265         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7266         buffer = r_u->buffer;
7267
7268         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7269         
7270         *needed=0;
7271
7272         switch(level) {
7273         case 1:
7274                 return getprintprocessordirectory_level_1
7275                   (&q_u->name, &q_u->environment, buffer, offered, needed);
7276         default:
7277                 return WERR_UNKNOWN_LEVEL;
7278         }
7279
7280         return WERR_ACCESS_DENIED;
7281 }
7282
7283 #endif