Added get_called_name() function, which replaces global_myname in printing
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7  *  Copyright (C) Jean François Micouleau      1998-2000.
8  *  Copyright (C) Jeremy Allison                    2001.
9  *  Copyright (C) Gerald Carter                2000-2001.
10  *  Copyright (C) Tim Potter                        2001.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31
32 #ifndef MAX_OPEN_PRINTER_EXS
33 #define MAX_OPEN_PRINTER_EXS 50
34 #endif
35
36 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
37 #define PRINTER_HANDLE_IS_PRINTER       0
38 #define PRINTER_HANDLE_IS_PRINTSERVER   1
39
40 struct table_node {
41         char    *long_archi;
42         char    *short_archi;
43         int     version;
44 };
45
46
47 /* structure to store the printer handles */
48 /* and a reference to what it's pointing to */
49 /* and the notify info asked about */
50 /* that's the central struct */
51 typedef struct _Printer{
52         BOOL document_started;
53         BOOL page_started;
54     int jobid; /* jobid in printing backend */
55         BOOL printer_type;
56         union {
57                 fstring handlename;
58                 fstring printerservername;
59         } dev;
60         uint32 type;
61         uint32 access;
62         struct {
63                 uint32 flags;
64                 uint32 options;
65                 fstring localmachine;
66                 uint32 printerlocal;
67                 SPOOL_NOTIFY_OPTION *option;
68                 POLICY_HND client_hnd;
69                 uint32 client_connected;
70         } notify;
71         struct {
72                 fstring machine;
73                 fstring user;
74         } client;
75 } Printer_entry;
76
77 typedef struct _counter_printer_0 {
78         ubi_dlNode Next;
79         ubi_dlNode Prev;
80         
81         int snum;
82         uint32 counter;
83 } counter_printer_0;
84
85 static ubi_dlList counter_list;
86
87 static struct cli_state cli;
88 static uint32 smb_connections=0;
89
90 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
91
92 /* translate between internal status numbers and NT status numbers */
93 static int nt_printj_status(int v)
94 {
95         switch (v) {
96         case LPQ_QUEUED:
97                 return 0;
98         case LPQ_PAUSED:
99                 return JOB_STATUS_PAUSED;
100         case LPQ_SPOOLING:
101                 return JOB_STATUS_SPOOLING;
102         case LPQ_PRINTING:
103                 return JOB_STATUS_PRINTING;
104         case LPQ_ERROR:
105                 return JOB_STATUS_ERROR;
106         case LPQ_DELETING:
107                 return JOB_STATUS_DELETING;
108         case LPQ_OFFLINE:
109                 return JOB_STATUS_OFFLINE;
110         case LPQ_PAPEROUT:
111                 return JOB_STATUS_PAPEROUT;
112         case LPQ_PRINTED:
113                 return JOB_STATUS_PRINTED;
114         case LPQ_DELETED:
115                 return JOB_STATUS_DELETED;
116         case LPQ_BLOCKED:
117                 return JOB_STATUS_BLOCKED;
118         case LPQ_USER_INTERVENTION:
119                 return JOB_STATUS_USER_INTERVENTION;
120         }
121         return 0;
122 }
123
124 static int nt_printq_status(int v)
125 {
126         switch (v) {
127         case LPQ_PAUSED:
128                 return PRINTER_STATUS_PAUSED;
129         case LPQ_QUEUED:
130         case LPQ_SPOOLING:
131         case LPQ_PRINTING:
132                 return 0;
133         }
134         return 0;
135 }
136
137 /****************************************************************************
138  Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
139 ****************************************************************************/
140
141 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
142 {
143         if (*pp == NULL)
144                 return;
145
146         SAFE_FREE((*pp)->ctr.type);
147         SAFE_FREE(*pp);
148 }
149
150 /***************************************************************************
151  Disconnect from the client
152 ****************************************************************************/
153
154 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
155 {
156         WERROR status;
157
158         /* weird if the test succeds !!! */
159         if (smb_connections==0) {
160                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161                 return;
162         }
163
164         if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
165                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
166
167         /* if it's the last connection, deconnect the IPC$ share */
168         if (smb_connections==1) {
169                 if(!spoolss_disconnect_from_client(&cli))
170                         return;
171
172                 message_deregister(MSG_PRINTER_NOTIFY);
173         }
174
175         smb_connections--;
176 }
177
178 /****************************************************************************
179  Functions to free a printer entry datastruct.
180 ****************************************************************************/
181
182 static void free_printer_entry(void *ptr)
183 {
184         Printer_entry *Printer = (Printer_entry *)ptr;
185
186         if (Printer->notify.client_connected==True)
187                 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
188
189         Printer->notify.flags=0;
190         Printer->notify.options=0;
191         Printer->notify.localmachine[0]='\0';
192         Printer->notify.printerlocal=0;
193         free_spool_notify_option(&Printer->notify.option);
194         Printer->notify.option=NULL;
195         Printer->notify.client_connected=False;
196
197         SAFE_FREE(Printer);
198 }
199
200 /****************************************************************************
201  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
202 ****************************************************************************/
203
204 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
205 {
206         SPOOL_NOTIFY_OPTION *new_sp = NULL;
207
208         if (!sp)
209                 return NULL;
210
211         new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
212         if (!new_sp)
213                 return NULL;
214
215         *new_sp = *sp;
216
217         if (sp->ctr.count) {
218                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
219
220                 if (!new_sp->ctr.type) {
221                         SAFE_FREE(new_sp);
222                         return NULL;
223                 }
224         }
225
226         return new_sp;
227 }
228
229 /****************************************************************************
230   find printer index by handle
231 ****************************************************************************/
232
233 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
234 {
235         Printer_entry *find_printer = NULL;
236
237         if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
238                 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
239                 return NULL;
240         }
241
242         return find_printer;
243 }
244
245 /****************************************************************************
246   close printer index by handle
247 ****************************************************************************/
248
249 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
250 {
251         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
252
253         if (!Printer) {
254                 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
255                 return False;
256         }
257
258         close_policy_hnd(p, hnd);
259
260         return True;
261 }       
262
263 /****************************************************************************
264   delete a printer given a handle
265 ****************************************************************************/
266 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
267 {
268         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
269
270         if (!Printer) {
271                 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
272                 return WERR_BADFID;
273         }
274
275         if (del_a_printer(Printer->dev.handlename) != 0) {
276                 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
277                 return WERR_BADFID;
278         }
279
280         /* Check calling user has permission to delete printer.  Note that
281            since we set the snum parameter to -1 only administrators can
282            delete the printer.  This stops people with the Full Control
283            permission from deleting the printer. */
284
285         if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
286                 DEBUG(3, ("printer delete denied by security descriptor\n"));
287                 return WERR_ACCESS_DENIED;
288         }
289
290         if (*lp_deleteprinter_cmd()) {
291
292                 char *cmd = lp_deleteprinter_cmd();
293                 pstring command;
294                 int ret;
295                 int i;
296
297                 /* Printer->dev.handlename equals portname equals sharename */
298                 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
299                                         Printer->dev.handlename);
300
301                 DEBUG(10,("Running [%s]\n", command));
302                 ret = smbrun(command, NULL);
303                 if (ret != 0) {
304                         return WERR_BADFID; /* What to return here? */
305                 }
306                 DEBUGADD(10,("returned [%d]\n", ret));
307
308                 /* Send SIGHUP to process group... is there a better way? */
309                 kill(0, SIGHUP);
310
311                 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
312                         lp_killservice( i );
313                         return WERR_OK;
314                 } else
315                         return WERR_ACCESS_DENIED;
316         }
317
318         return WERR_OK;
319 }       
320
321 /****************************************************************************
322   return the snum of a printer corresponding to an handle
323 ****************************************************************************/
324 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
325 {
326         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
327                 
328         if (!Printer) {
329                 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
330                 return False;
331         }
332         
333         switch (Printer->printer_type) {
334         case PRINTER_HANDLE_IS_PRINTER:         
335                 DEBUG(4,("short name:%s\n", Printer->dev.handlename));                  
336                 *number = print_queue_snum(Printer->dev.handlename);
337                 return (*number != -1);
338         case PRINTER_HANDLE_IS_PRINTSERVER:
339                 return False;
340         default:
341                 return False;
342         }
343 }
344
345 /****************************************************************************
346   set printer handle type.
347 ****************************************************************************/
348 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
349 {
350         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
351
352         if (!Printer) {
353                 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
354                 return False;
355         }
356
357         DEBUG(4,("Setting printer access=%x\n", access_required));
358         Printer->access = access_required;
359         return True;            
360 }
361
362 /****************************************************************************
363  Set printer handle type.
364  Check if it's \\server or \\server\printer
365 ****************************************************************************/
366
367 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
368 {
369         DEBUG(3,("Setting printer type=%s\n", handlename));
370
371         if ( strlen(handlename) < 3 ) {
372                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
373                 return False;
374         }
375
376         /* it's a print server */
377         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
378                 DEBUGADD(4,("Printer is a print server\n"));
379                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;          
380         }
381         /* it's a printer */
382         else {
383                 DEBUGADD(4,("Printer is a printer\n"));
384                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
385         }
386
387         return True;
388 }
389
390 /****************************************************************************
391  Set printer handle name.
392 ****************************************************************************/
393
394 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
395 {
396         NT_PRINTER_INFO_LEVEL *printer = NULL;
397         int snum;
398         int n_services=lp_numservices();
399         char *aprinter;
400         BOOL found=False;
401         
402         DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
403
404         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
405                 ZERO_STRUCT(Printer->dev.printerservername);
406                 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
407                 return True;
408         }
409
410         if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
411                 return False;
412         
413         if (*handlename=='\\') {
414                 aprinter=strchr_m(handlename+2, '\\');
415                 aprinter++;
416         }
417         else {
418                 aprinter=handlename;
419         }
420
421         DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
422
423         /*
424          * store the Samba share name in it
425          * in back we have the long printer name
426          * need to iterate all the snum and do a
427          * get_a_printer each time to find the printer
428          * faster to do it here than later.
429          */
430
431         for (snum=0;snum<n_services && found==False;snum++) {
432                 char *printername;
433         
434                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
435                         continue;
436                 
437                 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
438
439                 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
440                         continue;
441
442                 printername=strchr_m(printer->info_2->printername+2, '\\');
443                 printername++;
444
445                 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
446                                 printer->info_2->printername, aprinter ));
447
448                 if ( strlen(printername) != strlen(aprinter) ) {
449                         free_a_printer(&printer, 2);
450                         continue;
451                 }
452                 
453                 if ( strncasecmp(printername, aprinter, strlen(aprinter)))  {
454                         free_a_printer(&printer, 2);
455                         continue;
456                 }
457                 
458                 found=True;
459         }
460
461         /*
462          * if we haven't found a printer with the given handlename
463          * then it can be a share name as you can open both \\server\printer and
464          * \\server\share
465          */
466
467         /*
468          * we still check if the printer description file exists as NT won't be happy
469          * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
470          */
471
472         if (found==False) {
473                 DEBUGADD(5,("Printer not found, checking for share now\n"));
474         
475                 for (snum=0;snum<n_services && found==False;snum++) {
476         
477                         if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
478                                 continue;
479                 
480                         DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
481
482                         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
483                                 continue;
484
485                         DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
486                                         printer->info_2->printername, aprinter ));
487
488                         if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
489                                 free_a_printer(&printer, 2);
490                                 continue;
491                         }
492                 
493                         if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter)))  {
494                                 free_a_printer(&printer, 2);
495                                 continue;
496                         }
497                 
498                         found=True;
499                 }
500         }
501                 
502         if (found==False) {
503                 DEBUGADD(4,("Printer not found\n"));
504                 return False;
505         }
506         
507         snum--;
508         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
509                         printer->info_2->printername, lp_servicename(snum),snum));
510
511         ZERO_STRUCT(Printer->dev.handlename);
512         strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
513         
514         free_a_printer(&printer, 2);
515
516         return True;
517 }
518
519 /****************************************************************************
520   find first available printer slot. creates a printer handle for you.
521  ****************************************************************************/
522
523 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
524 {
525         Printer_entry *new_printer;
526
527         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
528
529         if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
530                 return False;
531
532         ZERO_STRUCTP(new_printer);
533         
534         new_printer->notify.option=NULL;
535                                 
536         if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
537                 SAFE_FREE(new_printer);
538                 return False;
539         }
540
541         if (!set_printer_hnd_printertype(new_printer, name)) {
542                 close_printer_handle(p, hnd);
543                 return False;
544         }
545         
546         if (!set_printer_hnd_name(new_printer, name)) {
547                 close_printer_handle(p, hnd);
548                 return False;
549         }
550
551         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
552
553         return True;
554 }
555
556 /********************************************************************
557  Return True is the handle is a print server.
558  ********************************************************************/
559
560 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
561 {
562         Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
563
564         if (!Printer)
565                 return False;
566                 
567         if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
568                 return False;
569         
570         return True;
571 }
572
573 /****************************************************************************
574  allocate more memory for a BUFFER.
575 ****************************************************************************/
576 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
577 {
578         prs_struct *ps;
579         uint32 extra_space;
580         uint32 old_offset;
581         
582         ps= &buffer->prs;
583
584         /* damn, I'm doing the reverse operation of prs_grow() :) */
585         if (buffer_size < prs_data_size(ps))
586                 extra_space=0;
587         else    
588                 extra_space = buffer_size - prs_data_size(ps);
589
590         /*
591          * save the offset and move to the end of the buffer
592          * prs_grow() checks the extra_space against the offset
593          */
594         old_offset=prs_offset(ps);      
595         prs_set_offset(ps, prs_data_size(ps));
596         
597         if (!prs_grow(ps, extra_space))
598                 return False;
599
600         prs_set_offset(ps, old_offset);
601
602         buffer->string_at_end=prs_data_size(ps);
603
604         return True;
605 }
606
607 /***************************************************************************
608  receive the notify message
609 ****************************************************************************/
610
611 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
612 {
613         fstring printer;
614         WERROR status;
615         struct pipes_struct *p;
616         struct policy *pol;
617         struct handle_list *hl;
618
619         *printer = '\0';
620         fstrcpy(printer,buf);
621
622         if (len == 0) {
623                 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
624                 return;
625         }
626
627         DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
628
629         /*
630          * We need to enumerate all printers. The handle list is shared
631          * across pipes of the same name, so just find the first open
632          * spoolss pipe.
633          */
634
635         hl = NULL;      
636         for ( p = get_first_pipe(); 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  Spoolss_enumprinters.
2878 ********************************************************************/
2879 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2880 {
2881         int snum;
2882         int i;
2883         int n_services=lp_numservices();
2884         PRINTER_INFO_1 *tp, *printers=NULL;
2885         PRINTER_INFO_1 current_prt;
2886         
2887         DEBUG(4,("enum_all_printers_info_1\n"));        
2888
2889         for (snum=0; snum<n_services; snum++) {
2890                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2891                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2892                                 
2893                         if (construct_printer_info_1(flags, &current_prt, snum)) {
2894                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2895                                         DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2896                                         SAFE_FREE(printers);
2897                                         *returned=0;
2898                                         return WERR_NOMEM;
2899                                 }
2900                                 else printers = tp;
2901                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
2902                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2903                                 (*returned)++;
2904                         }
2905                 }
2906         }
2907                 
2908         /* check the required size. */  
2909         for (i=0; i<*returned; i++)
2910                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2911
2912         if (!alloc_buffer_size(buffer, *needed))
2913                 return WERR_INSUFFICIENT_BUFFER;
2914
2915         /* fill the buffer with the structures */
2916         for (i=0; i<*returned; i++)
2917                 smb_io_printer_info_1("", buffer, &printers[i], 0);     
2918
2919         /* clear memory */
2920         SAFE_FREE(printers);
2921
2922         if (*needed > offered) {
2923                 *returned=0;
2924                 return WERR_INSUFFICIENT_BUFFER;
2925         }
2926         else
2927                 return WERR_OK;
2928 }
2929
2930 /********************************************************************
2931  enum_all_printers_info_1_local.
2932 *********************************************************************/
2933 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2934 {
2935         DEBUG(4,("enum_all_printers_info_1_local\n"));  
2936         
2937         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2938 }
2939
2940 /********************************************************************
2941  enum_all_printers_info_1_name.
2942 *********************************************************************/
2943 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2944 {
2945         char *s = name;
2946         
2947         DEBUG(4,("enum_all_printers_info_1_name\n"));   
2948         
2949         if ((name[0] == '\\') && (name[1] == '\\'))
2950                 s = name + 2;
2951
2952         if (is_myname_or_ipaddr(s)) {
2953                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2954         }
2955         else
2956                 return WERR_INVALID_NAME;
2957 }
2958
2959 /********************************************************************
2960  enum_all_printers_info_1_remote.
2961 *********************************************************************/
2962 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2963 {
2964         PRINTER_INFO_1 *printer;
2965         fstring printername;
2966         fstring desc;
2967         fstring comment;
2968         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
2969
2970         /* JFM: currently it's more a place holder than anything else.
2971          * In the spooler world there is a notion of server registration.
2972          * the print servers are registring (sp ?) on the PDC (in the same domain)
2973          *
2974          * We should have a TDB here. The registration is done thru an undocumented RPC call.
2975          */
2976         
2977         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2978                 return WERR_NOMEM;
2979
2980         *returned=1;
2981         
2982         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());           
2983         slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
2984         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2985
2986         init_unistr(&printer->description, desc);
2987         init_unistr(&printer->name, printername);       
2988         init_unistr(&printer->comment, comment);
2989         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2990                 
2991         /* check the required size. */  
2992         *needed += spoolss_size_printer_info_1(printer);
2993
2994         if (!alloc_buffer_size(buffer, *needed)) {
2995                 SAFE_FREE(printer);
2996                 return WERR_INSUFFICIENT_BUFFER;
2997         }
2998
2999         /* fill the buffer with the structures */
3000         smb_io_printer_info_1("", buffer, printer, 0);  
3001
3002         /* clear memory */
3003         SAFE_FREE(printer);
3004
3005         if (*needed > offered) {
3006                 *returned=0;
3007                 return WERR_INSUFFICIENT_BUFFER;
3008         }
3009         else
3010                 return WERR_OK;
3011 }
3012
3013 /********************************************************************
3014  enum_all_printers_info_1_network.
3015 *********************************************************************/
3016
3017 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3018 {
3019         DEBUG(4,("enum_all_printers_info_1_network\n"));        
3020         
3021         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3022 }
3023
3024 /********************************************************************
3025  * api_spoolss_enumprinters
3026  *
3027  * called from api_spoolss_enumprinters (see this to understand)
3028  ********************************************************************/
3029
3030 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3031 {
3032         int snum;
3033         int i;
3034         int n_services=lp_numservices();
3035         PRINTER_INFO_2 *tp, *printers=NULL;
3036         PRINTER_INFO_2 current_prt;
3037
3038         for (snum=0; snum<n_services; snum++) {
3039                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3040                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3041                                 
3042                         if (construct_printer_info_2(&current_prt, snum)) {
3043                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3044                                         DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3045                                         SAFE_FREE(printers);
3046                                         *returned = 0;
3047                                         return WERR_NOMEM;
3048                                 }
3049                                 else printers = tp;
3050                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
3051                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3052                                 (*returned)++;
3053                         }
3054                 }
3055         }
3056         
3057         /* check the required size. */  
3058         for (i=0; i<*returned; i++)
3059                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3060
3061         if (!alloc_buffer_size(buffer, *needed)) {
3062                 for (i=0; i<*returned; i++) {
3063                         free_devmode(printers[i].devmode);
3064                 }
3065                 SAFE_FREE(printers);
3066                 return WERR_INSUFFICIENT_BUFFER;
3067         }
3068
3069         /* fill the buffer with the structures */
3070         for (i=0; i<*returned; i++)
3071                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);   
3072         
3073         /* clear memory */
3074         for (i=0; i<*returned; i++) {
3075                 free_devmode(printers[i].devmode);
3076         }
3077         SAFE_FREE(printers);
3078
3079         if (*needed > offered) {
3080                 *returned=0;
3081                 return WERR_INSUFFICIENT_BUFFER;
3082         }
3083         else
3084                 return WERR_OK;
3085 }
3086
3087 /********************************************************************
3088  * handle enumeration of printers at level 1
3089  ********************************************************************/
3090 static WERROR enumprinters_level1( uint32 flags, fstring name,
3091                                  NEW_BUFFER *buffer, uint32 offered,
3092                                  uint32 *needed, uint32 *returned)
3093 {
3094         /* Not all the flags are equals */
3095
3096         if (flags & PRINTER_ENUM_LOCAL)
3097                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3098
3099         if (flags & PRINTER_ENUM_NAME)
3100                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3101
3102         if (flags & PRINTER_ENUM_REMOTE)
3103                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3104
3105         if (flags & PRINTER_ENUM_NETWORK)
3106                 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3107
3108         return WERR_OK; /* NT4sp5 does that */
3109 }
3110
3111 /********************************************************************
3112  * handle enumeration of printers at level 2
3113  ********************************************************************/
3114 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3115                                  NEW_BUFFER *buffer, uint32 offered,
3116                                  uint32 *needed, uint32 *returned)
3117 {
3118         char *s = servername;
3119
3120         if (flags & PRINTER_ENUM_LOCAL) {
3121                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3122         }
3123
3124         if (flags & PRINTER_ENUM_NAME) {
3125                 if ((servername[0] == '\\') && (servername[1] == '\\'))
3126                         s = servername + 2;
3127                 if (is_myname_or_ipaddr(s))
3128                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3129                 else
3130                         return WERR_INVALID_NAME;
3131         }
3132
3133         if (flags & PRINTER_ENUM_REMOTE)
3134                 return WERR_UNKNOWN_LEVEL;
3135
3136         return WERR_OK;
3137 }
3138
3139 /********************************************************************
3140  * handle enumeration of printers at level 5
3141  ********************************************************************/
3142 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3143                                  NEW_BUFFER *buffer, uint32 offered,
3144                                  uint32 *needed, uint32 *returned)
3145 {
3146 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3147         return WERR_OK;
3148 }
3149
3150 /********************************************************************
3151  * api_spoolss_enumprinters
3152  *
3153  * called from api_spoolss_enumprinters (see this to understand)
3154  ********************************************************************/
3155
3156 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3157 {
3158         uint32 flags = q_u->flags;
3159         UNISTR2 *servername = &q_u->servername;
3160         uint32 level = q_u->level;
3161         NEW_BUFFER *buffer = NULL;
3162         uint32 offered = q_u->offered;
3163         uint32 *needed = &r_u->needed;
3164         uint32 *returned = &r_u->returned;
3165
3166         fstring name;
3167         
3168         /* that's an [in out] buffer */
3169         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3170         buffer = r_u->buffer;
3171
3172         DEBUG(4,("_spoolss_enumprinters\n"));
3173
3174         *needed=0;
3175         *returned=0;
3176         
3177         /*
3178          * Level 1:
3179          *          flags==PRINTER_ENUM_NAME
3180          *           if name=="" then enumerates all printers
3181          *           if name!="" then enumerate the printer
3182          *          flags==PRINTER_ENUM_REMOTE
3183          *          name is NULL, enumerate printers
3184          * Level 2: name!="" enumerates printers, name can't be NULL
3185          * Level 3: doesn't exist
3186          * Level 4: does a local registry lookup
3187          * Level 5: same as Level 2
3188          */
3189
3190         unistr2_to_ascii(name, servername, sizeof(name)-1);
3191         strupper(name);
3192
3193         switch (level) {
3194         case 1:
3195                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3196         case 2:
3197                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3198         case 5:
3199                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3200         case 3:
3201         case 4:
3202                 break;
3203         }
3204         return WERR_UNKNOWN_LEVEL;
3205 }
3206
3207 /****************************************************************************
3208 ****************************************************************************/
3209 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3210 {
3211         PRINTER_INFO_0 *printer=NULL;
3212
3213         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3214                 return WERR_NOMEM;
3215
3216         construct_printer_info_0(printer, snum);
3217         
3218         /* check the required size. */  
3219         *needed += spoolss_size_printer_info_0(printer);
3220
3221         if (!alloc_buffer_size(buffer, *needed)) {
3222                 SAFE_FREE(printer);
3223                 return WERR_INSUFFICIENT_BUFFER;
3224         }
3225
3226         /* fill the buffer with the structures */
3227         smb_io_printer_info_0("", buffer, printer, 0);  
3228         
3229         /* clear memory */
3230         SAFE_FREE(printer);
3231
3232         if (*needed > offered) {
3233                 return WERR_INSUFFICIENT_BUFFER;
3234         }
3235
3236         return WERR_OK;
3237 }
3238
3239 /****************************************************************************
3240 ****************************************************************************/
3241 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3242 {
3243         PRINTER_INFO_1 *printer=NULL;
3244
3245         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3246                 return WERR_NOMEM;
3247
3248         construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3249         
3250         /* check the required size. */  
3251         *needed += spoolss_size_printer_info_1(printer);
3252
3253         if (!alloc_buffer_size(buffer, *needed)) {
3254                 SAFE_FREE(printer);
3255                 return WERR_INSUFFICIENT_BUFFER;
3256         }
3257
3258         /* fill the buffer with the structures */
3259         smb_io_printer_info_1("", buffer, printer, 0);  
3260         
3261         /* clear memory */
3262         SAFE_FREE(printer);
3263
3264         if (*needed > offered) {
3265                 return WERR_INSUFFICIENT_BUFFER;
3266         }
3267
3268         return WERR_OK; 
3269 }
3270
3271 /****************************************************************************
3272 ****************************************************************************/
3273 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3274 {
3275         PRINTER_INFO_2 *printer=NULL;
3276
3277         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3278                 return WERR_NOMEM;
3279         
3280         construct_printer_info_2(printer, snum);
3281         
3282         /* check the required size. */  
3283         *needed += spoolss_size_printer_info_2(printer);
3284
3285         if (!alloc_buffer_size(buffer, *needed)) {
3286                 free_printer_info_2(printer);
3287                 return WERR_INSUFFICIENT_BUFFER;
3288         }
3289
3290         /* fill the buffer with the structures */
3291         if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3292                 free_printer_info_2(printer);
3293                 return WERR_NOMEM;
3294         }
3295         
3296         /* clear memory */
3297         free_printer_info_2(printer);
3298
3299         if (*needed > offered) {
3300                 return WERR_INSUFFICIENT_BUFFER;
3301         }
3302
3303         return WERR_OK; 
3304 }
3305
3306 /****************************************************************************
3307 ****************************************************************************/
3308 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3309 {
3310         PRINTER_INFO_3 *printer=NULL;
3311
3312         if (!construct_printer_info_3(&printer, snum))
3313                 return WERR_NOMEM;
3314         
3315         /* check the required size. */  
3316         *needed += spoolss_size_printer_info_3(printer);
3317
3318         if (!alloc_buffer_size(buffer, *needed)) {
3319                 free_printer_info_3(printer);
3320                 return WERR_INSUFFICIENT_BUFFER;
3321         }
3322
3323         /* fill the buffer with the structures */
3324         smb_io_printer_info_3("", buffer, printer, 0);  
3325         
3326         /* clear memory */
3327         free_printer_info_3(printer);
3328         
3329         if (*needed > offered) {
3330                 return WERR_INSUFFICIENT_BUFFER;
3331         }
3332
3333         return WERR_OK; 
3334 }
3335
3336 /****************************************************************************
3337 ****************************************************************************/
3338
3339 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3340 {
3341         POLICY_HND *handle = &q_u->handle;
3342         uint32 level = q_u->level;
3343         NEW_BUFFER *buffer = NULL;
3344         uint32 offered = q_u->offered;
3345         uint32 *needed = &r_u->needed;
3346
3347         int snum;
3348
3349         /* that's an [in out] buffer */
3350         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3351         buffer = r_u->buffer;
3352
3353         *needed=0;
3354
3355         if (!get_printer_snum(p, handle, &snum))
3356                 return WERR_BADFID;
3357
3358         switch (level) {
3359         case 0:
3360                 return getprinter_level_0(snum, buffer, offered, needed);
3361         case 1:
3362                 return getprinter_level_1(snum, buffer, offered, needed);
3363         case 2:         
3364                 return getprinter_level_2(snum, buffer, offered, needed);
3365         case 3:         
3366                 return getprinter_level_3(snum, buffer, offered, needed);
3367         }
3368         return WERR_UNKNOWN_LEVEL;
3369 }       
3370                 
3371 /********************************************************************
3372  * fill a DRIVER_INFO_1 struct
3373  ********************************************************************/
3374 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3375 {
3376         init_unistr( &info->name, driver.info_3->name);
3377 }
3378
3379 /********************************************************************
3380  * construct_printer_driver_info_1
3381  ********************************************************************/
3382 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3383 {       
3384         NT_PRINTER_INFO_LEVEL *printer = NULL;
3385         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3386
3387         ZERO_STRUCT(driver);
3388
3389         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3390                 return WERR_INVALID_PRINTER_NAME;
3391
3392         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3393                 return WERR_UNKNOWN_PRINTER_DRIVER;
3394
3395         fill_printer_driver_info_1(info, driver, servername, architecture);
3396
3397         free_a_printer(&printer,2);
3398
3399         return WERR_OK;
3400 }
3401
3402 /********************************************************************
3403  * construct_printer_driver_info_2
3404  * fill a printer_info_2 struct
3405  ********************************************************************/
3406 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3407 {
3408         pstring temp;
3409
3410         info->version=driver.info_3->cversion;
3411
3412         init_unistr( &info->name, driver.info_3->name );
3413         init_unistr( &info->architecture, driver.info_3->environment );
3414
3415
3416     if (strlen(driver.info_3->driverpath)) {
3417                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3418                 init_unistr( &info->driverpath, temp );
3419     } else
3420         init_unistr( &info->driverpath, "" );
3421
3422         if (strlen(driver.info_3->datafile)) {
3423                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3424                 init_unistr( &info->datafile, temp );
3425         } else
3426                 init_unistr( &info->datafile, "" );
3427         
3428         if (strlen(driver.info_3->configfile)) {
3429                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3430                 init_unistr( &info->configfile, temp ); 
3431         } else
3432                 init_unistr( &info->configfile, "" );
3433 }
3434
3435 /********************************************************************
3436  * construct_printer_driver_info_2
3437  * fill a printer_info_2 struct
3438  ********************************************************************/
3439 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3440 {
3441         NT_PRINTER_INFO_LEVEL *printer = NULL;
3442         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3443
3444         ZERO_STRUCT(printer);
3445         ZERO_STRUCT(driver);
3446
3447         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3448                 return WERR_INVALID_PRINTER_NAME;
3449
3450         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3451                 return WERR_UNKNOWN_PRINTER_DRIVER;
3452
3453         fill_printer_driver_info_2(info, driver, servername);
3454
3455         free_a_printer(&printer,2);
3456
3457         return WERR_OK;
3458 }
3459
3460 /********************************************************************
3461  * copy a strings array and convert to UNICODE
3462  *
3463  * convert an array of ascii string to a UNICODE string
3464  ********************************************************************/
3465 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3466 {
3467         int i=0;
3468         int j=0;
3469         char *v;
3470         pstring line;
3471         uint16 *tuary;
3472
3473         DEBUG(6,("init_unistr_array\n"));
3474         *uni_array=NULL;
3475
3476         while (1) {
3477                 if (char_array == NULL)
3478                         v = "";
3479                 else {
3480                         v = char_array[i];
3481                         if (!v) v = ""; /* hack to handle null lists */
3482                 }
3483                 if (strlen(v) == 0) break;
3484                 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3485                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3486                 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3487                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
3488                         return;
3489                 }
3490                 else *uni_array = tuary;
3491                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3492                 i++;
3493         }
3494         
3495         if (*uni_array) {
3496                 (*uni_array)[j]=0x0000;
3497         }
3498         
3499         DEBUGADD(6,("last one:done\n"));
3500 }
3501
3502 /********************************************************************
3503  * construct_printer_info_3
3504  * fill a printer_info_3 struct
3505  ********************************************************************/
3506 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3507 {
3508         pstring temp;
3509
3510         ZERO_STRUCTP(info);
3511
3512         info->version=driver.info_3->cversion;
3513
3514         init_unistr( &info->name, driver.info_3->name );        
3515         init_unistr( &info->architecture, driver.info_3->environment );
3516
3517     if (strlen(driver.info_3->driverpath)) {
3518         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3519         init_unistr( &info->driverpath, temp );
3520     } else
3521         init_unistr( &info->driverpath, "" );
3522     
3523     if (strlen(driver.info_3->datafile)) {
3524         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3525         init_unistr( &info->datafile, temp );
3526     } else
3527         init_unistr( &info->datafile, "" );
3528
3529     if (strlen(driver.info_3->configfile)) {
3530         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3531         init_unistr( &info->configfile, temp ); 
3532     } else
3533         init_unistr( &info->configfile, "" );
3534
3535     if (strlen(driver.info_3->helpfile)) {
3536         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3537         init_unistr( &info->helpfile, temp );
3538     } else
3539         init_unistr( &info->helpfile, "" );
3540
3541         init_unistr( &info->monitorname, driver.info_3->monitorname );
3542         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3543
3544         info->dependentfiles=NULL;
3545         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3546 }
3547
3548 /********************************************************************
3549  * construct_printer_info_3
3550  * fill a printer_info_3 struct
3551  ********************************************************************/
3552 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *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         WERROR status;
3557         ZERO_STRUCT(driver);
3558
3559         status=get_a_printer(&printer, 2, lp_servicename(snum) );
3560         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3561         if (!W_ERROR_IS_OK(status))
3562                 return WERR_INVALID_PRINTER_NAME;
3563
3564         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3565         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3566         if (!W_ERROR_IS_OK(status)) {
3567                 free_a_printer(&printer,2);
3568                 return WERR_UNKNOWN_PRINTER_DRIVER;
3569         }
3570
3571         fill_printer_driver_info_3(info, driver, servername);
3572
3573         free_a_printer(&printer,2);
3574
3575         return WERR_OK;
3576 }
3577
3578 /********************************************************************
3579  * construct_printer_info_6
3580  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3581  ********************************************************************/
3582
3583 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3584 {
3585         pstring temp;
3586         fstring nullstr;
3587
3588         ZERO_STRUCTP(info);
3589         memset(&nullstr, '\0', sizeof(fstring));
3590
3591         info->version=driver.info_3->cversion;
3592
3593         init_unistr( &info->name, driver.info_3->name );        
3594         init_unistr( &info->architecture, driver.info_3->environment );
3595
3596         if (strlen(driver.info_3->driverpath)) {
3597                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3598                 init_unistr( &info->driverpath, temp );
3599         } else
3600                 init_unistr( &info->driverpath, "" );
3601
3602         if (strlen(driver.info_3->datafile)) {
3603                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3604                 init_unistr( &info->datafile, temp );
3605         } else
3606                 init_unistr( &info->datafile, "" );
3607
3608         if (strlen(driver.info_3->configfile)) {
3609                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3610                 init_unistr( &info->configfile, temp ); 
3611         } else
3612                 init_unistr( &info->configfile, "" );
3613
3614         if (strlen(driver.info_3->helpfile)) {
3615                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3616                 init_unistr( &info->helpfile, temp );
3617         } else
3618                 init_unistr( &info->helpfile, "" );
3619         
3620         init_unistr( &info->monitorname, driver.info_3->monitorname );
3621         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3622
3623         info->dependentfiles=NULL;
3624         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3625
3626         info->previousdrivernames=NULL;
3627         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3628
3629         info->driver_date.low=0;
3630         info->driver_date.high=0;
3631
3632         info->padding=0;
3633         info->driver_version_low=0;
3634         info->driver_version_high=0;
3635
3636         init_unistr( &info->mfgname, "");
3637         init_unistr( &info->oem_url, "");
3638         init_unistr( &info->hardware_id, "");
3639         init_unistr( &info->provider, "");
3640 }
3641
3642 /********************************************************************
3643  * construct_printer_info_6
3644  * fill a printer_info_6 struct
3645  ********************************************************************/
3646 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3647 {       
3648         NT_PRINTER_INFO_LEVEL *printer = NULL;
3649         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3650         WERROR status;
3651         ZERO_STRUCT(driver);
3652
3653         status=get_a_printer(&printer, 2, lp_servicename(snum) );
3654         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3655         if (!W_ERROR_IS_OK(status))
3656                 return WERR_INVALID_PRINTER_NAME;
3657
3658         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3659         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3660         if (!W_ERROR_IS_OK(status)) {
3661                 /*
3662                  * Is this a W2k client ?
3663                  */
3664
3665                 if (version < 3) {
3666                         free_a_printer(&printer,2);
3667                         return WERR_UNKNOWN_PRINTER_DRIVER;
3668                 }
3669
3670                 /* Yes - try again with a WinNT driver. */
3671                 version = 2;
3672                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3673                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3674                 if (!W_ERROR_IS_OK(status)) {
3675                         free_a_printer(&printer,2);
3676                         return WERR_UNKNOWN_PRINTER_DRIVER;
3677                 }
3678         }
3679
3680         fill_printer_driver_info_6(info, driver, servername);
3681
3682         free_a_printer(&printer,2);
3683
3684         return WERR_OK;
3685 }
3686
3687 /****************************************************************************
3688 ****************************************************************************/
3689
3690 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3691 {
3692         SAFE_FREE(info->dependentfiles);
3693 }
3694
3695 /****************************************************************************
3696 ****************************************************************************/
3697
3698 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3699 {
3700         SAFE_FREE(info->dependentfiles);
3701         
3702 }
3703
3704 /****************************************************************************
3705 ****************************************************************************/
3706 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3707 {
3708         DRIVER_INFO_1 *info=NULL;
3709         WERROR status;
3710         
3711         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3712                 return WERR_NOMEM;
3713         
3714         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3715         if (!W_ERROR_IS_OK(status)) {
3716                 SAFE_FREE(info);
3717                 return status;
3718         }
3719
3720         /* check the required size. */  
3721         *needed += spoolss_size_printer_driver_info_1(info);
3722
3723         if (!alloc_buffer_size(buffer, *needed)) {
3724                 SAFE_FREE(info);
3725                 return WERR_INSUFFICIENT_BUFFER;
3726         }
3727
3728         /* fill the buffer with the structures */
3729         smb_io_printer_driver_info_1("", buffer, info, 0);      
3730
3731         /* clear memory */
3732         SAFE_FREE(info);
3733
3734         if (*needed > offered)
3735                 return WERR_INSUFFICIENT_BUFFER;
3736
3737         return WERR_OK;
3738 }
3739
3740 /****************************************************************************
3741 ****************************************************************************/
3742 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3743 {
3744         DRIVER_INFO_2 *info=NULL;
3745         WERROR status;
3746         
3747         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3748                 return WERR_NOMEM;
3749         
3750         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3751         if (!W_ERROR_IS_OK(status)) {
3752                 SAFE_FREE(info);
3753                 return status;
3754         }
3755
3756         /* check the required size. */  
3757         *needed += spoolss_size_printer_driver_info_2(info);
3758
3759         if (!alloc_buffer_size(buffer, *needed)) {
3760                 SAFE_FREE(info);
3761                 return WERR_INSUFFICIENT_BUFFER;
3762         }
3763
3764         /* fill the buffer with the structures */
3765         smb_io_printer_driver_info_2("", buffer, info, 0);      
3766
3767         /* clear memory */
3768         SAFE_FREE(info);
3769
3770         if (*needed > offered)
3771                 return WERR_INSUFFICIENT_BUFFER;
3772         
3773         return WERR_OK;
3774 }
3775
3776 /****************************************************************************
3777 ****************************************************************************/
3778 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3779 {
3780         DRIVER_INFO_3 info;
3781         WERROR status;
3782
3783         ZERO_STRUCT(info);
3784
3785         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3786         if (!W_ERROR_IS_OK(status)) {
3787                 return status;
3788         }
3789
3790         /* check the required size. */  
3791         *needed += spoolss_size_printer_driver_info_3(&info);
3792
3793         if (!alloc_buffer_size(buffer, *needed)) {
3794                 free_printer_driver_info_3(&info);
3795                 return WERR_INSUFFICIENT_BUFFER;
3796         }
3797
3798         /* fill the buffer with the structures */
3799         smb_io_printer_driver_info_3("", buffer, &info, 0);
3800
3801         free_printer_driver_info_3(&info);
3802
3803         if (*needed > offered)
3804                 return WERR_INSUFFICIENT_BUFFER;
3805
3806         return WERR_OK;
3807 }
3808
3809 /****************************************************************************
3810 ****************************************************************************/
3811 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3812 {
3813         DRIVER_INFO_6 info;
3814         WERROR status;
3815
3816         ZERO_STRUCT(info);
3817
3818         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3819         if (!W_ERROR_IS_OK(status)) {
3820                 return status;
3821         }
3822
3823         /* check the required size. */  
3824         *needed += spoolss_size_printer_driver_info_6(&info);
3825
3826         if (!alloc_buffer_size(buffer, *needed)) {
3827                 free_printer_driver_info_6(&info);
3828                 return WERR_INSUFFICIENT_BUFFER;
3829         }
3830
3831         /* fill the buffer with the structures */
3832         smb_io_printer_driver_info_6("", buffer, &info, 0);
3833
3834         free_printer_driver_info_6(&info);
3835
3836         if (*needed > offered)
3837                 return WERR_INSUFFICIENT_BUFFER;
3838         
3839         return WERR_OK;
3840 }
3841
3842 /****************************************************************************
3843 ****************************************************************************/
3844
3845 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3846 {
3847         POLICY_HND *handle = &q_u->handle;
3848         UNISTR2 *uni_arch = &q_u->architecture;
3849         uint32 level = q_u->level;
3850         uint32 clientmajorversion = q_u->clientmajorversion;
3851 /*      uint32 clientminorversion = q_u->clientminorversion; - notused. */
3852         NEW_BUFFER *buffer = NULL;
3853         uint32 offered = q_u->offered;
3854         uint32 *needed = &r_u->needed;
3855         uint32 *servermajorversion = &r_u->servermajorversion;
3856         uint32 *serverminorversion = &r_u->serverminorversion;
3857
3858         fstring servername;
3859         fstring architecture;
3860         int snum;
3861
3862         /* that's an [in out] buffer */
3863         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3864         buffer = r_u->buffer;
3865
3866         DEBUG(4,("_spoolss_getprinterdriver2\n"));
3867
3868         *needed=0;
3869         *servermajorversion=0;
3870         *serverminorversion=0;
3871
3872         pstrcpy(servername, get_called_name());
3873         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3874
3875         if (!get_printer_snum(p, handle, &snum))
3876                 return WERR_BADFID;
3877
3878         switch (level) {
3879         case 1:
3880                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3881         case 2:
3882                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3883         case 3:
3884                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3885         case 6:
3886                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3887         }
3888
3889         return WERR_UNKNOWN_LEVEL;
3890 }
3891
3892 /****************************************************************************
3893 ****************************************************************************/
3894
3895 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3896 {
3897         POLICY_HND *handle = &q_u->handle;
3898
3899         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3900
3901         if (Printer) {
3902                 Printer->page_started=True;
3903                 return WERR_OK;
3904         }
3905
3906         DEBUG(3,("Error in startpageprinter printer handle\n"));
3907         return WERR_BADFID;
3908 }
3909
3910 /****************************************************************************
3911 ****************************************************************************/
3912
3913 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3914 {
3915         POLICY_HND *handle = &q_u->handle;
3916
3917         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3918
3919         if (!Printer) {
3920                 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3921                 return WERR_BADFID;
3922         }
3923         
3924         Printer->page_started=False;
3925
3926         return WERR_OK;
3927 }
3928
3929 /********************************************************************
3930  * api_spoolss_getprinter
3931  * called from the spoolss dispatcher
3932  *
3933  ********************************************************************/
3934
3935 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3936 {
3937         POLICY_HND *handle = &q_u->handle;
3938 /*      uint32 level = q_u->doc_info_container.level; - notused. */
3939         DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3940         uint32 *jobid = &r_u->jobid;
3941
3942         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3943         int snum;
3944         pstring jobname;
3945         fstring datatype;
3946         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3947         struct current_user user;
3948
3949         if (!Printer) {
3950                 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3951                 return WERR_BADFID;
3952         }
3953
3954         get_current_user(&user, p);
3955
3956         /*
3957          * a nice thing with NT is it doesn't listen to what you tell it.
3958          * when asked to send _only_ RAW datas, it tries to send datas
3959          * in EMF format.
3960          *
3961          * So I add checks like in NT Server ...
3962          *
3963          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
3964          * there's a bug in NT client-side code, so we'll fix it in the
3965          * server-side code. *nnnnnggggh!*
3966          */
3967         
3968         if (info_1->p_datatype != 0) {
3969                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3970                 if (strcmp(datatype, "RAW") != 0) {
3971                         (*jobid)=0;
3972                         return WERR_INVALID_DATATYPE;
3973                 }               
3974         }               
3975         
3976         /* get the share number of the printer */
3977         if (!get_printer_snum(p, handle, &snum)) {
3978                 return WERR_BADFID;
3979         }
3980
3981         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3982         
3983         Printer->jobid = print_job_start(&user, snum, jobname);
3984
3985         /* An error occured in print_job_start() so return an appropriate
3986            NT error code. */
3987
3988         if (Printer->jobid == -1) {
3989                 return map_werror_from_unix(errno);
3990         }
3991         
3992         Printer->document_started=True;
3993         (*jobid) = Printer->jobid;
3994
3995         return WERR_OK;
3996 }
3997
3998 /********************************************************************
3999  * api_spoolss_getprinter
4000  * called from the spoolss dispatcher
4001  *
4002  ********************************************************************/
4003
4004 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4005 {
4006         POLICY_HND *handle = &q_u->handle;
4007
4008         return _spoolss_enddocprinter_internal(p, handle);
4009 }
4010
4011 /****************************************************************************
4012 ****************************************************************************/
4013
4014 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4015 {
4016         POLICY_HND *handle = &q_u->handle;
4017         uint32 buffer_size = q_u->buffer_size;
4018         uint8 *buffer = q_u->buffer;
4019         uint32 *buffer_written = &q_u->buffer_size2;
4020
4021         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4022         
4023         if (!Printer) {
4024                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4025                 r_u->buffer_written = q_u->buffer_size2;
4026                 return WERR_BADFID;
4027         }
4028
4029         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4030
4031
4032         r_u->buffer_written = q_u->buffer_size2;
4033
4034         return WERR_OK;
4035 }
4036
4037 /********************************************************************
4038  * api_spoolss_getprinter
4039  * called from the spoolss dispatcher
4040  *
4041  ********************************************************************/
4042 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4043                               pipes_struct *p)
4044 {
4045         struct current_user user;
4046         int snum;
4047         WERROR errcode = WERR_BADFUNC;
4048         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4049
4050         get_current_user(&user, p);
4051
4052         if (!Printer) {
4053                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4054                 return WERR_BADFID;
4055         }
4056
4057         if (!get_printer_snum(p, handle, &snum))
4058                 return WERR_BADFID;
4059
4060         switch (command) {
4061         case PRINTER_CONTROL_PAUSE:
4062                 if (print_queue_pause(&user, snum, &errcode)) {
4063                         errcode = WERR_OK;
4064                 }
4065                 break;
4066         case PRINTER_CONTROL_RESUME:
4067         case PRINTER_CONTROL_UNPAUSE:
4068                 if (print_queue_resume(&user, snum, &errcode)) {
4069                         errcode = WERR_OK;
4070                 }
4071                 break;
4072         case PRINTER_CONTROL_PURGE:
4073                 if (print_queue_purge(&user, snum, &errcode)) {
4074                         errcode = WERR_OK;
4075                 }
4076                 break;
4077         default:
4078                 return WERR_UNKNOWN_LEVEL;
4079         }
4080
4081         return errcode;
4082 }
4083
4084 /********************************************************************
4085  * api_spoolss_abortprinter
4086  ********************************************************************/
4087
4088 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4089 {
4090         POLICY_HND *handle = &q_u->handle;
4091
4092         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4093 }
4094
4095 /********************************************************************
4096  * called by spoolss_api_setprinter
4097  * when updating a printer description
4098  ********************************************************************/
4099 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4100                                  const SPOOL_PRINTER_INFO_LEVEL *info,
4101                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4102 {
4103         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4104         struct current_user user;
4105         WERROR result;
4106         int snum;
4107
4108         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4109
4110         if (!Printer || !get_printer_snum(p, handle, &snum)) {
4111                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4112                          OUR_HANDLE(handle)));
4113
4114                 result = WERR_BADFID;
4115                 goto done;
4116         }
4117
4118         /* NT seems to like setting the security descriptor even though
4119            nothing may have actually changed.  This causes annoying
4120            dialog boxes when the user doesn't have permission to change
4121            the security descriptor. */
4122
4123         nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4124
4125         if (DEBUGLEVEL >= 10) {
4126                 SEC_ACL *the_acl;
4127                 int i;
4128
4129                 the_acl = old_secdesc_ctr->sec->dacl;
4130                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
4131                            PRINTERNAME(snum), the_acl->num_aces));
4132
4133                 for (i = 0; i < the_acl->num_aces; i++) {
4134                         fstring sid_str;
4135
4136                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4137
4138                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
4139                                   the_acl->ace[i].info.mask));
4140                 }
4141
4142                 the_acl = secdesc_ctr->sec->dacl;
4143
4144                 if (the_acl) {
4145                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4146                                    PRINTERNAME(snum), the_acl->num_aces));
4147
4148                         for (i = 0; i < the_acl->num_aces; i++) {
4149                                 fstring sid_str;
4150                                 
4151                                 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4152                                 
4153                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
4154                                            the_acl->ace[i].info.mask));
4155                         }
4156                 } else {
4157                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4158                 }
4159         }
4160
4161         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4162
4163         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4164                 result = WERR_OK;
4165                 goto done;
4166         }
4167
4168         /* Work out which user is performing the operation */
4169
4170         get_current_user(&user, p);
4171
4172         /* Check the user has permissions to change the security
4173            descriptor.  By experimentation with two NT machines, the user
4174            requires Full Access to the printer to change security
4175            information. */
4176
4177         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4178                 result = WERR_ACCESS_DENIED;
4179                 goto done;
4180         }
4181
4182         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4183
4184  done:
4185
4186         return result;
4187 }
4188
4189 /********************************************************************
4190  Do Samba sanity checks on a printer info struct.
4191  this has changed purpose: it now "canonicalises" printer
4192  info from a client rather than just checking it is correct
4193  ********************************************************************/
4194
4195 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4196 {
4197         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4198                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4199
4200         /* we force some elements to "correct" values */
4201         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4202         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4203                  get_called_name(), lp_servicename(snum));
4204         fstrcpy(info->sharename, lp_servicename(snum));
4205         info->attributes = PRINTER_ATTRIBUTE_SHARED   \
4206                 | PRINTER_ATTRIBUTE_LOCAL  \
4207                 | PRINTER_ATTRIBUTE_RAW_ONLY \
4208                 | PRINTER_ATTRIBUTE_QUEUED ;
4209         
4210         return True;
4211 }
4212
4213 /****************************************************************************
4214 ****************************************************************************/
4215 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4216 {
4217         char *cmd = lp_addprinter_cmd();
4218         char **qlines;
4219         pstring command;
4220         pstring driverlocation;
4221         int numlines;
4222         int ret;
4223         int fd;
4224
4225         /* build driver path... only 9X architecture is needed for legacy reasons */
4226         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4227                         get_called_name());
4228         /* change \ to \\ for the shell */
4229         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4230
4231         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4232                         cmd, printer->info_2->printername, printer->info_2->sharename,
4233                         printer->info_2->portname, printer->info_2->drivername,
4234                         printer->info_2->location, driverlocation);
4235
4236         DEBUG(10,("Running [%s]\n", command));
4237         ret = smbrun(command, &fd);
4238         DEBUGADD(10,("returned [%d]\n", ret));
4239
4240         if ( ret != 0 ) {
4241                 if (fd != -1)
4242                         close(fd);
4243                 return False;
4244         }
4245
4246         numlines = 0;
4247         /* Get lines and convert them back to dos-codepage */
4248         qlines = fd_lines_load(fd, &numlines);
4249         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4250         close(fd);
4251
4252         if(numlines) {
4253                 /* Set the portname to what the script says the portname should be. */
4254                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4255                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4256
4257                 /* Send SIGHUP to process group... is there a better way? */
4258                 kill(0, SIGHUP);
4259                 add_all_printers();
4260         }
4261
4262         file_lines_free(qlines);
4263         return True;
4264 }
4265
4266 /* Return true if two devicemodes are equal */
4267
4268 #define DEVMODE_CHECK_INT(field) \
4269     if (d1->field != d2->field) { \
4270         DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4271             d1->field, d2->field)); \
4272         return False; \
4273     }
4274
4275 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4276 {
4277         if (!d1 && !d2) goto equal;  /* if both are NULL they are equal */
4278
4279         if (!d1 ^ !d2) {
4280                 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4281                 return False; /* if either is exclusively NULL are not equal */
4282         }
4283
4284         if (!strequal(d1->devicename, d2->devicename)) {
4285                 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4286                 return False;
4287         }
4288
4289         if (!strequal(d1->formname, d2->formname)) {
4290                 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4291                 return False;
4292         }
4293
4294         DEVMODE_CHECK_INT(specversion);
4295         DEVMODE_CHECK_INT(driverversion);
4296         DEVMODE_CHECK_INT(driverextra);
4297         DEVMODE_CHECK_INT(orientation);
4298         DEVMODE_CHECK_INT(papersize);
4299         DEVMODE_CHECK_INT(paperlength);
4300         DEVMODE_CHECK_INT(paperwidth);
4301         DEVMODE_CHECK_INT(scale);
4302         DEVMODE_CHECK_INT(copies);
4303         DEVMODE_CHECK_INT(defaultsource);
4304         DEVMODE_CHECK_INT(printquality);
4305         DEVMODE_CHECK_INT(color);
4306         DEVMODE_CHECK_INT(duplex);
4307         DEVMODE_CHECK_INT(yresolution);
4308         DEVMODE_CHECK_INT(ttoption);
4309         DEVMODE_CHECK_INT(collate);
4310         DEVMODE_CHECK_INT(logpixels);
4311
4312         DEVMODE_CHECK_INT(fields);
4313         DEVMODE_CHECK_INT(bitsperpel);
4314         DEVMODE_CHECK_INT(pelswidth);
4315         DEVMODE_CHECK_INT(pelsheight);
4316         DEVMODE_CHECK_INT(displayflags);
4317         DEVMODE_CHECK_INT(displayfrequency);
4318         DEVMODE_CHECK_INT(icmmethod);
4319         DEVMODE_CHECK_INT(icmintent);
4320         DEVMODE_CHECK_INT(mediatype);
4321         DEVMODE_CHECK_INT(dithertype);
4322         DEVMODE_CHECK_INT(reserved1);
4323         DEVMODE_CHECK_INT(reserved2);
4324         DEVMODE_CHECK_INT(panningwidth);
4325         DEVMODE_CHECK_INT(panningheight);
4326
4327         /* compare the private data if it exists */
4328         if (!d1->driverextra && !d2->driverextra) goto equal;
4329
4330
4331         DEVMODE_CHECK_INT(driverextra);
4332
4333         if (memcmp(d1->private, d2->private, d1->driverextra)) {
4334                 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4335                 return False;
4336         }
4337
4338  equal:
4339         DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4340         return True;
4341 }
4342
4343 /* Return true if two NT_PRINTER_PARAM structures are equal */
4344
4345 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4346                                    NT_PRINTER_PARAM *p2)
4347 {
4348         if (!p1 && !p2) goto equal;
4349
4350         if ((!p1 && p2) || (p1 && !p2)) {
4351                 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4352                 return False;
4353         }
4354
4355         /* Compare lists of printer parameters */
4356
4357         while (p1) {
4358                 BOOL found = False;
4359                 NT_PRINTER_PARAM *q = p1;
4360
4361                 /* Find the parameter in the second structure */
4362
4363                 while(q) {
4364
4365                         if (strequal(p1->value, q->value)) {
4366
4367                                 if (p1->type != q->type) {
4368                                         DEBUG(10, ("nt_printer_param_equal():"
4369                                                    "types for %s differ (%d != %d)\n",
4370                                                    p1->value, p1->type,
4371                                                    q->type));
4372                                         break;
4373                                 }
4374
4375                                 if (p1->data_len != q->data_len) {
4376                                         DEBUG(10, ("nt_printer_param_equal():"
4377                                                    "len for %s differs (%d != %d)\n",
4378                                                    p1->value, p1->data_len,
4379                                                    q->data_len));
4380                                         break;
4381                                 }
4382
4383                                 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4384                                         found = True;
4385                                 } else {
4386                                         DEBUG(10, ("nt_printer_param_equal():"
4387                                                    "data for %s differs\n", p1->value));
4388                                 }
4389
4390                                 break;
4391                         }
4392
4393                         q = q->next;
4394                 }
4395
4396                 if (!found) {
4397                         DEBUG(10, ("nt_printer_param_equal(): param %s "
4398                                    "does not exist\n", p1->value));
4399                         return False;
4400                 }
4401
4402                 p1 = p1->next;
4403         }
4404
4405         equal:
4406
4407         DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4408         return True;
4409 }
4410
4411 /********************************************************************
4412  * Called by update_printer when trying to work out whether to
4413  * actually update printer info.
4414  ********************************************************************/
4415
4416 #define PI_CHECK_INT(field) \
4417     if (pi1->field != pi2->field) { \
4418         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4419             pi1->field, pi2->field)); \
4420         return False; \
4421     }
4422
4423 #define PI_CHECK_STR(field) \
4424     if (!strequal(pi1->field, pi2->field)) { \
4425         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4426             pi1->field, pi2->field)); \
4427         return False; \
4428     }
4429
4430 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4431                                         NT_PRINTER_INFO_LEVEL *p2)
4432 {
4433         NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4434
4435         /* Trivial conditions */
4436
4437         if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4438                 goto equal;
4439         }
4440
4441         if ((!p1 && p2) || (p1 && !p2) ||
4442             (!p1->info_2 && p2->info_2) ||
4443             (p1->info_2 && !p2->info_2)) {
4444                 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4445                            "differ\n"));
4446                 return False;
4447         }
4448
4449         /* Compare two nt_printer_info_level structures.  Don't compare
4450            status or cjobs as they seem to have something to do with the
4451            printer queue. */
4452
4453         pi1 = p1->info_2;
4454         pi2 = p2->info_2;
4455
4456         /* Don't check the attributes as we stomp on the value in
4457            check_printer_ok() anyway. */
4458
4459 #if 0
4460         PI_CHECK_INT(attributes);
4461 #endif
4462
4463         PI_CHECK_INT(priority);
4464         PI_CHECK_INT(default_priority);
4465         PI_CHECK_INT(starttime);
4466         PI_CHECK_INT(untiltime);
4467         PI_CHECK_INT(averageppm);
4468
4469         /* Yuck - don't check the printername or servername as the
4470            add_a_printer() code plays games with them.  You can't
4471            change the printername or the sharename through this interface
4472            in Samba. */
4473
4474         PI_CHECK_STR(sharename);
4475         PI_CHECK_STR(portname);
4476         PI_CHECK_STR(drivername);
4477         PI_CHECK_STR(comment);
4478         PI_CHECK_STR(location);
4479
4480         if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4481                 return False;
4482         }
4483
4484         PI_CHECK_STR(sepfile);
4485         PI_CHECK_STR(printprocessor);
4486         PI_CHECK_STR(datatype);
4487         PI_CHECK_STR(parameters);
4488
4489         if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4490                 return False;
4491         }
4492
4493         if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4494                 return False;
4495         }
4496
4497         PI_CHECK_INT(changeid);
4498         PI_CHECK_INT(c_setprinter);
4499         PI_CHECK_INT(setuptime);
4500
4501  equal:
4502         DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4503         return True;
4504 }
4505
4506 /********************************************************************
4507  * called by spoolss_api_setprinter
4508  * when updating a printer description
4509  ********************************************************************/
4510
4511 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4512                            const SPOOL_PRINTER_INFO_LEVEL *info,
4513                            DEVICEMODE *devmode)
4514 {
4515         int snum;
4516         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4517         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4518         WERROR result;
4519
4520         DEBUG(8,("update_printer\n"));
4521         
4522         result = WERR_OK;
4523
4524         if (level!=2) {
4525                 DEBUG(0,("Send a mail to samba@samba.org\n"));
4526                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4527                 result = WERR_UNKNOWN_LEVEL;
4528                 goto done;
4529         }
4530
4531         if (!Printer) {
4532                 result = WERR_BADFID;
4533                 goto done;
4534         }
4535
4536         if (!get_printer_snum(p, handle, &snum)) {
4537                 result = WERR_BADFID;
4538                 goto done;
4539         }
4540
4541         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4542             (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4543                 result = WERR_BADFID;
4544                 goto done;
4545         }
4546
4547         DEBUGADD(8,("Converting info_2 struct\n"));
4548
4549         /*
4550          * convert_printer_info converts the incoming
4551          * info from the client and overwrites the info
4552          * just read from the tdb in the pointer 'printer'.
4553          */
4554
4555         if (!convert_printer_info(info, printer, level)) {
4556                 result =  WERR_NOMEM;
4557                 goto done;
4558         }
4559
4560         if (info->info_2->devmode_ptr != 0) {
4561                 /* we have a valid devmode
4562                    convert it and link it*/
4563
4564                 DEBUGADD(8,("Converting the devicemode struct\n"));
4565                 if (!convert_devicemode(printer->info_2->printername, devmode,
4566                                 &printer->info_2->devmode)) {
4567                         result =  WERR_NOMEM;
4568                         goto done;
4569                 }
4570         }
4571
4572         /* Do sanity check on the requested changes for Samba */
4573
4574         if (!check_printer_ok(printer->info_2, snum)) {
4575                 result = WERR_INVALID_PARAM;
4576                 goto done;
4577         }
4578
4579         /* NT likes to call this function even though nothing has actually
4580            changed.  Check this so the user doesn't end up with an
4581            annoying permission denied dialog box. */
4582
4583         if (nt_printer_info_level_equal(printer, old_printer)) {
4584                 DEBUG(3, ("printer info has not changed\n"));
4585                 result = WERR_OK;
4586                 goto done;
4587         }
4588
4589         /* Check calling user has permission to update printer description */
4590
4591         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4592                 DEBUG(3, ("printer property change denied by security "
4593                           "descriptor\n"));
4594                 result = WERR_ACCESS_DENIED;
4595                 goto done;
4596         }
4597
4598         /* Call addprinter hook */
4599
4600         if (*lp_addprinter_cmd()) {
4601                 if (!add_printer_hook(printer)) {
4602                         result = WERR_ACCESS_DENIED;
4603                         goto done;
4604                 }
4605         }
4606         
4607         /* Update printer info */
4608         result = add_a_printer(*printer, 2);
4609
4610  done:
4611         free_a_printer(&printer, 2);
4612         free_a_printer(&old_printer, 2);
4613
4614         srv_spoolss_sendnotify(p, handle);
4615
4616         return result;
4617 }
4618
4619 /****************************************************************************
4620 ****************************************************************************/
4621
4622 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4623 {
4624         POLICY_HND *handle = &q_u->handle;
4625         uint32 level = q_u->level;
4626         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4627         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4628         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4629         uint32 command = q_u->command;
4630
4631         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4632         
4633         if (!Printer) {
4634                 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4635                 return WERR_BADFID;
4636         }
4637
4638         /* check the level */   
4639         switch (level) {
4640                 case 0:
4641                         return control_printer(handle, command, p);
4642                 case 2:
4643                         return update_printer(p, handle, level, info, devmode_ctr.devmode);
4644                 case 3:
4645                         return update_printer_sec(handle, level, info, p,
4646                                                   secdesc_ctr);
4647                 default:
4648                         return WERR_UNKNOWN_LEVEL;
4649         }
4650 }
4651
4652 /****************************************************************************
4653 ****************************************************************************/
4654
4655 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4656 {
4657         POLICY_HND *handle = &q_u->handle;
4658
4659         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4660         
4661         if (!Printer) {
4662                 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4663                 return WERR_BADFID;
4664         }
4665
4666         if (Printer->notify.client_connected==True)
4667                 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4668
4669         Printer->notify.flags=0;
4670         Printer->notify.options=0;
4671         Printer->notify.localmachine[0]='\0';
4672         Printer->notify.printerlocal=0;
4673         if (Printer->notify.option)
4674                 free_spool_notify_option(&Printer->notify.option);
4675         Printer->notify.client_connected=False;
4676
4677         return WERR_OK;
4678 }
4679
4680 /****************************************************************************
4681 ****************************************************************************/
4682
4683 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4684 {
4685         /* that's an [in out] buffer (despite appearences to the contrary) */
4686         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4687
4688         r_u->needed = 0;
4689         return WERR_INVALID_PARAM; /* this is what a NT server
4690                                            returns for AddJob. AddJob
4691                                            must fail on non-local
4692                                            printers */
4693 }
4694
4695 /****************************************************************************
4696 ****************************************************************************/
4697 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4698                             int position, int snum)
4699 {
4700         pstring temp_name;
4701         
4702         struct tm *t;
4703         
4704         t=gmtime(&queue->time);
4705         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4706
4707         job_info->jobid=queue->job;     
4708         init_unistr(&job_info->printername, lp_servicename(snum));
4709         init_unistr(&job_info->machinename, temp_name);
4710         init_unistr(&job_info->username, queue->user);
4711         init_unistr(&job_info->document, queue->file);
4712         init_unistr(&job_info->datatype, "RAW");
4713         init_unistr(&job_info->text_status, "");
4714         job_info->status=nt_printj_status(queue->status);
4715         job_info->priority=queue->priority;
4716         job_info->position=position;
4717         job_info->totalpages=0;
4718         job_info->pagesprinted=0;
4719
4720         make_systemtime(&job_info->submitted, t);
4721 }
4722
4723 /****************************************************************************
4724 ****************************************************************************/
4725 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4726                             int position, int snum, 
4727                             NT_PRINTER_INFO_LEVEL *ntprinter)
4728 {
4729         pstring temp_name;
4730         pstring chaine;
4731         struct tm *t;
4732
4733         t=gmtime(&queue->time);
4734         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4735
4736         job_info->jobid=queue->job;
4737         
4738         slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
4739
4740         init_unistr(&job_info->printername, chaine);
4741         
4742         init_unistr(&job_info->machinename, temp_name);
4743         init_unistr(&job_info->username, queue->user);
4744         init_unistr(&job_info->document, queue->file);
4745         init_unistr(&job_info->notifyname, queue->user);
4746         init_unistr(&job_info->datatype, "RAW");
4747         init_unistr(&job_info->printprocessor, "winprint");
4748         init_unistr(&job_info->parameters, "");
4749         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4750         init_unistr(&job_info->text_status, "");
4751         
4752 /* and here the security descriptor */
4753
4754         job_info->status=nt_printj_status(queue->status);
4755         job_info->priority=queue->priority;
4756         job_info->position=position;
4757         job_info->starttime=0;
4758         job_info->untiltime=0;
4759         job_info->totalpages=0;
4760         job_info->size=queue->size;
4761         make_systemtime(&(job_info->submitted), t);
4762         job_info->timeelapsed=0;
4763         job_info->pagesprinted=0;
4764
4765         if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4766                 return False;
4767         }
4768
4769         return (True);
4770 }
4771
4772 /****************************************************************************
4773  Enumjobs at level 1.
4774 ****************************************************************************/
4775 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4776                               NEW_BUFFER *buffer, uint32 offered,
4777                               uint32 *needed, uint32 *returned)
4778 {
4779         JOB_INFO_1 *info;
4780         int i;
4781         
4782         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4783         if (info==NULL) {
4784                 SAFE_FREE(queue);
4785                 *returned=0;
4786                 return WERR_NOMEM;
4787         }
4788         
4789         for (i=0; i<*returned; i++)
4790                 fill_job_info_1(&info[i], &queue[i], i, snum);
4791
4792         SAFE_FREE(queue);
4793
4794         /* check the required size. */  
4795         for (i=0; i<*returned; i++)
4796                 (*needed) += spoolss_size_job_info_1(&info[i]);
4797
4798         if (!alloc_buffer_size(buffer, *needed)) {
4799                 SAFE_FREE(info);
4800                 return WERR_INSUFFICIENT_BUFFER;
4801         }
4802
4803         /* fill the buffer with the structures */
4804         for (i=0; i<*returned; i++)
4805                 smb_io_job_info_1("", buffer, &info[i], 0);     
4806
4807         /* clear memory */
4808         SAFE_FREE(info);
4809
4810         if (*needed > offered) {
4811                 *returned=0;
4812                 return WERR_INSUFFICIENT_BUFFER;
4813         }
4814
4815         return WERR_OK;
4816 }
4817
4818 /****************************************************************************
4819  Enumjobs at level 2.
4820 ****************************************************************************/
4821 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4822                               NEW_BUFFER *buffer, uint32 offered,
4823                               uint32 *needed, uint32 *returned)
4824 {
4825         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4826         JOB_INFO_2 *info;
4827         int i;
4828         WERROR result;
4829         
4830         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4831         if (info==NULL) {
4832                 *returned=0;
4833                 return WERR_NOMEM;
4834         }
4835
4836         result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4837         if (!W_ERROR_IS_OK(result)) {
4838                 *returned = 0;
4839                 return result;
4840         }
4841                 
4842         for (i=0; i<*returned; i++)
4843                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4844
4845         free_a_printer(&ntprinter, 2);
4846         SAFE_FREE(queue);
4847
4848         /* check the required size. */  
4849         for (i=0; i<*returned; i++)
4850                 (*needed) += spoolss_size_job_info_2(&info[i]);
4851
4852         if (!alloc_buffer_size(buffer, *needed)) {
4853                 SAFE_FREE(info);
4854                 return WERR_INSUFFICIENT_BUFFER;
4855         }
4856
4857         /* fill the buffer with the structures */
4858         for (i=0; i<*returned; i++)
4859                 smb_io_job_info_2("", buffer, &info[i], 0);     
4860
4861         /* clear memory */
4862         for (i = 0; i < *returned; i++)
4863                 free_job_info_2(&info[i]);
4864
4865         SAFE_FREE(info);
4866
4867         if (*needed > offered) {
4868                 *returned=0;
4869                 return WERR_INSUFFICIENT_BUFFER;
4870         }
4871
4872         return WERR_OK;
4873 }
4874
4875 /****************************************************************************
4876  Enumjobs.
4877 ****************************************************************************/
4878
4879 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4880 {       
4881         POLICY_HND *handle = &q_u->handle;
4882 /*      uint32 firstjob = q_u->firstjob; - notused. */
4883 /*      uint32 numofjobs = q_u->numofjobs; - notused. */
4884         uint32 level = q_u->level;
4885         NEW_BUFFER *buffer = NULL;
4886         uint32 offered = q_u->offered;
4887         uint32 *needed = &r_u->needed;
4888         uint32 *returned = &r_u->returned;
4889
4890         int snum;
4891         print_status_struct prt_status;
4892         print_queue_struct *queue=NULL;
4893
4894         /* that's an [in out] buffer */
4895         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4896         buffer = r_u->buffer;
4897
4898         DEBUG(4,("_spoolss_enumjobs\n"));
4899
4900         *needed=0;
4901         *returned=0;
4902
4903         if (!get_printer_snum(p, handle, &snum))
4904                 return WERR_BADFID;
4905
4906         *returned = print_queue_status(snum, &queue, &prt_status);
4907         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4908
4909         if (*returned == 0) {
4910                 SAFE_FREE(queue);
4911                 return WERR_OK;
4912         }
4913
4914         switch (level) {
4915         case 1:
4916                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4917         case 2:
4918                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4919         default:
4920                 SAFE_FREE(queue);
4921                 *returned=0;
4922                 return WERR_UNKNOWN_LEVEL;
4923         }
4924 }
4925
4926 /****************************************************************************
4927 ****************************************************************************/
4928
4929 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4930 {
4931         return WERR_OK;
4932 }
4933
4934 /****************************************************************************
4935 ****************************************************************************/
4936
4937 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4938 {
4939         POLICY_HND *handle = &q_u->handle;
4940         uint32 jobid = q_u->jobid;
4941 /*      uint32 level = q_u->level; - notused. */
4942 /*      JOB_INFO *ctr = &q_u->ctr; - notused. */
4943         uint32 command = q_u->command;
4944
4945         struct current_user user;
4946         int snum;
4947         WERROR errcode = WERR_BADFUNC;
4948                 
4949         if (!get_printer_snum(p, handle, &snum)) {
4950                 return WERR_BADFID;
4951         }
4952
4953         if (!print_job_exists(jobid)) {
4954                 return WERR_INVALID_PRINTER_NAME;
4955         }
4956
4957         get_current_user(&user, p);     
4958
4959         switch (command) {
4960         case JOB_CONTROL_CANCEL:
4961         case JOB_CONTROL_DELETE:
4962                 if (print_job_delete(&user, jobid, &errcode)) {
4963                         errcode = WERR_OK;
4964                 }
4965                 break;
4966         case JOB_CONTROL_PAUSE:
4967                 if (print_job_pause(&user, jobid, &errcode)) {
4968                         errcode = WERR_OK;
4969                 }               
4970                 break;
4971         case JOB_CONTROL_RESTART:
4972         case JOB_CONTROL_RESUME:
4973                 if (print_job_resume(&user, jobid, &errcode)) {
4974                         errcode = WERR_OK;
4975                 }
4976                 break;
4977         default:
4978                 return WERR_UNKNOWN_LEVEL;
4979         }
4980
4981         return errcode;
4982 }
4983
4984 /****************************************************************************
4985  Enumerates all printer drivers at level 1.
4986 ****************************************************************************/
4987 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4988 {
4989         int i;
4990         int ndrivers;
4991         uint32 version;
4992         fstring *list = NULL;
4993
4994         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4995         DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
4996
4997         *returned=0;
4998
4999 #define MAX_VERSION 4
5000
5001         for (version=0; version<MAX_VERSION; version++) {
5002                 list=NULL;
5003                 ndrivers=get_ntdrivers(&list, architecture, version);
5004                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5005
5006                 if(ndrivers == -1)
5007                         return WERR_NOMEM;
5008
5009                 if(ndrivers != 0) {
5010                         if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5011                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5012                                 SAFE_FREE(driver_info_1);
5013                                 SAFE_FREE(list);
5014                                 return WERR_NOMEM;
5015                         }
5016                         else driver_info_1 = tdi1;
5017                 }
5018
5019                 for (i=0; i<ndrivers; i++) {
5020                         WERROR status;
5021                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5022                         ZERO_STRUCT(driver);
5023                         status = get_a_printer_driver(&driver, 3, list[i], 
5024                                                       architecture, version);
5025                         if (!W_ERROR_IS_OK(status)) {
5026                                 SAFE_FREE(list);
5027                                 return status;
5028                         }
5029                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
5030                         free_a_printer_driver(driver, 3);
5031                 }       
5032
5033                 *returned+=ndrivers;
5034                 SAFE_FREE(list);
5035         }
5036         
5037         /* check the required size. */
5038         for (i=0; i<*returned; i++) {
5039                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5040                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5041         }
5042
5043         if (!alloc_buffer_size(buffer, *needed)) {
5044                 SAFE_FREE(driver_info_1);
5045                 return WERR_INSUFFICIENT_BUFFER;
5046         }
5047
5048         /* fill the buffer with the driver structures */
5049         for (i=0; i<*returned; i++) {
5050                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5051                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5052         }
5053
5054         SAFE_FREE(driver_info_1);
5055
5056         if (*needed > offered) {
5057                 *returned=0;
5058                 return WERR_INSUFFICIENT_BUFFER;
5059         }
5060
5061         return WERR_OK;
5062 }
5063
5064 /****************************************************************************
5065  Enumerates all printer drivers at level 2.
5066 ****************************************************************************/
5067 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5068 {
5069         int i;
5070         int ndrivers;
5071         uint32 version;
5072         fstring *list = NULL;
5073
5074         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5075         DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5076
5077         *returned=0;
5078
5079 #define MAX_VERSION 4
5080
5081         for (version=0; version<MAX_VERSION; version++) {
5082                 list=NULL;
5083                 ndrivers=get_ntdrivers(&list, architecture, version);
5084                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5085
5086                 if(ndrivers == -1)
5087                         return WERR_NOMEM;
5088
5089                 if(ndrivers != 0) {
5090                         if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5091                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5092                                 SAFE_FREE(driver_info_2);
5093                                 SAFE_FREE(list);
5094                                 return WERR_NOMEM;
5095                         }
5096                         else driver_info_2 = tdi2;
5097                 }
5098                 
5099                 for (i=0; i<ndrivers; i++) {
5100                         WERROR status;
5101
5102                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5103                         ZERO_STRUCT(driver);
5104                         status = get_a_printer_driver(&driver, 3, list[i], 
5105                                                       architecture, version);
5106                         if (!W_ERROR_IS_OK(status)) {
5107                                 SAFE_FREE(list);
5108                                 return status;
5109                         }
5110                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
5111                         free_a_printer_driver(driver, 3);
5112                 }       
5113
5114                 *returned+=ndrivers;
5115                 SAFE_FREE(list);
5116         }
5117         
5118         /* check the required size. */
5119         for (i=0; i<*returned; i++) {
5120                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5121                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5122         }
5123
5124         if (!alloc_buffer_size(buffer, *needed)) {
5125                 SAFE_FREE(driver_info_2);
5126                 return WERR_INSUFFICIENT_BUFFER;
5127         }
5128
5129         /* fill the buffer with the form structures */
5130         for (i=0; i<*returned; i++) {
5131                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5132                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5133         }
5134
5135         SAFE_FREE(driver_info_2);
5136
5137         if (*needed > offered) {
5138                 *returned=0;
5139                 return WERR_INSUFFICIENT_BUFFER;
5140         }
5141
5142         return WERR_OK;
5143 }
5144
5145 /****************************************************************************
5146  Enumerates all printer drivers at level 3.
5147 ****************************************************************************/
5148 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5149 {
5150         int i;
5151         int ndrivers;
5152         uint32 version;
5153         fstring *list = NULL;
5154
5155         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5156         DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5157
5158         *returned=0;
5159
5160 #define MAX_VERSION 4
5161
5162         for (version=0; version<MAX_VERSION; version++) {
5163                 list=NULL;
5164                 ndrivers=get_ntdrivers(&list, architecture, version);
5165                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5166
5167                 if(ndrivers == -1)
5168                         return WERR_NOMEM;
5169
5170                 if(ndrivers != 0) {
5171                         if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5172                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5173                                 SAFE_FREE(driver_info_3);
5174                                 SAFE_FREE(list);
5175                                 return WERR_NOMEM;
5176                         }
5177                         else driver_info_3 = tdi3;
5178                 }
5179
5180                 for (i=0; i<ndrivers; i++) {
5181                         WERROR status;
5182
5183                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5184                         ZERO_STRUCT(driver);
5185                         status = get_a_printer_driver(&driver, 3, list[i], 
5186                                                       architecture, version);
5187                         if (!W_ERROR_IS_OK(status)) {
5188                                 SAFE_FREE(list);
5189                                 return status;
5190                         }
5191                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
5192                         free_a_printer_driver(driver, 3);
5193                 }       
5194
5195                 *returned+=ndrivers;
5196                 SAFE_FREE(list);
5197         }
5198
5199         /* check the required size. */
5200         for (i=0; i<*returned; i++) {
5201                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5202                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5203         }
5204
5205         if (!alloc_buffer_size(buffer, *needed)) {
5206                 SAFE_FREE(driver_info_3);
5207                 return WERR_INSUFFICIENT_BUFFER;
5208         }
5209         
5210         /* fill the buffer with the driver structures */
5211         for (i=0; i<*returned; i++) {
5212                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5213                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5214         }
5215
5216         for (i=0; i<*returned; i++)
5217                 SAFE_FREE(driver_info_3[i].dependentfiles);
5218         
5219         SAFE_FREE(driver_info_3);
5220         
5221         if (*needed > offered) {
5222                 *returned=0;
5223                 return WERR_INSUFFICIENT_BUFFER;
5224         }
5225
5226         return WERR_OK;
5227 }
5228
5229 /****************************************************************************
5230  Enumerates all printer drivers.
5231 ****************************************************************************/
5232
5233 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5234 {
5235 /*      UNISTR2 *name = &q_u->name; - notused. */
5236         UNISTR2 *environment = &q_u->environment;
5237         uint32 level = q_u->level;
5238         NEW_BUFFER *buffer = NULL;
5239         uint32 offered = q_u->offered;
5240         uint32 *needed = &r_u->needed;
5241         uint32 *returned = &r_u->returned;
5242
5243         fstring *list = NULL;
5244         fstring servername;
5245         fstring architecture;
5246
5247         /* that's an [in out] buffer */
5248         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5249         buffer = r_u->buffer;
5250
5251         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5252         fstrcpy(servername, get_called_name());
5253         *needed=0;
5254         *returned=0;
5255
5256         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5257
5258         switch (level) {
5259         case 1:
5260                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5261         case 2:
5262                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5263         case 3:
5264                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5265         default:
5266                 *returned=0;
5267                 SAFE_FREE(list);
5268                 return WERR_UNKNOWN_LEVEL;
5269         }
5270 }
5271
5272 /****************************************************************************
5273 ****************************************************************************/
5274
5275 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5276 {
5277         form->flag=list->flag;
5278         init_unistr(&form->name, list->name);
5279         form->width=list->width;
5280         form->length=list->length;
5281         form->left=list->left;
5282         form->top=list->top;
5283         form->right=list->right;
5284         form->bottom=list->bottom;      
5285 }
5286         
5287 /****************************************************************************
5288 ****************************************************************************/
5289
5290 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5291 {
5292 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5293         uint32 level = q_u->level;
5294         NEW_BUFFER *buffer = NULL;
5295         uint32 offered = q_u->offered;
5296         uint32 *needed = &r_u->needed;
5297         uint32 *numofforms = &r_u->numofforms;
5298         uint32 numbuiltinforms;
5299
5300         nt_forms_struct *list=NULL;
5301         nt_forms_struct *builtinlist=NULL;
5302         FORM_1 *forms_1;
5303         int buffer_size=0;
5304         int i;
5305
5306         /* that's an [in out] buffer */
5307         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5308         buffer = r_u->buffer;
5309
5310         DEBUG(4,("_spoolss_enumforms\n"));
5311         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5312         DEBUGADD(5,("Info level [%d]\n",          level));
5313
5314         numbuiltinforms = get_builtin_ntforms(&builtinlist);
5315         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
5316         *numofforms = get_ntforms(&list);
5317         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
5318         *numofforms += numbuiltinforms;
5319
5320         if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5321
5322         switch (level) {
5323         case 1:
5324                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5325                         *numofforms=0;
5326                         return WERR_NOMEM;
5327                 }
5328
5329                 /* construct the list of form structures */
5330                 for (i=0; i<numbuiltinforms; i++) {
5331                         DEBUGADD(6,("Filling form number [%d]\n",i));
5332                         fill_form_1(&forms_1[i], &builtinlist[i]);
5333                 }
5334                 
5335                 SAFE_FREE(builtinlist);
5336
5337                 for (; i<*numofforms; i++) {
5338                         DEBUGADD(6,("Filling form number [%d]\n",i));
5339                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5340                 }
5341                 
5342                 SAFE_FREE(list);
5343
5344                 /* check the required size. */
5345                 for (i=0; i<numbuiltinforms; i++) {
5346                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5347                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5348                 }
5349                 for (; i<*numofforms; i++) {
5350                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5351                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5352                 }
5353
5354                 *needed=buffer_size;            
5355                 
5356                 if (!alloc_buffer_size(buffer, buffer_size)){
5357                         SAFE_FREE(forms_1);
5358                         return WERR_INSUFFICIENT_BUFFER;
5359                 }
5360
5361                 /* fill the buffer with the form structures */
5362                 for (i=0; i<numbuiltinforms; i++) {
5363                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5364                         smb_io_form_1("", buffer, &forms_1[i], 0);
5365                 }
5366                 for (; i<*numofforms; i++) {
5367                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5368                         smb_io_form_1("", buffer, &forms_1[i], 0);
5369                 }
5370
5371                 SAFE_FREE(forms_1);
5372
5373                 if (*needed > offered) {
5374                         *numofforms=0;
5375                         return WERR_INSUFFICIENT_BUFFER;
5376                 }
5377                 else
5378                         return WERR_OK;
5379                         
5380         default:
5381                 SAFE_FREE(list);
5382                 SAFE_FREE(builtinlist);
5383                 return WERR_UNKNOWN_LEVEL;
5384         }
5385
5386 }
5387
5388 /****************************************************************************
5389 ****************************************************************************/
5390
5391 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5392 {
5393 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5394         uint32 level = q_u->level;
5395         UNISTR2 *uni_formname = &q_u->formname;
5396         NEW_BUFFER *buffer = NULL;
5397         uint32 offered = q_u->offered;
5398         uint32 *needed = &r_u->needed;
5399
5400         nt_forms_struct *list=NULL;
5401         nt_forms_struct builtin_form;
5402         BOOL foundBuiltin;
5403         FORM_1 form_1;
5404         fstring form_name;
5405         int buffer_size=0;
5406         int numofforms=0, i=0;
5407
5408         /* that's an [in out] buffer */
5409         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5410         buffer = r_u->buffer;
5411
5412         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5413
5414         DEBUG(4,("_spoolss_getform\n"));
5415         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5416         DEBUGADD(5,("Info level [%d]\n",          level));
5417
5418         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5419         if (!foundBuiltin) {
5420                 numofforms = get_ntforms(&list);
5421                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
5422
5423                 if (numofforms == 0)
5424                         return WERR_BADFID;
5425         }
5426
5427         switch (level) {
5428         case 1:
5429                 if (foundBuiltin) {
5430                         fill_form_1(&form_1, &builtin_form);
5431                 } else {
5432
5433                         /* Check if the requested name is in the list of form structures */
5434                         for (i=0; i<numofforms; i++) {
5435
5436                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5437
5438                                 if (strequal(form_name, list[i].name)) {
5439                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5440                                         fill_form_1(&form_1, &list[i]);
5441                                         break;
5442                                 }
5443                         }
5444                         
5445                         SAFE_FREE(list);
5446                         if (i == numofforms) {
5447                                 return WERR_BADFID;
5448                         }
5449                 }
5450                 /* check the required size. */
5451
5452                 *needed=spoolss_size_form_1(&form_1);
5453                 
5454                 if (!alloc_buffer_size(buffer, buffer_size)){
5455                         return WERR_INSUFFICIENT_BUFFER;
5456                 }
5457
5458                 if (*needed > offered) {
5459                         return WERR_INSUFFICIENT_BUFFER;
5460                 }
5461
5462                 /* fill the buffer with the form structures */
5463                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5464                 smb_io_form_1("", buffer, &form_1, 0);
5465
5466                 return WERR_OK;
5467                         
5468         default:
5469                 SAFE_FREE(list);
5470                 return WERR_UNKNOWN_LEVEL;
5471         }
5472 }
5473
5474 /****************************************************************************
5475 ****************************************************************************/
5476 static void fill_port_1(PORT_INFO_1 *port, char *name)
5477 {
5478         init_unistr(&port->port_name, name);
5479 }
5480
5481 /****************************************************************************
5482 ****************************************************************************/
5483 static void fill_port_2(PORT_INFO_2 *port, char *name)
5484 {
5485         init_unistr(&port->port_name, name);
5486         init_unistr(&port->monitor_name, "Local Monitor");
5487         init_unistr(&port->description, "Local Port");
5488 #define PORT_TYPE_WRITE 1
5489         port->port_type=PORT_TYPE_WRITE;
5490         port->reserved=0x0;     
5491 }
5492
5493 /****************************************************************************
5494  enumports level 1.
5495 ****************************************************************************/
5496 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5497 {
5498         PORT_INFO_1 *ports=NULL;
5499         int i=0;
5500
5501         if (*lp_enumports_cmd()) {
5502                 char *cmd = lp_enumports_cmd();
5503                 char **qlines;
5504                 pstring command;
5505                 int numlines;
5506                 int ret;
5507                 int fd;
5508
5509                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5510
5511                 DEBUG(10,("Running [%s]\n", command));
5512                 ret = smbrun(command, &fd);
5513                 DEBUG(10,("Returned [%d]\n", ret));
5514                 if (ret != 0) {
5515                         if (fd != -1)
5516                                 close(fd);
5517                         /* Is this the best error to return here? */
5518                         return WERR_ACCESS_DENIED;
5519                 }
5520
5521                 numlines = 0;
5522                 qlines = fd_lines_load(fd, &numlines);
5523                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5524                 close(fd);
5525
5526                 if(numlines) {
5527                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5528                                 DEBUG(10,("Returning WERR_NOMEM [%s]\n", 
5529                                           werror_str(WERR_NOMEM)));
5530                                 file_lines_free(qlines);
5531                                 return WERR_NOMEM;
5532                         }
5533
5534                         for (i=0; i<numlines; i++) {
5535                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5536                                 fill_port_1(&ports[i], qlines[i]);
5537                         }
5538
5539                         file_lines_free(qlines);
5540                 }
5541
5542                 *returned = numlines;
5543
5544         } else {
5545                 *returned = 1; /* Sole Samba port returned. */
5546
5547                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5548                         return WERR_NOMEM;
5549         
5550                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5551
5552                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5553         }
5554
5555         /* check the required size. */
5556         for (i=0; i<*returned; i++) {
5557                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5558                 *needed += spoolss_size_port_info_1(&ports[i]);
5559         }
5560                 
5561         if (!alloc_buffer_size(buffer, *needed)) {
5562                 SAFE_FREE(ports);
5563                 return WERR_INSUFFICIENT_BUFFER;
5564         }
5565
5566         /* fill the buffer with the ports structures */
5567         for (i=0; i<*returned; i++) {
5568                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5569                 smb_io_port_1("", buffer, &ports[i], 0);
5570         }
5571
5572         SAFE_FREE(ports);
5573
5574         if (*needed > offered) {
5575                 *returned=0;
5576                 return WERR_INSUFFICIENT_BUFFER;
5577         }
5578
5579         return WERR_OK;
5580 }
5581
5582 /****************************************************************************
5583  enumports level 2.
5584 ****************************************************************************/
5585
5586 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5587 {
5588         PORT_INFO_2 *ports=NULL;
5589         int i=0;
5590
5591         if (*lp_enumports_cmd()) {
5592                 char *cmd = lp_enumports_cmd();
5593                 char *path;
5594                 char **qlines;
5595                 pstring tmp_file;
5596                 pstring command;
5597                 int numlines;
5598                 int ret;
5599                 int fd;
5600
5601                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5602                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5603                 else
5604                         path = lp_lockdir();
5605
5606                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5607                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5608
5609                 unlink(tmp_file);
5610                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5611                 ret = smbrun(command, &fd);
5612                 DEBUGADD(10,("returned [%d]\n", ret));
5613                 if (ret != 0) {
5614                         if (fd != -1)
5615                                 close(fd);
5616                         /* Is this the best error to return here? */
5617                         return WERR_ACCESS_DENIED;
5618                 }
5619
5620                 numlines = 0;
5621                 qlines = fd_lines_load(fd, &numlines);
5622                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5623                 close(fd);
5624
5625                 if(numlines) {
5626                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5627                                 file_lines_free(qlines);
5628                                 return WERR_NOMEM;
5629                         }
5630
5631                         for (i=0; i<numlines; i++) {
5632                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5633                                 fill_port_2(&(ports[i]), qlines[i]);
5634                         }
5635
5636                         file_lines_free(qlines);
5637                 }
5638
5639                 *returned = numlines;
5640
5641         } else {
5642
5643                 *returned = 1;
5644
5645                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5646                         return WERR_NOMEM;
5647         
5648                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5649
5650                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5651         }
5652
5653         /* check the required size. */
5654         for (i=0; i<*returned; i++) {
5655                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5656                 *needed += spoolss_size_port_info_2(&ports[i]);
5657         }
5658                 
5659         if (!alloc_buffer_size(buffer, *needed)) {
5660                 SAFE_FREE(ports);
5661                 return WERR_INSUFFICIENT_BUFFER;
5662         }
5663
5664         /* fill the buffer with the ports structures */
5665         for (i=0; i<*returned; i++) {
5666                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5667                 smb_io_port_2("", buffer, &ports[i], 0);
5668         }
5669
5670         SAFE_FREE(ports);
5671
5672         if (*needed > offered) {
5673                 *returned=0;
5674                 return WERR_INSUFFICIENT_BUFFER;
5675         }
5676
5677         return WERR_OK;
5678 }
5679
5680 /****************************************************************************
5681  enumports.
5682 ****************************************************************************/
5683
5684 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5685 {
5686 /*      UNISTR2 *name = &q_u->name; - notused. */
5687         uint32 level = q_u->level;
5688         NEW_BUFFER *buffer = NULL;
5689         uint32 offered = q_u->offered;
5690         uint32 *needed = &r_u->needed;
5691         uint32 *returned = &r_u->returned;
5692
5693         /* that's an [in out] buffer */
5694         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5695         buffer = r_u->buffer;
5696
5697         DEBUG(4,("_spoolss_enumports\n"));
5698         
5699         *returned=0;
5700         *needed=0;
5701         
5702         switch (level) {
5703         case 1:
5704                 return enumports_level_1(buffer, offered, needed, returned);
5705         case 2:
5706                 return enumports_level_2(buffer, offered, needed, returned);
5707         default:
5708                 return WERR_UNKNOWN_LEVEL;
5709         }
5710 }
5711
5712 /****************************************************************************
5713 ****************************************************************************/
5714 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5715                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5716                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5717                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5718                                 POLICY_HND *handle)
5719 {
5720         NT_PRINTER_INFO_LEVEL *printer = NULL;
5721         fstring name;
5722         int     snum;
5723         WERROR err = WERR_OK;
5724
5725         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5726                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5727                 return WERR_NOMEM;
5728         }
5729
5730         ZERO_STRUCTP(printer);
5731
5732         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5733         if (!convert_printer_info(info, printer, 2)) {
5734                 free_a_printer(&printer, 2);
5735                 return WERR_NOMEM;
5736         }
5737
5738         /* check to see if the printer already exists */
5739
5740         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5741                 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n", 
5742                         printer->info_2->sharename));
5743                 free_a_printer(&printer, 2);
5744                 return WERR_PRINTER_ALREADY_EXISTS;
5745         }
5746
5747         if (*lp_addprinter_cmd() )
5748                 if ( !add_printer_hook(printer) ) {
5749                         free_a_printer(&printer,2);
5750                         return WERR_ACCESS_DENIED;
5751         }
5752
5753         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
5754              printer->info_2->sharename);
5755
5756         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5757                 free_a_printer(&printer,2);
5758                 return WERR_ACCESS_DENIED;
5759         }
5760
5761         /* you must be a printer admin to add a new printer */
5762         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5763                 free_a_printer(&printer,2);
5764                 return WERR_ACCESS_DENIED;              
5765         }
5766         
5767         /*
5768          * Do sanity check on the requested changes for Samba.
5769          */
5770
5771         if (!check_printer_ok(printer->info_2, snum)) {
5772                 free_a_printer(&printer,2);
5773                 return WERR_INVALID_PARAM;
5774         }
5775
5776     /*
5777          * When a printer is created, the drivername bound to the printer is used
5778          * to lookup previously saved driver initialization info, which is then 
5779          * bound to the new printer, simulating what happens in the Windows arch.
5780          */
5781         set_driver_init(printer, 2);
5782         
5783         /* write the ASCII on disk */
5784         err = add_a_printer(*printer, 2);
5785         if (!W_ERROR_IS_OK(err)) {
5786                 free_a_printer(&printer,2);
5787                 return err;
5788         }
5789
5790         if (!open_printer_hnd(p, handle, name)) {
5791                 /* Handle open failed - remove addition. */
5792                 del_a_printer(printer->info_2->sharename);
5793                 free_a_printer(&printer,2);
5794                 return WERR_ACCESS_DENIED;
5795         }
5796
5797         free_a_printer(&printer,2);
5798
5799         srv_spoolss_sendnotify(p, handle);
5800
5801         return WERR_OK;
5802 }
5803
5804 /****************************************************************************
5805 ****************************************************************************/
5806
5807 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5808 {
5809         UNISTR2 *uni_srv_name = &q_u->server_name;
5810         uint32 level = q_u->level;
5811         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5812         uint32 unk0 = q_u->unk0;
5813         uint32 unk1 = q_u->unk1;
5814         uint32 unk2 = q_u->unk2;
5815         uint32 unk3 = q_u->unk3;
5816         uint32 user_switch = q_u->user_switch;
5817         SPOOL_USER_CTR *user = &q_u->user_ctr;
5818         POLICY_HND *handle = &r_u->handle;
5819
5820         switch (level) {
5821                 case 1:
5822                         /* we don't handle yet */
5823                         /* but I know what to do ... */
5824                         return WERR_UNKNOWN_LEVEL;
5825                 case 2:
5826                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5827                                                             unk0, unk1, unk2, unk3,
5828                                                             user_switch, user, handle);
5829                 default:
5830                         return WERR_UNKNOWN_LEVEL;
5831         }
5832 }
5833
5834 /****************************************************************************
5835 ****************************************************************************/
5836
5837 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5838 {
5839 /*      UNISTR2 *server_name = &q_u->server_name; - notused. */
5840         uint32 level = q_u->level;
5841         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5842         WERROR err = WERR_OK;
5843         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5844         struct current_user user;
5845         
5846         ZERO_STRUCT(driver);
5847
5848         get_current_user(&user, p);     
5849         
5850         if (!convert_printer_driver_info(info, &driver, level)) {
5851                 err = WERR_NOMEM;
5852                 goto done;
5853         }
5854
5855         DEBUG(5,("Cleaning driver's information\n"));
5856         err = clean_up_driver_struct(driver, level, &user);
5857         if (!W_ERROR_IS_OK(err))
5858                 goto done;
5859
5860         DEBUG(5,("Moving driver to final destination\n"));
5861         if(!move_driver_to_download_area(driver, level, &user, &err)) {
5862                 if (W_ERROR_IS_OK(err))
5863                         err = WERR_ACCESS_DENIED;
5864                 goto done;
5865         }
5866
5867         if (add_a_printer_driver(driver, level)!=0) {
5868                 err = WERR_ACCESS_DENIED;
5869                 goto done;
5870         }
5871
5872  done:
5873         free_a_printer_driver(driver, level);
5874         return err;
5875 }
5876
5877 /****************************************************************************
5878 ****************************************************************************/
5879 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5880 {
5881         init_unistr(&info->name, name);
5882 }
5883
5884 /****************************************************************************
5885 ****************************************************************************/
5886 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5887 {
5888         pstring path;
5889         pstring long_archi;
5890         pstring short_archi;
5891         DRIVER_DIRECTORY_1 *info=NULL;
5892
5893         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5894
5895         if (get_short_archi(short_archi, long_archi)==False)
5896                 return WERR_INVALID_ENVIRONMENT;
5897
5898         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5899                 return WERR_NOMEM;
5900
5901         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
5902
5903         DEBUG(4,("printer driver directory: [%s]\n", path));
5904
5905         fill_driverdir_1(info, path);
5906         
5907         *needed += spoolss_size_driverdir_info_1(info);
5908
5909         if (!alloc_buffer_size(buffer, *needed)) {
5910                 SAFE_FREE(info);
5911                 return WERR_INSUFFICIENT_BUFFER;
5912         }
5913
5914         smb_io_driverdir_1("", buffer, info, 0);
5915
5916         SAFE_FREE(info);
5917         
5918         if (*needed > offered)
5919                 return WERR_INSUFFICIENT_BUFFER;
5920
5921         return WERR_OK;
5922 }
5923
5924 /****************************************************************************
5925 ****************************************************************************/
5926
5927 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5928 {
5929         UNISTR2 *name = &q_u->name;
5930         UNISTR2 *uni_environment = &q_u->environment;
5931         uint32 level = q_u->level;
5932         NEW_BUFFER *buffer = NULL;
5933         uint32 offered = q_u->offered;
5934         uint32 *needed = &r_u->needed;
5935
5936         /* that's an [in out] buffer */
5937         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5938         buffer = r_u->buffer;
5939
5940         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5941
5942         *needed=0;
5943
5944         switch(level) {
5945         case 1:
5946                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5947         default:
5948                 return WERR_UNKNOWN_LEVEL;
5949         }
5950 }
5951         
5952 /****************************************************************************
5953 ****************************************************************************/
5954
5955 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5956 {
5957         POLICY_HND *handle = &q_u->handle;
5958         uint32 idx = q_u->index;
5959         uint32 in_value_len = q_u->valuesize;
5960         uint32 in_data_len = q_u->datasize;
5961         uint32 *out_max_value_len = &r_u->valuesize;
5962         uint16 **out_value = &r_u->value;
5963         uint32 *out_value_len = &r_u->realvaluesize;
5964         uint32 *out_type = &r_u->type;
5965         uint32 *out_max_data_len = &r_u->datasize;
5966         uint8  **data_out = &r_u->data;
5967         uint32 *out_data_len = &r_u->realdatasize;
5968
5969         NT_PRINTER_INFO_LEVEL *printer = NULL;
5970         
5971         fstring value;
5972         
5973         uint32 param_index;
5974         uint32 biggest_valuesize;
5975         uint32 biggest_datasize;
5976         uint32 data_len;
5977         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5978         int snum;
5979         uint8 *data=NULL;
5980         uint32 type;
5981         WERROR result;
5982
5983         ZERO_STRUCT(printer);
5984         
5985         *out_type=0;
5986
5987         *out_max_data_len=0;
5988         *data_out=NULL;
5989         *out_data_len=0;
5990
5991         DEBUG(5,("spoolss_enumprinterdata\n"));
5992
5993         if (!Printer) {
5994                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5995                 return WERR_BADFID;
5996         }
5997
5998         if (!get_printer_snum(p,handle, &snum))
5999                 return WERR_BADFID;
6000         
6001         result = get_a_printer(&printer, 2, lp_servicename(snum));
6002         if (!W_ERROR_IS_OK(result))
6003                 return result;
6004
6005         /*
6006          * The NT machine wants to know the biggest size of value and data
6007          *
6008          * cf: MSDN EnumPrinterData remark section
6009          */
6010         if ( (in_value_len==0) && (in_data_len==0) ) {
6011                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6012
6013 #if 0
6014                 /*
6015                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6016                  * if this parameter size doesn't exist.
6017                  * Ok - my opinion here is that the client is not asking for the greatest
6018                  * possible size of all the parameters, but is asking specifically for the size needed
6019                  * for this specific parameter. In that case we can remove the loop below and
6020                  * simplify this lookup code considerably. JF - comments welcome. JRA.
6021                  */
6022
6023                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6024                         SAFE_FREE(data);
6025                         free_a_printer(&printer, 2);
6026                         return WERR_NO_MORE_ITEMS;
6027                 }
6028 #endif
6029
6030                 SAFE_FREE(data);
6031
6032                 param_index=0;
6033                 biggest_valuesize=0;
6034                 biggest_datasize=0;
6035                 
6036                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6037                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6038                         if (data_len > biggest_datasize) biggest_datasize=data_len;
6039
6040                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6041
6042                         SAFE_FREE(data);
6043                         param_index++;
6044                 }
6045
6046                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6047                 *out_value_len=2*(1+biggest_valuesize);
6048                 *out_data_len=biggest_datasize;
6049
6050                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6051
6052                 free_a_printer(&printer, 2);
6053                 return WERR_OK;
6054         }
6055         
6056         /*
6057          * the value len is wrong in NT sp3
6058          * that's the number of bytes not the number of unicode chars
6059          */
6060
6061         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6062
6063                 SAFE_FREE(data);
6064                 free_a_printer(&printer, 2);
6065
6066                 /* out_value should default to "" or else NT4 has
6067                    problems unmarshalling the response */
6068
6069                 *out_max_value_len=(in_value_len/sizeof(uint16));
6070                 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
6071                         return WERR_NOMEM;
6072
6073                 ZERO_STRUCTP(*out_value);
6074                 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6075
6076                 /* the data is counted in bytes */
6077                 *out_max_data_len = in_data_len;
6078                 *out_data_len = in_data_len;
6079                 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
6080                         return WERR_NOMEM;
6081
6082                 memset(*data_out,'\0',in_data_len);
6083
6084                 return WERR_NO_MORE_ITEMS;
6085         }
6086
6087         free_a_printer(&printer, 2);
6088
6089         /*
6090          * the value is:
6091          * - counted in bytes in the request
6092          * - counted in UNICODE chars in the max reply
6093          * - counted in bytes in the real size
6094          *
6095          * take a pause *before* coding not *during* coding
6096          */
6097         
6098         *out_max_value_len=(in_value_len/sizeof(uint16));
6099         if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6100                 SAFE_FREE(data);
6101                 return WERR_NOMEM;
6102         }
6103         
6104         *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6105
6106         *out_type=type;
6107
6108         /* the data is counted in bytes */
6109         *out_max_data_len=in_data_len;
6110         if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6111                 SAFE_FREE(data);
6112                 return WERR_NOMEM;
6113         }
6114         
6115         memcpy(*data_out, data, (size_t)data_len);
6116         *out_data_len=data_len;
6117
6118         SAFE_FREE(data);
6119         
6120         return WERR_OK;
6121 }
6122
6123 /****************************************************************************
6124 ****************************************************************************/
6125
6126 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6127 {
6128         POLICY_HND *handle = &q_u->handle;
6129         UNISTR2 *value = &q_u->value;
6130         uint32 type = q_u->type;
6131 /*      uint32 max_len = q_u->max_len; - notused. */
6132         uint8 *data = q_u->data;
6133         uint32 real_len = q_u->real_len;
6134 /*      uint32 numeric_data = q_u->numeric_data; - notused. */
6135
6136         NT_PRINTER_INFO_LEVEL *printer = NULL;
6137         NT_PRINTER_PARAM *param = NULL, old_param;
6138         int snum=0;
6139         WERROR status = WERR_OK;
6140         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6141         
6142         DEBUG(5,("spoolss_setprinterdata\n"));
6143
6144         if (!Printer) {
6145                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6146                 return WERR_BADFID;
6147         }
6148
6149         if (!get_printer_snum(p,handle, &snum))
6150                 return WERR_BADFID;
6151
6152         ZERO_STRUCT(old_param);
6153
6154         /* 
6155          * Access check : NT returns "access denied" if you make a 
6156          * SetPrinterData call without the necessary privildge.
6157          * we were originally returning OK if nothing changed
6158          * which made Win2k issue **a lot** of SetPrinterData
6159          * when connecting to a printer  --jerry
6160          */
6161
6162         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6163                 DEBUG(3, ("security descriptor change denied by existing "
6164                           "security descriptor\n"));
6165                 status = WERR_ACCESS_DENIED;
6166                 goto done;
6167         }
6168
6169         /* Check if we are making any changes or not.  Return true if
6170            nothing is actually changing.  This is not needed anymore but
6171            has been left in as an optimization to keep from from
6172            writing to disk as often  --jerry  */
6173
6174         status = get_a_printer(&printer, 2, lp_servicename(snum));
6175         if (!W_ERROR_IS_OK(status))
6176                 return status;
6177
6178         convert_specific_param(&param, value , type, data, real_len);
6179
6180
6181         if (get_specific_param(*printer, 2, param->value, &old_param.data,
6182                                &old_param.type, (uint32 *)&old_param.data_len)) {
6183
6184                 if (param->type == old_param.type &&
6185                     param->data_len == old_param.data_len &&
6186                     memcmp(param->data, old_param.data,
6187                            old_param.data_len) == 0) {
6188
6189                         DEBUG(3, ("setprinterdata hasn't changed\n"));
6190                         status = WERR_OK;
6191                         goto done;
6192                 }
6193         }
6194
6195         unlink_specific_param_if_exist(printer->info_2, param);
6196         
6197         /*
6198          * When client side code sets a magic printer data key, detect it and save
6199          * the current printer data and the magic key's data (its the DEVMODE) for
6200          * future printer/driver initializations.
6201          */
6202         if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6203                 /*
6204                  * Set devmode and printer initialization info
6205                  */
6206                 status = save_driver_init(printer, 2, param);
6207         }
6208         else {
6209                 add_a_specific_param(printer->info_2, &param);
6210                 status = mod_a_printer(*printer, 2);
6211         }
6212
6213  done:
6214         free_a_printer(&printer, 2);
6215         if (param)
6216                 free_nt_printer_param(&param);
6217         SAFE_FREE(old_param.data);
6218
6219         return status;
6220 }
6221
6222 /****************************************************************************
6223 ****************************************************************************/
6224
6225 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6226 {
6227         POLICY_HND *handle = &q_u->handle;
6228         UNISTR2 *value = &q_u->valuename;
6229
6230         NT_PRINTER_INFO_LEVEL *printer = NULL;
6231         NT_PRINTER_PARAM param;
6232         int snum=0;
6233         WERROR status = WERR_OK;
6234         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6235         
6236         DEBUG(5,("spoolss_deleteprinterdata\n"));
6237         
6238         if (!Printer) {
6239                 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6240                 return WERR_BADFID;
6241         }
6242
6243         if (!get_printer_snum(p, handle, &snum))
6244                 return WERR_BADFID;
6245
6246         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6247                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6248                           "change denied by existing security descriptor\n"));
6249                 return WERR_ACCESS_DENIED;
6250         }
6251
6252         status = get_a_printer(&printer, 2, lp_servicename(snum));
6253         if (!W_ERROR_IS_OK(status))
6254                 return status;
6255
6256         ZERO_STRUCTP(&param);
6257         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6258
6259         if(!unlink_specific_param_if_exist(printer->info_2, &param))
6260                 status = WERR_INVALID_PARAM;
6261         else
6262                 status = mod_a_printer(*printer, 2);
6263
6264         free_a_printer(&printer, 2);
6265         return status;
6266 }
6267
6268 /****************************************************************************
6269 ****************************************************************************/
6270
6271 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6272 {
6273         POLICY_HND *handle = &q_u->handle;
6274 /*      uint32 level = q_u->level; - notused. */
6275         FORM *form = &q_u->form;
6276         nt_forms_struct tmpForm;
6277
6278         int count=0;
6279         nt_forms_struct *list=NULL;
6280         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6281
6282         DEBUG(5,("spoolss_addform\n"));
6283
6284         if (!Printer) {
6285                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6286                 return WERR_BADFID;
6287         }
6288
6289         /* 
6290          * FIXME!!  Feels like there should be an access check here, but haven't
6291          * had time to verify.  --jerry
6292          */
6293
6294         /* can't add if builtin */
6295         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6296                 return WERR_INVALID_PARAM;
6297         }
6298
6299         count=get_ntforms(&list);
6300         if(!add_a_form(&list, form, &count))
6301                 return WERR_NOMEM;
6302         write_ntforms(&list, count);
6303
6304         SAFE_FREE(list);
6305
6306         return WERR_OK;
6307 }
6308
6309 /****************************************************************************
6310 ****************************************************************************/
6311
6312 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6313 {
6314         POLICY_HND *handle = &q_u->handle;
6315         UNISTR2 *form_name = &q_u->name;
6316         nt_forms_struct tmpForm;
6317         int count=0;
6318         WERROR ret = WERR_OK;
6319         nt_forms_struct *list=NULL;
6320         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6321
6322         DEBUG(5,("spoolss_deleteform\n"));
6323
6324         if (!Printer) {
6325                 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6326                 return WERR_BADFID;
6327         }
6328
6329         /* can't delete if builtin */
6330         if (get_a_builtin_ntform(form_name,&tmpForm)) {
6331                 return WERR_INVALID_PARAM;
6332         }
6333
6334         count = get_ntforms(&list);
6335         if(!delete_a_form(&list, form_name, &count, &ret))
6336                 return WERR_INVALID_PARAM;
6337
6338         SAFE_FREE(list);
6339
6340         return ret;
6341 }
6342
6343 /****************************************************************************
6344 ****************************************************************************/
6345
6346 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6347 {
6348         POLICY_HND *handle = &q_u->handle;
6349 /*      UNISTR2 *uni_name = &q_u->name; - notused. */
6350 /*      uint32 level = q_u->level; - notused. */
6351         FORM *form = &q_u->form;
6352         nt_forms_struct tmpForm;
6353
6354         int count=0;
6355         nt_forms_struct *list=NULL;
6356         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6357
6358         DEBUG(5,("spoolss_setform\n"));
6359
6360         if (!Printer) {
6361                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6362                 return WERR_BADFID;
6363         }
6364         /* can't set if builtin */
6365         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6366                 return WERR_INVALID_PARAM;
6367         }
6368
6369         count=get_ntforms(&list);
6370         update_a_form(&list, form, count);
6371         write_ntforms(&list, count);
6372
6373         SAFE_FREE(list);
6374
6375         return WERR_OK;
6376 }
6377
6378 /****************************************************************************
6379  enumprintprocessors level 1.
6380 ****************************************************************************/
6381 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6382 {
6383         PRINTPROCESSOR_1 *info_1=NULL;
6384         
6385         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6386                 return WERR_NOMEM;
6387
6388         (*returned) = 0x1;
6389         
6390         init_unistr(&info_1->name, "winprint");
6391
6392         *needed += spoolss_size_printprocessor_info_1(info_1);
6393
6394         if (!alloc_buffer_size(buffer, *needed))
6395                 return WERR_INSUFFICIENT_BUFFER;
6396
6397         smb_io_printprocessor_info_1("", buffer, info_1, 0);
6398
6399         SAFE_FREE(info_1);
6400
6401         if (*needed > offered) {
6402                 *returned=0;
6403                 return WERR_INSUFFICIENT_BUFFER;
6404         }
6405
6406         return WERR_OK;
6407 }
6408
6409 /****************************************************************************
6410 ****************************************************************************/
6411
6412 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6413 {
6414 /*      UNISTR2 *name = &q_u->name; - notused. */
6415 /*      UNISTR2 *environment = &q_u->environment; - notused. */
6416         uint32 level = q_u->level;
6417     NEW_BUFFER *buffer = NULL;
6418         uint32 offered = q_u->offered;
6419     uint32 *needed = &r_u->needed;
6420         uint32 *returned = &r_u->returned;
6421
6422         /* that's an [in out] buffer */
6423         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6424         buffer = r_u->buffer;
6425
6426         DEBUG(5,("spoolss_enumprintprocessors\n"));
6427
6428         /*
6429          * Enumerate the print processors ...
6430          *
6431          * Just reply with "winprint", to keep NT happy
6432          * and I can use my nice printer checker.
6433          */
6434         
6435         *returned=0;
6436         *needed=0;
6437         
6438         switch (level) {
6439         case 1:
6440                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6441         default:
6442                 return WERR_UNKNOWN_LEVEL;
6443         }
6444 }
6445
6446 /****************************************************************************
6447  enumprintprocdatatypes level 1.
6448 ****************************************************************************/
6449 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6450 {
6451         PRINTPROCDATATYPE_1 *info_1=NULL;
6452         
6453         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6454                 return WERR_NOMEM;
6455
6456         (*returned) = 0x1;
6457         
6458         init_unistr(&info_1->name, "RAW");
6459
6460         *needed += spoolss_size_printprocdatatype_info_1(info_1);
6461
6462         if (!alloc_buffer_size(buffer, *needed))
6463                 return WERR_INSUFFICIENT_BUFFER;
6464
6465         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6466
6467         SAFE_FREE(info_1);
6468
6469         if (*needed > offered) {
6470                 *returned=0;
6471                 return WERR_INSUFFICIENT_BUFFER;
6472         }
6473
6474         return WERR_OK;
6475 }
6476
6477 /****************************************************************************
6478 ****************************************************************************/
6479
6480 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6481 {
6482 /*      UNISTR2 *name = &q_u->name; - notused. */
6483 /*      UNISTR2 *processor = &q_u->processor; - notused. */
6484         uint32 level = q_u->level;
6485         NEW_BUFFER *buffer = NULL;
6486         uint32 offered = q_u->offered;
6487         uint32 *needed = &r_u->needed;
6488         uint32 *returned = &r_u->returned;
6489
6490         /* that's an [in out] buffer */
6491         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6492         buffer = r_u->buffer;
6493
6494         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6495         
6496         *returned=0;
6497         *needed=0;
6498         
6499         switch (level) {
6500         case 1:
6501                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6502         default:
6503                 return WERR_UNKNOWN_LEVEL;
6504         }
6505 }
6506
6507 /****************************************************************************
6508  enumprintmonitors level 1.
6509 ****************************************************************************/
6510
6511 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6512 {
6513         PRINTMONITOR_1 *info_1=NULL;
6514         
6515         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6516                 return WERR_NOMEM;
6517
6518         (*returned) = 0x1;
6519         
6520         init_unistr(&info_1->name, "Local Port");
6521
6522         *needed += spoolss_size_printmonitor_info_1(info_1);
6523
6524         if (!alloc_buffer_size(buffer, *needed))
6525                 return WERR_INSUFFICIENT_BUFFER;
6526
6527         smb_io_printmonitor_info_1("", buffer, info_1, 0);
6528
6529         SAFE_FREE(info_1);
6530
6531         if (*needed > offered) {
6532                 *returned=0;
6533                 return WERR_INSUFFICIENT_BUFFER;
6534         }
6535
6536         return WERR_OK;
6537 }
6538
6539 /****************************************************************************
6540  enumprintmonitors level 2.
6541 ****************************************************************************/
6542 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6543 {
6544         PRINTMONITOR_2 *info_2=NULL;
6545         
6546         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6547                 return WERR_NOMEM;
6548
6549         (*returned) = 0x1;
6550         
6551         init_unistr(&info_2->name, "Local Port");
6552         init_unistr(&info_2->environment, "Windows NT X86");
6553         init_unistr(&info_2->dll_name, "localmon.dll");
6554
6555         *needed += spoolss_size_printmonitor_info_2(info_2);
6556
6557         if (!alloc_buffer_size(buffer, *needed))
6558                 return WERR_INSUFFICIENT_BUFFER;
6559
6560         smb_io_printmonitor_info_2("", buffer, info_2, 0);
6561
6562         SAFE_FREE(info_2);
6563
6564         if (*needed > offered) {
6565                 *returned=0;
6566                 return WERR_INSUFFICIENT_BUFFER;
6567         }
6568
6569         return WERR_OK;
6570 }
6571
6572 /****************************************************************************
6573 ****************************************************************************/
6574
6575 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6576 {
6577 /*      UNISTR2 *name = &q_u->name; - notused. */
6578         uint32 level = q_u->level;
6579     NEW_BUFFER *buffer = NULL;
6580         uint32 offered = q_u->offered;
6581     uint32 *needed = &r_u->needed;
6582         uint32 *returned = &r_u->returned;
6583
6584         /* that's an [in out] buffer */
6585         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6586         buffer = r_u->buffer;
6587
6588         DEBUG(5,("spoolss_enumprintmonitors\n"));
6589
6590         /*
6591          * Enumerate the print monitors ...
6592          *
6593          * Just reply with "Local Port", to keep NT happy
6594          * and I can use my nice printer checker.
6595          */
6596         
6597         *returned=0;
6598         *needed=0;
6599         
6600         switch (level) {
6601         case 1:
6602                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6603         case 2:
6604                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6605         default:
6606                 return WERR_UNKNOWN_LEVEL;
6607         }
6608 }
6609
6610 /****************************************************************************
6611 ****************************************************************************/
6612 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6613 {
6614         int i=0;
6615         BOOL found=False;
6616         JOB_INFO_1 *info_1=NULL;
6617
6618         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6619
6620         if (info_1 == NULL) {
6621                 SAFE_FREE(queue);
6622                 return WERR_NOMEM;
6623         }
6624                 
6625         for (i=0; i<count && found==False; i++) {
6626                 if (queue[i].job==(int)jobid)
6627                         found=True;
6628         }
6629         
6630         if (found==False) {
6631                 SAFE_FREE(queue);
6632                 SAFE_FREE(info_1);
6633                 /* NT treats not found as bad param... yet another bad choice */
6634                 return WERR_INVALID_PARAM;
6635         }
6636         
6637         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6638         
6639         SAFE_FREE(queue);
6640         
6641         *needed += spoolss_size_job_info_1(info_1);
6642
6643         if (!alloc_buffer_size(buffer, *needed)) {
6644                 SAFE_FREE(info_1);
6645                 return WERR_INSUFFICIENT_BUFFER;
6646         }
6647
6648         smb_io_job_info_1("", buffer, info_1, 0);
6649
6650         SAFE_FREE(info_1);
6651
6652         if (*needed > offered)
6653                 return WERR_INSUFFICIENT_BUFFER;
6654
6655         return WERR_OK;
6656 }
6657
6658
6659 /****************************************************************************
6660 ****************************************************************************/
6661 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6662 {
6663         int i=0;
6664         BOOL found=False;
6665         JOB_INFO_2 *info_2;
6666         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6667         WERROR ret;
6668
6669         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6670
6671         ZERO_STRUCTP(info_2);
6672
6673         if (info_2 == NULL) {
6674                 SAFE_FREE(queue);
6675                 return WERR_NOMEM;
6676         }
6677
6678         for (i=0; i<count && found==False; i++) {
6679                 if (queue[i].job==(int)jobid)
6680                         found=True;
6681         }
6682         
6683         if (found==False) {
6684                 SAFE_FREE(queue);
6685                 SAFE_FREE(info_2);
6686                 /* NT treats not found as bad param... yet another bad choice */
6687                 return WERR_INVALID_PARAM;
6688         }
6689         
6690         ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6691         if (!W_ERROR_IS_OK(ret)) {
6692                 SAFE_FREE(queue);
6693                 return ret;
6694         }
6695
6696         fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6697         
6698         free_a_printer(&ntprinter, 2);
6699         SAFE_FREE(queue);
6700         
6701         *needed += spoolss_size_job_info_2(info_2);
6702
6703         if (!alloc_buffer_size(buffer, *needed)) {
6704                 SAFE_FREE(info_2);
6705                 return WERR_INSUFFICIENT_BUFFER;
6706         }
6707
6708         smb_io_job_info_2("", buffer, info_2, 0);
6709
6710         free_job_info_2(info_2);
6711         SAFE_FREE(info_2);
6712
6713         if (*needed > offered)
6714                 return WERR_INSUFFICIENT_BUFFER;
6715
6716         return WERR_OK;
6717 }
6718
6719 /****************************************************************************
6720 ****************************************************************************/
6721
6722 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6723 {
6724         POLICY_HND *handle = &q_u->handle;
6725         uint32 jobid = q_u->jobid;
6726         uint32 level = q_u->level;
6727         NEW_BUFFER *buffer = NULL;
6728         uint32 offered = q_u->offered;
6729         uint32 *needed = &r_u->needed;
6730
6731         int snum;
6732         int count;
6733         print_queue_struct *queue=NULL;
6734         print_status_struct prt_status;
6735
6736         /* that's an [in out] buffer */
6737         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6738         buffer = r_u->buffer;
6739
6740         DEBUG(5,("spoolss_getjob\n"));
6741         
6742         *needed=0;
6743         
6744         if (!get_printer_snum(p, handle, &snum))
6745                 return WERR_BADFID;
6746         
6747         count = print_queue_status(snum, &queue, &prt_status);
6748         
6749         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6750                      count, prt_status.status, prt_status.message));
6751                 
6752         switch (level) {
6753         case 1:
6754                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6755         case 2:
6756                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6757         default:
6758                 SAFE_FREE(queue);
6759                 return WERR_UNKNOWN_LEVEL;
6760         }
6761 }
6762
6763 /********************************************************************
6764  * spoolss_getprinterdataex
6765  ********************************************************************/
6766
6767 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6768 {
6769         POLICY_HND      *handle = &q_u->handle;
6770         uint32          in_size = q_u->size;
6771         uint32          *type = &r_u->type;
6772         uint32          *out_size = &r_u->size;
6773         uint8           **data = &r_u->data;
6774         uint32          *needed = &r_u->needed;
6775
6776         fstring         key, value;
6777         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6778         BOOL            found = False;
6779
6780         DEBUG(4,("_spoolss_getprinterdataex\n"));
6781
6782         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6783         unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6784
6785         /* in case of problem, return some default values */
6786         *needed=0;
6787         *type=0;
6788         *out_size=0;
6789
6790                 
6791         if (!Printer) {
6792                 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6793                         return WERR_NOMEM;
6794                 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6795                 return WERR_BADFID;
6796         }
6797
6798                 
6799         /* Is the handle to a printer or to the server? */
6800
6801         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6802         {
6803                 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6804                 return WERR_INVALID_PARAM;
6805         }
6806         else
6807         {
6808                 /* 
6809                  * From MSDN documentation of GetPrinterDataEx: pass request
6810                  * to GetPrinterData if key is "PrinterDriverData". This is 
6811                  * the only key we really support. Other keys to implement:
6812                  * (a) DsDriver
6813                  * (b) DsSpooler
6814                  * (c) PnPData
6815                  */
6816            
6817                 if (strcmp(key, "PrinterDriverData") != 0)
6818                         return WERR_INVALID_PARAM;
6819
6820                 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6821                 found = getprinterdata_printer(p, p->mem_ctx, handle, value, 
6822                         type, data, needed, in_size);
6823                 
6824         }
6825          
6826         if (!found) {
6827                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6828                 
6829                 /* reply this param doesn't exist */
6830                 if (*out_size) {
6831                         if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6832                                 return WERR_NOMEM;
6833                 } else {
6834                         *data = NULL;
6835                 }
6836
6837                 return WERR_INVALID_PARAM;
6838         }
6839         
6840         if (*needed > *out_size)
6841                 return WERR_MORE_DATA;
6842         else
6843                 return WERR_OK;
6844 }
6845
6846 /********************************************************************
6847  * spoolss_setprinterdata
6848  ********************************************************************/
6849
6850 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6851 {
6852         SPOOL_Q_SETPRINTERDATA q_u_local;
6853         SPOOL_R_SETPRINTERDATA r_u_local;
6854         fstring key;
6855
6856         DEBUG(4,("_spoolss_setprinterdataex\n"));
6857
6858         /* From MSDN documentation of SetPrinterDataEx: pass request to
6859            SetPrinterData if key is "PrinterDriverData" */
6860
6861         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6862
6863         if (strcmp(key, "PrinterDriverData") == 0)
6864                 return WERR_INVALID_PARAM;
6865                 
6866         ZERO_STRUCT(q_u_local); 
6867         ZERO_STRUCT(r_u_local); 
6868         
6869         /* make a copy to call _spoolss_setprinterdata() */
6870
6871         memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
6872         copy_unistr2(&q_u_local.value, &q_u->value);
6873         q_u_local.type = q_u->type;
6874         q_u_local.max_len = q_u->max_len;
6875         q_u_local.data = q_u->data;
6876         q_u_local.real_len = q_u->real_len;
6877         q_u_local.numeric_data = q_u->numeric_data;
6878                 
6879         return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
6880 }
6881
6882 /********************************************************************
6883  * spoolss_enumprinterkey
6884  ********************************************************************/
6885
6886 /* constants for EnumPrinterKey() */
6887 #define ENUMERATED_KEY_SIZE     19
6888
6889 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
6890 {
6891         fstring key;
6892         uint16  enumkeys[ENUMERATED_KEY_SIZE+1];
6893         char*   ptr = NULL;
6894         int     i;
6895         char    *PrinterKey = "PrinterDriverData";
6896
6897         DEBUG(4,("_spoolss_enumprinterkey\n"));
6898
6899         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6900
6901         /* 
6902          * we only support enumating all keys (key == "")
6903          * Of course, the only key we support is the "PrinterDriverData" 
6904          * key
6905          */     
6906         if (strlen(key) == 0)
6907         {
6908                 r_u->needed = ENUMERATED_KEY_SIZE *2;
6909                 if (q_u->size < r_u->needed)
6910                         return WERR_MORE_DATA;
6911         
6912                 ptr = PrinterKey;
6913                 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
6914                 {
6915                         enumkeys[i] = (uint16)(*ptr);
6916                         ptr++;
6917                 }
6918
6919                 /* tag of with 2 '\0's */
6920                 enumkeys[i++] = '\0';
6921                 enumkeys[i] = '\0';
6922         
6923                 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
6924                         return WERR_BADFILE;
6925                         
6926                 return WERR_OK;
6927         }
6928         
6929         /* The "PrinterDriverData" key should have no subkeys */
6930         if (strcmp(key, PrinterKey) == 0)
6931         {
6932                 r_u-> needed = 2;
6933                 if (q_u->size < r_u->needed)
6934                         return WERR_MORE_DATA;
6935                 enumkeys[0] = 0x0;
6936                 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
6937                         return WERR_BADFILE;
6938                         
6939                 return WERR_OK;
6940         }
6941         
6942
6943         /* The return value for an unknown key is documented in MSDN
6944            EnumPrinterKey description */
6945         return WERR_BADFILE;
6946 }
6947
6948 /********************************************************************
6949  * spoolss_enumprinterdataex
6950  ********************************************************************/
6951
6952 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
6953 {
6954         POLICY_HND      *handle = &q_u->handle; 
6955         uint32          in_size = q_u->size;
6956         uint32          num_entries, 
6957                         needed;
6958         NT_PRINTER_INFO_LEVEL   *printer = NULL;
6959         PRINTER_ENUM_VALUES     *enum_values = NULL;
6960         fstring         key, value;
6961         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6962         int             snum;
6963         uint32          param_index, 
6964                         data_len,
6965                         type;
6966         WERROR          result;
6967         uint8           *data=NULL;
6968         
6969
6970         DEBUG(4,("_spoolss_enumprinterdataex\n"));
6971
6972         if (!Printer) {
6973                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6974                 return WERR_BADFID;
6975         }
6976
6977                 
6978         /* 
6979          * The only key we support is "PrinterDriverData". This should return 
6980          > an array of all the key/value pairs returned by EnumPrinterDataSee 
6981          * _spoolss_getprinterdataex() for details    --jerry
6982          */
6983    
6984         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6985         if (strcmp(key, "PrinterDriverData") != 0)
6986         {
6987                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
6988                 return WERR_INVALID_PARAM;
6989         }
6990
6991
6992         if (!get_printer_snum(p,handle, &snum))
6993                 return WERR_BADFID;
6994         
6995         ZERO_STRUCT(printer);
6996         result = get_a_printer(&printer, 2, lp_servicename(snum));
6997         if (!W_ERROR_IS_OK(result))
6998                 return result;
6999
7000         
7001         /* 
7002          * loop through all params and build the array to pass 
7003          * back to the  client 
7004          */
7005         result = WERR_OK;
7006         param_index             = 0;
7007         needed                  = 0;
7008         num_entries             = 0;
7009         
7010         while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) 
7011         {
7012                 PRINTER_ENUM_VALUES     *ptr;
7013                 uint32                  add_len = 0;
7014
7015                 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7016
7017                 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7018                 {
7019                         DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7020                         result = WERR_NOMEM;
7021                         goto done;
7022                 }
7023                 enum_values = ptr;
7024
7025                 /* copy the data */
7026                 init_unistr(&enum_values[num_entries].valuename, value);
7027                 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7028                 enum_values[num_entries].type      = type;
7029                 
7030                 /* 
7031                  * NULL terminate REG_SZ
7032                  * FIXME!!!  We should not be correctly problems in the way
7033                  * we store PrinterData here.  Need to investogate 
7034                  * SetPrinterData[Ex]   --jerry
7035                  */
7036                 
7037                 if (type == REG_SZ) {
7038                         /* fix alignment if the string was stored 
7039                            in a bizarre fashion */
7040                         if ((data_len % 2) == 0)
7041                                 add_len = 2;
7042                         else
7043                                 add_len = data_len % 2;
7044                 }
7045                 
7046                 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7047                         DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7048                         result = WERR_NOMEM;
7049                         goto done;
7050                 }
7051                 memcpy(enum_values[num_entries].data, data, data_len);
7052                 enum_values[num_entries].data_len = data_len + add_len;
7053
7054                 /* keep track of the size of the array in bytes */
7055                 
7056                 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7057                 
7058                 num_entries++;
7059                 param_index++;
7060         }
7061         
7062         r_u->needed             = needed;
7063         r_u->returned           = num_entries;
7064
7065         if (needed > in_size) {
7066                 result = WERR_MORE_DATA;
7067                 goto done;
7068         }
7069                 
7070         /* copy data into the reply */
7071         
7072         r_u->ctr.size           = r_u->needed;
7073         r_u->ctr.size_of_array  = r_u->returned;
7074         r_u->ctr.values         = enum_values;
7075         
7076         
7077                 
7078 done:   
7079         free_a_printer(&printer, 2);
7080
7081         return result;
7082 }
7083
7084 /****************************************************************************
7085 ****************************************************************************/
7086
7087 /* Disabled because it doesn't fix the bug I am looking at but it would be
7088    a shame to throw away the code. -tpot */
7089
7090 #if 0
7091
7092 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7093 {
7094         init_unistr(&info->name, name);
7095 }
7096
7097 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
7098                                                  UNISTR2 *environment, 
7099                                                  NEW_BUFFER *buffer, 
7100                                                  uint32 offered, 
7101                                                  uint32 *needed)
7102 {
7103         pstring path;
7104         pstring long_archi;
7105         pstring short_archi;
7106         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7107
7108         unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7109
7110         if (get_short_archi(short_archi, long_archi)==False)
7111                 return WERR_INVALID_ENVIRONMENT;
7112
7113         if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7114                 return WERR_NOMEM;
7115
7116         /* Not sure what to return here - are UNC names valid here?.
7117            Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7118            which is pretty bogus for a RPC. */
7119
7120         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7121
7122         DEBUG(4,("print processor directory: [%s]\n", path));
7123
7124         fill_printprocessordirectory_1(info, path);
7125         
7126         *needed += spoolss_size_printprocessordirectory_info_1(info);
7127
7128         if (!alloc_buffer_size(buffer, *needed)) {
7129                 safe_free(info);
7130                 return WERR_INSUFFICIENT_BUFFER;
7131         }
7132
7133         smb_io_printprocessordirectory_1("", buffer, info, 0);
7134
7135         safe_free(info);
7136         
7137         if (*needed > offered)
7138                 return WERR_INSUFFICIENT_BUFFER;
7139         else
7140                 return WERR_OK;
7141 }
7142
7143 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7144 {
7145         uint32 level = q_u->level;
7146         NEW_BUFFER *buffer = NULL;
7147         uint32 offered = q_u->offered;
7148         uint32 *needed = &r_u->needed;
7149
7150         /* that's an [in out] buffer */
7151         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7152         buffer = r_u->buffer;
7153
7154         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7155         
7156         *needed=0;
7157
7158         switch(level) {
7159         case 1:
7160                 return getprintprocessordirectory_level_1
7161                   (&q_u->name, &q_u->environment, buffer, offered, needed);
7162         default:
7163                 return WERR_UNKNOWN_LEVEL;
7164         }
7165
7166         return WERR_ACCESS_DENIED;
7167 }
7168
7169 #endif