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