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