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