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