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