merge from APP_HEAD to use GMT in job submission notification
[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, gmtime((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         /* this should not be a failure condition if the devmode is NULL */
6021         
6022         devmode = construct_dev_mode(snum);
6023
6024         for (i=0; i<*returned; i++)
6025                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6026                                 devmode);
6027
6028         free_a_printer(&ntprinter, 2);
6029         SAFE_FREE(queue);
6030
6031         /* check the required size. */  
6032         for (i=0; i<*returned; i++)
6033                 (*needed) += spoolss_size_job_info_2(&info[i]);
6034
6035         if (*needed > offered) {
6036                 *returned=0;
6037                 result = WERR_INSUFFICIENT_BUFFER;
6038                 goto done;
6039         }
6040
6041         if (!alloc_buffer_size(buffer, *needed)) {
6042                 SAFE_FREE(info);
6043                 result = WERR_INSUFFICIENT_BUFFER;
6044                 goto done;
6045         }
6046
6047         /* fill the buffer with the structures */
6048         for (i=0; i<*returned; i++)
6049                 smb_io_job_info_2("", buffer, &info[i], 0);     
6050
6051         result = WERR_OK;
6052
6053  done:
6054         free_a_printer(&ntprinter, 2);
6055         free_devmode(devmode);
6056         SAFE_FREE(queue);
6057         SAFE_FREE(info);
6058
6059         return result;
6060
6061 }
6062
6063 /****************************************************************************
6064  Enumjobs.
6065 ****************************************************************************/
6066
6067 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6068 {       
6069         POLICY_HND *handle = &q_u->handle;
6070         uint32 level = q_u->level;
6071         NEW_BUFFER *buffer = NULL;
6072         uint32 offered = q_u->offered;
6073         uint32 *needed = &r_u->needed;
6074         uint32 *returned = &r_u->returned;
6075
6076         int snum;
6077         print_status_struct prt_status;
6078         print_queue_struct *queue=NULL;
6079
6080         /* that's an [in out] buffer */
6081         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6082         buffer = r_u->buffer;
6083
6084         DEBUG(4,("_spoolss_enumjobs\n"));
6085
6086         *needed=0;
6087         *returned=0;
6088
6089         if (!get_printer_snum(p, handle, &snum))
6090                 return WERR_BADFID;
6091
6092         *returned = print_queue_status(snum, &queue, &prt_status);
6093         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6094
6095         if (*returned == 0) {
6096                 SAFE_FREE(queue);
6097                 return WERR_OK;
6098         }
6099
6100         switch (level) {
6101         case 1:
6102                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6103         case 2:
6104                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6105         default:
6106                 SAFE_FREE(queue);
6107                 *returned=0;
6108                 return WERR_UNKNOWN_LEVEL;
6109         }
6110 }
6111
6112 /****************************************************************************
6113 ****************************************************************************/
6114
6115 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6116 {
6117         return WERR_OK;
6118 }
6119
6120 /****************************************************************************
6121 ****************************************************************************/
6122
6123 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6124 {
6125         POLICY_HND *handle = &q_u->handle;
6126         uint32 jobid = q_u->jobid;
6127         uint32 command = q_u->command;
6128
6129         struct current_user user;
6130         int snum;
6131         WERROR errcode = WERR_BADFUNC;
6132                 
6133         if (!get_printer_snum(p, handle, &snum)) {
6134                 return WERR_BADFID;
6135         }
6136
6137         if (!print_job_exists(snum, jobid)) {
6138                 return WERR_INVALID_PRINTER_NAME;
6139         }
6140
6141         get_current_user(&user, p);     
6142
6143         switch (command) {
6144         case JOB_CONTROL_CANCEL:
6145         case JOB_CONTROL_DELETE:
6146                 if (print_job_delete(&user, snum, jobid, &errcode)) {
6147                         errcode = WERR_OK;
6148                 }
6149                 break;
6150         case JOB_CONTROL_PAUSE:
6151                 if (print_job_pause(&user, snum, jobid, &errcode)) {
6152                         errcode = WERR_OK;
6153                 }               
6154                 break;
6155         case JOB_CONTROL_RESTART:
6156         case JOB_CONTROL_RESUME:
6157                 if (print_job_resume(&user, snum, jobid, &errcode)) {
6158                         errcode = WERR_OK;
6159                 }
6160                 break;
6161         default:
6162                 return WERR_UNKNOWN_LEVEL;
6163         }
6164
6165         return errcode;
6166 }
6167
6168 /****************************************************************************
6169  Enumerates all printer drivers at level 1.
6170 ****************************************************************************/
6171
6172 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6173 {
6174         int i;
6175         int ndrivers;
6176         uint32 version;
6177         fstring *list = NULL;
6178
6179         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6180         DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6181
6182         *returned=0;
6183
6184         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6185                 list=NULL;
6186                 ndrivers=get_ntdrivers(&list, architecture, version);
6187                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6188
6189                 if(ndrivers == -1)
6190                         return WERR_NOMEM;
6191
6192                 if(ndrivers != 0) {
6193                         if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6194                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6195                                 SAFE_FREE(driver_info_1);
6196                                 SAFE_FREE(list);
6197                                 return WERR_NOMEM;
6198                         }
6199                         else driver_info_1 = tdi1;
6200                 }
6201
6202                 for (i=0; i<ndrivers; i++) {
6203                         WERROR status;
6204                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6205                         ZERO_STRUCT(driver);
6206                         status = get_a_printer_driver(&driver, 3, list[i], 
6207                                                       architecture, version);
6208                         if (!W_ERROR_IS_OK(status)) {
6209                                 SAFE_FREE(list);
6210                                 return status;
6211                         }
6212                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
6213                         free_a_printer_driver(driver, 3);
6214                 }       
6215
6216                 *returned+=ndrivers;
6217                 SAFE_FREE(list);
6218         }
6219         
6220         /* check the required size. */
6221         for (i=0; i<*returned; i++) {
6222                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6223                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6224         }
6225
6226         if (!alloc_buffer_size(buffer, *needed)) {
6227                 SAFE_FREE(driver_info_1);
6228                 return WERR_INSUFFICIENT_BUFFER;
6229         }
6230
6231         /* fill the buffer with the driver structures */
6232         for (i=0; i<*returned; i++) {
6233                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6234                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6235         }
6236
6237         SAFE_FREE(driver_info_1);
6238
6239         if (*needed > offered) {
6240                 *returned=0;
6241                 return WERR_INSUFFICIENT_BUFFER;
6242         }
6243
6244         return WERR_OK;
6245 }
6246
6247 /****************************************************************************
6248  Enumerates all printer drivers at level 2.
6249 ****************************************************************************/
6250
6251 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6252 {
6253         int i;
6254         int ndrivers;
6255         uint32 version;
6256         fstring *list = NULL;
6257
6258         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6259         DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6260
6261         *returned=0;
6262
6263         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6264                 list=NULL;
6265                 ndrivers=get_ntdrivers(&list, architecture, version);
6266                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6267
6268                 if(ndrivers == -1)
6269                         return WERR_NOMEM;
6270
6271                 if(ndrivers != 0) {
6272                         if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6273                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6274                                 SAFE_FREE(driver_info_2);
6275                                 SAFE_FREE(list);
6276                                 return WERR_NOMEM;
6277                         }
6278                         else driver_info_2 = tdi2;
6279                 }
6280                 
6281                 for (i=0; i<ndrivers; i++) {
6282                         WERROR status;
6283
6284                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6285                         ZERO_STRUCT(driver);
6286                         status = get_a_printer_driver(&driver, 3, list[i], 
6287                                                       architecture, version);
6288                         if (!W_ERROR_IS_OK(status)) {
6289                                 SAFE_FREE(list);
6290                                 return status;
6291                         }
6292                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
6293                         free_a_printer_driver(driver, 3);
6294                 }       
6295
6296                 *returned+=ndrivers;
6297                 SAFE_FREE(list);
6298         }
6299         
6300         /* check the required size. */
6301         for (i=0; i<*returned; i++) {
6302                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6303                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6304         }
6305
6306         if (!alloc_buffer_size(buffer, *needed)) {
6307                 SAFE_FREE(driver_info_2);
6308                 return WERR_INSUFFICIENT_BUFFER;
6309         }
6310
6311         /* fill the buffer with the form structures */
6312         for (i=0; i<*returned; i++) {
6313                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6314                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6315         }
6316
6317         SAFE_FREE(driver_info_2);
6318
6319         if (*needed > offered) {
6320                 *returned=0;
6321                 return WERR_INSUFFICIENT_BUFFER;
6322         }
6323
6324         return WERR_OK;
6325 }
6326
6327 /****************************************************************************
6328  Enumerates all printer drivers at level 3.
6329 ****************************************************************************/
6330
6331 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6332 {
6333         int i;
6334         int ndrivers;
6335         uint32 version;
6336         fstring *list = NULL;
6337
6338         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6339         DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6340
6341         *returned=0;
6342
6343         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6344                 list=NULL;
6345                 ndrivers=get_ntdrivers(&list, architecture, version);
6346                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6347
6348                 if(ndrivers == -1)
6349                         return WERR_NOMEM;
6350
6351                 if(ndrivers != 0) {
6352                         if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6353                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6354                                 SAFE_FREE(driver_info_3);
6355                                 SAFE_FREE(list);
6356                                 return WERR_NOMEM;
6357                         }
6358                         else driver_info_3 = tdi3;
6359                 }
6360
6361                 for (i=0; i<ndrivers; i++) {
6362                         WERROR status;
6363
6364                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6365                         ZERO_STRUCT(driver);
6366                         status = get_a_printer_driver(&driver, 3, list[i], 
6367                                                       architecture, version);
6368                         if (!W_ERROR_IS_OK(status)) {
6369                                 SAFE_FREE(list);
6370                                 return status;
6371                         }
6372                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
6373                         free_a_printer_driver(driver, 3);
6374                 }       
6375
6376                 *returned+=ndrivers;
6377                 SAFE_FREE(list);
6378         }
6379
6380         /* check the required size. */
6381         for (i=0; i<*returned; i++) {
6382                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6383                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6384         }
6385
6386         if (!alloc_buffer_size(buffer, *needed)) {
6387                 SAFE_FREE(driver_info_3);
6388                 return WERR_INSUFFICIENT_BUFFER;
6389         }
6390         
6391         /* fill the buffer with the driver structures */
6392         for (i=0; i<*returned; i++) {
6393                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6394                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6395         }
6396
6397         for (i=0; i<*returned; i++)
6398                 SAFE_FREE(driver_info_3[i].dependentfiles);
6399         
6400         SAFE_FREE(driver_info_3);
6401         
6402         if (*needed > offered) {
6403                 *returned=0;
6404                 return WERR_INSUFFICIENT_BUFFER;
6405         }
6406
6407         return WERR_OK;
6408 }
6409
6410 /****************************************************************************
6411  Enumerates all printer drivers.
6412 ****************************************************************************/
6413
6414 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6415 {
6416         UNISTR2 *environment = &q_u->environment;
6417         uint32 level = q_u->level;
6418         NEW_BUFFER *buffer = NULL;
6419         uint32 offered = q_u->offered;
6420         uint32 *needed = &r_u->needed;
6421         uint32 *returned = &r_u->returned;
6422
6423         fstring *list = NULL;
6424         fstring servername;
6425         fstring architecture;
6426
6427         /* that's an [in out] buffer */
6428         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6429         buffer = r_u->buffer;
6430
6431         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6432         fstrcpy(servername, get_called_name());
6433         *needed=0;
6434         *returned=0;
6435
6436         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6437
6438         switch (level) {
6439         case 1:
6440                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6441         case 2:
6442                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6443         case 3:
6444                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6445         default:
6446                 *returned=0;
6447                 SAFE_FREE(list);
6448                 return WERR_UNKNOWN_LEVEL;
6449         }
6450 }
6451
6452 /****************************************************************************
6453 ****************************************************************************/
6454
6455 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6456 {
6457         form->flag=list->flag;
6458         init_unistr(&form->name, list->name);
6459         form->width=list->width;
6460         form->length=list->length;
6461         form->left=list->left;
6462         form->top=list->top;
6463         form->right=list->right;
6464         form->bottom=list->bottom;      
6465 }
6466         
6467 /****************************************************************************
6468 ****************************************************************************/
6469
6470 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6471 {
6472         uint32 level = q_u->level;
6473         NEW_BUFFER *buffer = NULL;
6474         uint32 offered = q_u->offered;
6475         uint32 *needed = &r_u->needed;
6476         uint32 *numofforms = &r_u->numofforms;
6477         uint32 numbuiltinforms;
6478
6479         nt_forms_struct *list=NULL;
6480         nt_forms_struct *builtinlist=NULL;
6481         FORM_1 *forms_1;
6482         int buffer_size=0;
6483         int i;
6484
6485         /* that's an [in out] buffer */
6486         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6487         buffer = r_u->buffer;
6488
6489         DEBUG(4,("_spoolss_enumforms\n"));
6490         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6491         DEBUGADD(5,("Info level [%d]\n",          level));
6492
6493         numbuiltinforms = get_builtin_ntforms(&builtinlist);
6494         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
6495         *numofforms = get_ntforms(&list);
6496         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
6497         *numofforms += numbuiltinforms;
6498
6499         if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6500
6501         switch (level) {
6502         case 1:
6503                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6504                         *numofforms=0;
6505                         return WERR_NOMEM;
6506                 }
6507
6508                 /* construct the list of form structures */
6509                 for (i=0; i<numbuiltinforms; i++) {
6510                         DEBUGADD(6,("Filling form number [%d]\n",i));
6511                         fill_form_1(&forms_1[i], &builtinlist[i]);
6512                 }
6513                 
6514                 SAFE_FREE(builtinlist);
6515
6516                 for (; i<*numofforms; i++) {
6517                         DEBUGADD(6,("Filling form number [%d]\n",i));
6518                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6519                 }
6520                 
6521                 SAFE_FREE(list);
6522
6523                 /* check the required size. */
6524                 for (i=0; i<numbuiltinforms; i++) {
6525                         DEBUGADD(6,("adding form [%d]'s size\n",i));
6526                         buffer_size += spoolss_size_form_1(&forms_1[i]);
6527                 }
6528                 for (; i<*numofforms; i++) {
6529                         DEBUGADD(6,("adding form [%d]'s size\n",i));
6530                         buffer_size += spoolss_size_form_1(&forms_1[i]);
6531                 }
6532
6533                 *needed=buffer_size;            
6534                 
6535                 if (!alloc_buffer_size(buffer, buffer_size)){
6536                         SAFE_FREE(forms_1);
6537                         return WERR_INSUFFICIENT_BUFFER;
6538                 }
6539
6540                 /* fill the buffer with the form structures */
6541                 for (i=0; i<numbuiltinforms; i++) {
6542                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
6543                         smb_io_form_1("", buffer, &forms_1[i], 0);
6544                 }
6545                 for (; i<*numofforms; i++) {
6546                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
6547                         smb_io_form_1("", buffer, &forms_1[i], 0);
6548                 }
6549
6550                 SAFE_FREE(forms_1);
6551
6552                 if (*needed > offered) {
6553                         *numofforms=0;
6554                         return WERR_INSUFFICIENT_BUFFER;
6555                 }
6556                 else
6557                         return WERR_OK;
6558                         
6559         default:
6560                 SAFE_FREE(list);
6561                 SAFE_FREE(builtinlist);
6562                 return WERR_UNKNOWN_LEVEL;
6563         }
6564
6565 }
6566
6567 /****************************************************************************
6568 ****************************************************************************/
6569
6570 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6571 {
6572         uint32 level = q_u->level;
6573         UNISTR2 *uni_formname = &q_u->formname;
6574         NEW_BUFFER *buffer = NULL;
6575         uint32 offered = q_u->offered;
6576         uint32 *needed = &r_u->needed;
6577
6578         nt_forms_struct *list=NULL;
6579         nt_forms_struct builtin_form;
6580         BOOL foundBuiltin;
6581         FORM_1 form_1;
6582         fstring form_name;
6583         int buffer_size=0;
6584         int numofforms=0, i=0;
6585
6586         /* that's an [in out] buffer */
6587         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6588         buffer = r_u->buffer;
6589
6590         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6591
6592         DEBUG(4,("_spoolss_getform\n"));
6593         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6594         DEBUGADD(5,("Info level [%d]\n",          level));
6595
6596         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6597         if (!foundBuiltin) {
6598                 numofforms = get_ntforms(&list);
6599                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
6600
6601                 if (numofforms == 0)
6602                         return WERR_BADFID;
6603         }
6604
6605         switch (level) {
6606         case 1:
6607                 if (foundBuiltin) {
6608                         fill_form_1(&form_1, &builtin_form);
6609                 } else {
6610
6611                         /* Check if the requested name is in the list of form structures */
6612                         for (i=0; i<numofforms; i++) {
6613
6614                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6615
6616                                 if (strequal(form_name, list[i].name)) {
6617                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6618                                         fill_form_1(&form_1, &list[i]);
6619                                         break;
6620                                 }
6621                         }
6622                         
6623                         SAFE_FREE(list);
6624                         if (i == numofforms) {
6625                                 return WERR_BADFID;
6626                         }
6627                 }
6628                 /* check the required size. */
6629
6630                 *needed=spoolss_size_form_1(&form_1);
6631                 
6632                 if (!alloc_buffer_size(buffer, buffer_size)){
6633                         return WERR_INSUFFICIENT_BUFFER;
6634                 }
6635
6636                 if (*needed > offered) {
6637                         return WERR_INSUFFICIENT_BUFFER;
6638                 }
6639
6640                 /* fill the buffer with the form structures */
6641                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6642                 smb_io_form_1("", buffer, &form_1, 0);
6643
6644                 return WERR_OK;
6645                         
6646         default:
6647                 SAFE_FREE(list);
6648                 return WERR_UNKNOWN_LEVEL;
6649         }
6650 }
6651
6652 /****************************************************************************
6653 ****************************************************************************/
6654
6655 static void fill_port_1(PORT_INFO_1 *port, char *name)
6656 {
6657         init_unistr(&port->port_name, name);
6658 }
6659
6660 /****************************************************************************
6661 ****************************************************************************/
6662
6663 static void fill_port_2(PORT_INFO_2 *port, char *name)
6664 {
6665         init_unistr(&port->port_name, name);
6666         init_unistr(&port->monitor_name, "Local Monitor");
6667         init_unistr(&port->description, "Local Port");
6668 #define PORT_TYPE_WRITE 1
6669         port->port_type=PORT_TYPE_WRITE;
6670         port->reserved=0x0;     
6671 }
6672
6673 /****************************************************************************
6674  enumports level 1.
6675 ****************************************************************************/
6676
6677 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6678 {
6679         PORT_INFO_1 *ports=NULL;
6680         int i=0;
6681
6682         if (*lp_enumports_cmd()) {
6683                 char *cmd = lp_enumports_cmd();
6684                 char **qlines;
6685                 pstring command;
6686                 int numlines;
6687                 int ret;
6688                 int fd;
6689
6690                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6691
6692                 DEBUG(10,("Running [%s]\n", command));
6693                 ret = smbrun(command, &fd);
6694                 DEBUG(10,("Returned [%d]\n", ret));
6695                 if (ret != 0) {
6696                         if (fd != -1)
6697                                 close(fd);
6698                         /* Is this the best error to return here? */
6699                         return WERR_ACCESS_DENIED;
6700                 }
6701
6702                 numlines = 0;
6703                 qlines = fd_lines_load(fd, &numlines);
6704                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6705                 close(fd);
6706
6707                 if(numlines) {
6708                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6709                                 DEBUG(10,("Returning WERR_NOMEM [%s]\n", 
6710                                           dos_errstr(WERR_NOMEM)));
6711                                 file_lines_free(qlines);
6712                                 return WERR_NOMEM;
6713                         }
6714
6715                         for (i=0; i<numlines; i++) {
6716                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6717                                 fill_port_1(&ports[i], qlines[i]);
6718                         }
6719
6720                         file_lines_free(qlines);
6721                 }
6722
6723                 *returned = numlines;
6724
6725         } else {
6726                 *returned = 1; /* Sole Samba port returned. */
6727
6728                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6729                         return WERR_NOMEM;
6730         
6731                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6732
6733                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6734         }
6735
6736         /* check the required size. */
6737         for (i=0; i<*returned; i++) {
6738                 DEBUGADD(6,("adding port [%d]'s size\n", i));
6739                 *needed += spoolss_size_port_info_1(&ports[i]);
6740         }
6741                 
6742         if (!alloc_buffer_size(buffer, *needed)) {
6743                 SAFE_FREE(ports);
6744                 return WERR_INSUFFICIENT_BUFFER;
6745         }
6746
6747         /* fill the buffer with the ports structures */
6748         for (i=0; i<*returned; i++) {
6749                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6750                 smb_io_port_1("", buffer, &ports[i], 0);
6751         }
6752
6753         SAFE_FREE(ports);
6754
6755         if (*needed > offered) {
6756                 *returned=0;
6757                 return WERR_INSUFFICIENT_BUFFER;
6758         }
6759
6760         return WERR_OK;
6761 }
6762
6763 /****************************************************************************
6764  enumports level 2.
6765 ****************************************************************************/
6766
6767 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6768 {
6769         PORT_INFO_2 *ports=NULL;
6770         int i=0;
6771
6772         if (*lp_enumports_cmd()) {
6773                 char *cmd = lp_enumports_cmd();
6774                 char *path;
6775                 char **qlines;
6776                 pstring tmp_file;
6777                 pstring command;
6778                 int numlines;
6779                 int ret;
6780                 int fd;
6781
6782                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6783                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6784                 else
6785                         path = lp_lockdir();
6786
6787                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6788                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6789
6790                 unlink(tmp_file);
6791                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6792                 ret = smbrun(command, &fd);
6793                 DEBUGADD(10,("returned [%d]\n", ret));
6794                 if (ret != 0) {
6795                         if (fd != -1)
6796                                 close(fd);
6797                         /* Is this the best error to return here? */
6798                         return WERR_ACCESS_DENIED;
6799                 }
6800
6801                 numlines = 0;
6802                 qlines = fd_lines_load(fd, &numlines);
6803                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6804                 close(fd);
6805
6806                 if(numlines) {
6807                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6808                                 file_lines_free(qlines);
6809                                 return WERR_NOMEM;
6810                         }
6811
6812                         for (i=0; i<numlines; i++) {
6813                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6814                                 fill_port_2(&(ports[i]), qlines[i]);
6815                         }
6816
6817                         file_lines_free(qlines);
6818                 }
6819
6820                 *returned = numlines;
6821
6822         } else {
6823
6824                 *returned = 1;
6825
6826                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6827                         return WERR_NOMEM;
6828         
6829                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6830
6831                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6832         }
6833
6834         /* check the required size. */
6835         for (i=0; i<*returned; i++) {
6836                 DEBUGADD(6,("adding port [%d]'s size\n", i));
6837                 *needed += spoolss_size_port_info_2(&ports[i]);
6838         }
6839                 
6840         if (!alloc_buffer_size(buffer, *needed)) {
6841                 SAFE_FREE(ports);
6842                 return WERR_INSUFFICIENT_BUFFER;
6843         }
6844
6845         /* fill the buffer with the ports structures */
6846         for (i=0; i<*returned; i++) {
6847                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6848                 smb_io_port_2("", buffer, &ports[i], 0);
6849         }
6850
6851         SAFE_FREE(ports);
6852
6853         if (*needed > offered) {
6854                 *returned=0;
6855                 return WERR_INSUFFICIENT_BUFFER;
6856         }
6857
6858         return WERR_OK;
6859 }
6860
6861 /****************************************************************************
6862  enumports.
6863 ****************************************************************************/
6864
6865 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6866 {
6867         uint32 level = q_u->level;
6868         NEW_BUFFER *buffer = NULL;
6869         uint32 offered = q_u->offered;
6870         uint32 *needed = &r_u->needed;
6871         uint32 *returned = &r_u->returned;
6872
6873         /* that's an [in out] buffer */
6874         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6875         buffer = r_u->buffer;
6876
6877         DEBUG(4,("_spoolss_enumports\n"));
6878         
6879         *returned=0;
6880         *needed=0;
6881         
6882         switch (level) {
6883         case 1:
6884                 return enumports_level_1(buffer, offered, needed, returned);
6885         case 2:
6886                 return enumports_level_2(buffer, offered, needed, returned);
6887         default:
6888                 return WERR_UNKNOWN_LEVEL;
6889         }
6890 }
6891
6892 /****************************************************************************
6893 ****************************************************************************/
6894
6895 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6896                                 const SPOOL_PRINTER_INFO_LEVEL *info,
6897                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6898                                 uint32 user_switch, const SPOOL_USER_CTR *user,
6899                                 POLICY_HND *handle)
6900 {
6901         NT_PRINTER_INFO_LEVEL *printer = NULL;
6902         fstring name;
6903         int     snum;
6904         WERROR err = WERR_OK;
6905
6906         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6907                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6908                 return WERR_NOMEM;
6909         }
6910
6911         ZERO_STRUCTP(printer);
6912
6913         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6914         if (!convert_printer_info(info, printer, 2)) {
6915                 free_a_printer(&printer, 2);
6916                 return WERR_NOMEM;
6917         }
6918
6919         /* check to see if the printer already exists */
6920
6921         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6922                 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n", 
6923                         printer->info_2->sharename));
6924                 free_a_printer(&printer, 2);
6925                 return WERR_PRINTER_ALREADY_EXISTS;
6926         }
6927
6928         if (*lp_addprinter_cmd() ) {
6929                 if ( !add_printer_hook(printer) ) {
6930                         free_a_printer(&printer,2);
6931                         return WERR_ACCESS_DENIED;
6932         }
6933         }
6934
6935         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6936              printer->info_2->sharename);
6937
6938         
6939         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6940                 free_a_printer(&printer,2);
6941                 return WERR_ACCESS_DENIED;
6942         }
6943
6944         /* you must be a printer admin to add a new printer */
6945         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6946                 free_a_printer(&printer,2);
6947                 return WERR_ACCESS_DENIED;              
6948         }
6949         
6950         /*
6951          * Do sanity check on the requested changes for Samba.
6952          */
6953
6954         if (!check_printer_ok(printer->info_2, snum)) {
6955                 free_a_printer(&printer,2);
6956                 return WERR_INVALID_PARAM;
6957         }
6958
6959         /*
6960          * When a printer is created, the drivername bound to the printer is used
6961          * to lookup previously saved driver initialization info, which is then 
6962          * bound to the new printer, simulating what happens in the Windows arch.
6963          */
6964
6965         if (!devmode)
6966         {
6967                 set_driver_init(printer, 2);
6968         }
6969         else 
6970         {
6971                 /* A valid devmode was included, convert and link it
6972                 */
6973                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6974
6975                 if (!convert_devicemode(printer->info_2->printername, devmode,
6976                                 &printer->info_2->devmode))
6977                         return  WERR_NOMEM;
6978         }
6979
6980         /* write the ASCII on disk */
6981         err = mod_a_printer(*printer, 2);
6982         if (!W_ERROR_IS_OK(err)) {
6983                 free_a_printer(&printer,2);
6984                 return err;
6985         }
6986
6987         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6988                 /* Handle open failed - remove addition. */
6989                 del_a_printer(printer->info_2->sharename);
6990                 free_a_printer(&printer,2);
6991                 return WERR_ACCESS_DENIED;
6992         }
6993
6994         update_c_setprinter(False);
6995         free_a_printer(&printer,2);
6996
6997         return WERR_OK;
6998 }
6999
7000 /****************************************************************************
7001 ****************************************************************************/
7002
7003 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7004 {
7005         UNISTR2 *uni_srv_name = &q_u->server_name;
7006         uint32 level = q_u->level;
7007         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7008         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7009         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7010         uint32 user_switch = q_u->user_switch;
7011         SPOOL_USER_CTR *user = &q_u->user_ctr;
7012         POLICY_HND *handle = &r_u->handle;
7013
7014         switch (level) {
7015                 case 1:
7016                         /* we don't handle yet */
7017                         /* but I know what to do ... */
7018                         return WERR_UNKNOWN_LEVEL;
7019                 case 2:
7020                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7021                                                             devmode, sdb,
7022                                                             user_switch, user, handle);
7023                 default:
7024                         return WERR_UNKNOWN_LEVEL;
7025         }
7026 }
7027
7028 /****************************************************************************
7029 ****************************************************************************/
7030
7031 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7032 {
7033         uint32 level = q_u->level;
7034         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7035         WERROR err = WERR_OK;
7036         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7037         struct current_user user;
7038         fstring driver_name;
7039         uint32 version;
7040
7041         ZERO_STRUCT(driver);
7042
7043         get_current_user(&user, p);
7044         
7045         if (!convert_printer_driver_info(info, &driver, level)) {
7046                 err = WERR_NOMEM;
7047                 goto done;
7048         }
7049
7050         DEBUG(5,("Cleaning driver's information\n"));
7051         err = clean_up_driver_struct(driver, level, &user);
7052         if (!W_ERROR_IS_OK(err))
7053                 goto done;
7054
7055         DEBUG(5,("Moving driver to final destination\n"));
7056         if(!move_driver_to_download_area(driver, level, &user, &err)) {
7057                 if (W_ERROR_IS_OK(err))
7058                         err = WERR_ACCESS_DENIED;
7059                 goto done;
7060         }
7061
7062         if (add_a_printer_driver(driver, level)!=0) {
7063                 err = WERR_ACCESS_DENIED;
7064                 goto done;
7065         }
7066
7067         /* BEGIN_ADMIN_LOG */
7068         switch(level) {
7069             case 3:
7070                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7071                         driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7072                 fstrcpy(driver_name, driver.info_3->name);
7073                 break;
7074             case 6:   
7075                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7076                         driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7077                 fstrcpy(driver_name, driver.info_6->name);
7078                 break;
7079         }
7080         /* END_ADMIN_LOG */
7081
7082         /* 
7083          * I think this is where he DrvUpgradePrinter() hook would be
7084          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7085          * server.  Right now, we just need to send ourselves a message
7086          * to update each printer bound to this driver.   --jerry       
7087          */
7088          
7089         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7090                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7091                         driver_name));
7092         }
7093
7094         /*
7095          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7096          * decide if the driver init data should be deleted. The rules are:
7097          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7098          *  2) delete init data only if there is no 2k/Xp driver
7099          *  3) always delete init data
7100          * The generalized rule is always use init data from the highest order driver.
7101          * It is necessary to follow the driver install by an initialization step to
7102          * finish off this process.
7103         */
7104         if (level == 3)
7105                 version = driver.info_3->cversion;
7106         else if (level == 6)
7107                 version = driver.info_6->version;
7108         else
7109                 version = -1;
7110         switch (version) {
7111                 /*
7112                  * 9x printer driver - never delete init data
7113                 */
7114                 case 0: 
7115                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7116                                         driver_name));
7117                         break;
7118                 
7119                 /*
7120                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7121                  * there is no 2k/Xp driver init data for this driver name.
7122                 */
7123                 case 2:
7124                 {
7125                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7126
7127                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7128                                 /*
7129                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7130                                 */
7131                                 if (!del_driver_init(driver_name))
7132                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7133                         } else {
7134                                 /*
7135                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7136                                 */
7137                                 free_a_printer_driver(driver1,3);
7138                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n", 
7139                                                 driver_name));
7140                         }
7141                 }
7142                 break;
7143
7144                 /*
7145                  * 2k or Xp printer driver - always delete init data
7146                 */
7147                 case 3: 
7148                         if (!del_driver_init(driver_name))
7149                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7150                         break;
7151
7152                 default:
7153                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7154                         break;
7155         }
7156
7157         
7158 done:
7159         free_a_printer_driver(driver, level);
7160         return err;
7161 }
7162
7163 /********************************************************************
7164  * spoolss_addprinterdriverex
7165  ********************************************************************/
7166
7167 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7168 {
7169         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7170         SPOOL_R_ADDPRINTERDRIVER r_u_local;
7171         
7172         /* 
7173          * we only support the semantics of AddPrinterDriver()
7174          * i.e. only copy files that are newer than existing ones
7175          */
7176         
7177         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7178                 return WERR_ACCESS_DENIED;
7179         
7180         ZERO_STRUCT(q_u_local);
7181         ZERO_STRUCT(r_u_local);
7182
7183         /* just pass the information off to _spoolss_addprinterdriver() */
7184         q_u_local.server_name_ptr = q_u->server_name_ptr;
7185         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7186         q_u_local.level = q_u->level;
7187         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7188         
7189         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7190 }
7191
7192 /****************************************************************************
7193 ****************************************************************************/
7194
7195 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7196 {
7197         init_unistr(&info->name, name);
7198 }
7199
7200 /****************************************************************************
7201 ****************************************************************************/
7202
7203 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7204 {
7205         pstring path;
7206         pstring long_archi;
7207         pstring short_archi;
7208         DRIVER_DIRECTORY_1 *info=NULL;
7209
7210         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7211
7212         if (get_short_archi(short_archi, long_archi)==False)
7213                 return WERR_INVALID_ENVIRONMENT;
7214
7215         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7216                 return WERR_NOMEM;
7217
7218         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7219
7220         DEBUG(4,("printer driver directory: [%s]\n", path));
7221
7222         fill_driverdir_1(info, path);
7223         
7224         *needed += spoolss_size_driverdir_info_1(info);
7225
7226         if (!alloc_buffer_size(buffer, *needed)) {
7227                 SAFE_FREE(info);
7228                 return WERR_INSUFFICIENT_BUFFER;
7229         }
7230
7231         smb_io_driverdir_1("", buffer, info, 0);
7232
7233         SAFE_FREE(info);
7234         
7235         if (*needed > offered)
7236                 return WERR_INSUFFICIENT_BUFFER;
7237
7238         return WERR_OK;
7239 }
7240
7241 /****************************************************************************
7242 ****************************************************************************/
7243
7244 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7245 {
7246         UNISTR2 *name = &q_u->name;
7247         UNISTR2 *uni_environment = &q_u->environment;
7248         uint32 level = q_u->level;
7249         NEW_BUFFER *buffer = NULL;
7250         uint32 offered = q_u->offered;
7251         uint32 *needed = &r_u->needed;
7252
7253         /* that's an [in out] buffer */
7254         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7255         buffer = r_u->buffer;
7256
7257         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7258
7259         *needed=0;
7260
7261         switch(level) {
7262         case 1:
7263                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7264         default:
7265                 return WERR_UNKNOWN_LEVEL;
7266         }
7267 }
7268         
7269 /****************************************************************************
7270 ****************************************************************************/
7271
7272 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7273 {
7274         POLICY_HND *handle = &q_u->handle;
7275         uint32 idx               = q_u->index;
7276         uint32 in_value_len      = q_u->valuesize;
7277         uint32 in_data_len       = q_u->datasize;
7278         uint32 *out_max_value_len = &r_u->valuesize;
7279         uint16 **out_value       = &r_u->value;
7280         uint32 *out_value_len    = &r_u->realvaluesize;
7281         uint32 *out_type         = &r_u->type;
7282         uint32 *out_max_data_len = &r_u->datasize;
7283         uint8  **data_out        = &r_u->data;
7284         uint32 *out_data_len     = &r_u->realdatasize;
7285
7286         NT_PRINTER_INFO_LEVEL *printer = NULL;
7287         
7288         uint32          param_index;
7289         uint32          biggest_valuesize;
7290         uint32          biggest_datasize;
7291         uint32          data_len;
7292         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7293         int             snum;
7294         WERROR          result;
7295         REGISTRY_VALUE  *val;
7296         NT_PRINTER_DATA *p_data;
7297         int             i, key_index, num_values;
7298         int             name_length;
7299         
7300         ZERO_STRUCT( printer );
7301         
7302         *out_type = 0;
7303
7304         *out_max_data_len = 0;
7305         *data_out         = NULL;
7306         *out_data_len     = 0;
7307
7308         DEBUG(5,("spoolss_enumprinterdata\n"));
7309
7310         if (!Printer) {
7311                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7312                 return WERR_BADFID;
7313         }
7314
7315         if (!get_printer_snum(p,handle, &snum))
7316                 return WERR_BADFID;
7317         
7318         result = get_a_printer(&printer, 2, lp_servicename(snum));
7319         if (!W_ERROR_IS_OK(result))
7320                 return result;
7321                 
7322         p_data = &printer->info_2->data;        
7323         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7324
7325         result = WERR_OK;
7326
7327         /*
7328          * The NT machine wants to know the biggest size of value and data
7329          *
7330          * cf: MSDN EnumPrinterData remark section
7331          */
7332          
7333         if ( !in_value_len && !in_data_len ) 
7334         {
7335                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7336
7337                 param_index       = 0;
7338                 biggest_valuesize = 0;
7339                 biggest_datasize  = 0;
7340                                 
7341                 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7342                 
7343                 for ( i=0; i<num_values; i++ )
7344                 {
7345                         val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7346                         
7347                         name_length = strlen(val->valuename);
7348                         if ( strlen(val->valuename) > biggest_valuesize ) 
7349                                 biggest_valuesize = name_length;
7350                                 
7351                         if ( val->size > biggest_datasize )
7352                                 biggest_datasize = val->size;
7353                                 
7354                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, 
7355                                 biggest_datasize));
7356                 }
7357
7358                 /* the value is an UNICODE string but real_value_size is the length 
7359                    in bytes including the trailing 0 */
7360                    
7361                 *out_value_len = 2 * (1+biggest_valuesize);
7362                 *out_data_len  = biggest_datasize;
7363
7364                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7365
7366                 goto done;
7367         }
7368         
7369         /*
7370          * the value len is wrong in NT sp3
7371          * that's the number of bytes not the number of unicode chars
7372          */
7373          
7374         val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7375
7376         if ( !val ) 
7377         {
7378
7379                 /* out_value should default to "" or else NT4 has
7380                    problems unmarshalling the response */
7381
7382                 *out_max_value_len = (in_value_len/sizeof(uint16));
7383                 
7384                 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL ) 
7385                 {
7386                         result = WERR_NOMEM;
7387                         goto done;
7388                 }
7389
7390                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7391
7392                 /* the data is counted in bytes */
7393                 
7394                 *out_max_data_len = in_data_len;
7395                 *out_data_len     = in_data_len;
7396                 
7397                 /* only allocate when given a non-zero data_len */
7398                 
7399                 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7400                 {
7401                         result = WERR_NOMEM;
7402                         goto done;
7403                 }
7404
7405                 result = WERR_NO_MORE_ITEMS;
7406         }
7407         else 
7408         {
7409                 /*
7410                  * the value is:
7411                  * - counted in bytes in the request
7412                  * - counted in UNICODE chars in the max reply
7413                  * - counted in bytes in the real size
7414                  *
7415                  * take a pause *before* coding not *during* coding
7416                  */
7417         
7418                 /* name */
7419                 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7420                 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL ) 
7421                 {
7422                         result = WERR_NOMEM;
7423                         goto done;
7424                 }
7425         
7426                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7427
7428                 /* type */
7429                 
7430                 *out_type = regval_type( val );
7431
7432                 /* data - counted in bytes */
7433
7434                 *out_max_data_len = in_data_len;
7435                 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) 
7436                 {
7437                         result = WERR_NOMEM;
7438                         goto done;
7439                 }
7440                 data_len = (size_t)regval_size(val);
7441                 memcpy( *data_out, regval_data_p(val), data_len );
7442                 *out_data_len = data_len;
7443         }
7444
7445 done:
7446         free_a_printer(&printer, 2);
7447         return result;
7448 }
7449
7450 /****************************************************************************
7451 ****************************************************************************/
7452
7453 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7454 {
7455         POLICY_HND              *handle = &q_u->handle;
7456         UNISTR2                 *value = &q_u->value;
7457         uint32                  type = q_u->type;
7458         uint8                   *data = q_u->data;
7459         uint32                  real_len = q_u->real_len;
7460
7461         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7462         int                     snum=0;
7463         WERROR                  status = WERR_OK;
7464         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
7465         fstring                 valuename;
7466         
7467         DEBUG(5,("spoolss_setprinterdata\n"));
7468
7469         if (!Printer) {
7470                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7471                 return WERR_BADFID;
7472         }
7473
7474         if (!get_printer_snum(p,handle, &snum))
7475                 return WERR_BADFID;
7476
7477         /* 
7478          * Access check : NT returns "access denied" if you make a 
7479          * SetPrinterData call without the necessary privildge.
7480          * we were originally returning OK if nothing changed
7481          * which made Win2k issue **a lot** of SetPrinterData
7482          * when connecting to a printer  --jerry
7483          */
7484
7485         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
7486         {
7487                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7488                 status = WERR_ACCESS_DENIED;
7489                 goto done;
7490         }
7491
7492         status = get_a_printer(&printer, 2, lp_servicename(snum));
7493         if (!W_ERROR_IS_OK(status))
7494                 return status;
7495
7496         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7497         
7498         /*
7499          * When client side code sets a magic printer data key, detect it and save
7500          * the current printer data and the magic key's data (its the DEVMODE) for
7501          * future printer/driver initializations.
7502          */
7503         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY)) 
7504         {
7505                 /* Set devmode and printer initialization info */
7506                 status = save_driver_init( printer, 2, data, real_len );
7507         
7508                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7509         }
7510         else 
7511         {
7512         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename, 
7513                                         type, data, real_len );
7514                 if ( W_ERROR_IS_OK(status) )
7515                         status = mod_a_printer(*printer, 2);
7516         }
7517
7518 done:
7519         free_a_printer(&printer, 2);
7520
7521         return status;
7522 }
7523
7524 /****************************************************************************
7525 ****************************************************************************/
7526
7527 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7528 {
7529         POLICY_HND      *handle = &q_u->handle;
7530         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
7531         int             snum;
7532         
7533         DEBUG(5,("_spoolss_resetprinter\n"));
7534
7535         /*
7536          * All we do is to check to see if the handle and queue is valid.
7537          * This call really doesn't mean anything to us because we only
7538          * support RAW printing.   --jerry
7539          */
7540          
7541         if (!Printer) {
7542                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7543                 return WERR_BADFID;
7544         }
7545
7546         if (!get_printer_snum(p,handle, &snum))
7547                 return WERR_BADFID;
7548
7549
7550         /* blindly return success */    
7551         return WERR_OK;
7552 }
7553
7554
7555 /****************************************************************************
7556 ****************************************************************************/
7557
7558 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7559 {
7560         POLICY_HND      *handle = &q_u->handle;
7561         UNISTR2         *value = &q_u->valuename;
7562
7563         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7564         int             snum=0;
7565         WERROR          status = WERR_OK;
7566         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
7567         pstring         valuename;
7568         
7569         DEBUG(5,("spoolss_deleteprinterdata\n"));
7570         
7571         if (!Printer) {
7572                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7573                 return WERR_BADFID;
7574         }
7575
7576         if (!get_printer_snum(p, handle, &snum))
7577                 return WERR_BADFID;
7578
7579         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7580                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7581                 return WERR_ACCESS_DENIED;
7582         }
7583
7584         status = get_a_printer(&printer, 2, lp_servicename(snum));
7585         if (!W_ERROR_IS_OK(status))
7586                 return status;
7587
7588         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7589
7590         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7591
7592         free_a_printer(&printer, 2);
7593
7594         return status;
7595 }
7596
7597 /****************************************************************************
7598 ****************************************************************************/
7599
7600 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7601 {
7602         POLICY_HND *handle = &q_u->handle;
7603         FORM *form = &q_u->form;
7604         nt_forms_struct tmpForm;
7605         int snum;
7606         WERROR status = WERR_OK;
7607         NT_PRINTER_INFO_LEVEL *printer = NULL;
7608
7609         int count=0;
7610         nt_forms_struct *list=NULL;
7611         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7612
7613         DEBUG(5,("spoolss_addform\n"));
7614
7615         if (!Printer) {
7616                 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7617                 return WERR_BADFID;
7618         }
7619         
7620         
7621         /* forms can be added on printer of on the print server handle */
7622         
7623         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7624         {
7625                 if (!get_printer_snum(p,handle, &snum))
7626                         return WERR_BADFID;
7627          
7628                 status = get_a_printer(&printer, 2, lp_servicename(snum));
7629                 if (!W_ERROR_IS_OK(status))
7630                         goto done;
7631         }
7632
7633         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7634                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7635                 status = WERR_ACCESS_DENIED;
7636                 goto done;
7637         }
7638         
7639         /* can't add if builtin */
7640         
7641         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7642                 status = WERR_ALREADY_EXISTS;
7643                 goto done;
7644         }
7645
7646         count = get_ntforms(&list);
7647         
7648         if(!add_a_form(&list, form, &count)) {
7649                 status =  WERR_NOMEM;
7650                 goto done;
7651         }
7652         
7653         write_ntforms(&list, count);
7654         
7655         /*
7656          * ChangeID must always be set if this is a printer
7657          */
7658          
7659         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7660                 status = mod_a_printer(*printer, 2);
7661         
7662 done:
7663         if ( printer )
7664                 free_a_printer(&printer, 2);
7665         SAFE_FREE(list);
7666
7667         return status;
7668 }
7669
7670 /****************************************************************************
7671 ****************************************************************************/
7672
7673 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7674 {
7675         POLICY_HND *handle = &q_u->handle;
7676         UNISTR2 *form_name = &q_u->name;
7677         nt_forms_struct tmpForm;
7678         int count=0;
7679         nt_forms_struct *list=NULL;
7680         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7681         int snum;
7682         WERROR status = WERR_OK;
7683         NT_PRINTER_INFO_LEVEL *printer = NULL;
7684
7685         DEBUG(5,("spoolss_deleteform\n"));
7686
7687         if (!Printer) {
7688                 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7689                 return WERR_BADFID;
7690         }
7691
7692         /* forms can be deleted on printer of on the print server handle */
7693         
7694         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7695         {
7696                 if (!get_printer_snum(p,handle, &snum))
7697                         return WERR_BADFID;
7698          
7699                 status = get_a_printer(&printer, 2, lp_servicename(snum));
7700                 if (!W_ERROR_IS_OK(status))
7701                         goto done;
7702         }
7703
7704         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7705                 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7706                 status = WERR_ACCESS_DENIED;
7707                 goto done;
7708         }
7709
7710         /* can't delete if builtin */
7711         
7712         if (get_a_builtin_ntform(form_name,&tmpForm)) {
7713                 status = WERR_INVALID_PARAM;
7714                 goto done;
7715         }
7716
7717         count = get_ntforms(&list);
7718         
7719         if ( !delete_a_form(&list, form_name, &count, &status ))
7720                 goto done;
7721
7722         /*
7723          * ChangeID must always be set if this is a printer
7724          */
7725          
7726         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7727                 status = mod_a_printer(*printer, 2);
7728         
7729 done:
7730         if ( printer )
7731                 free_a_printer(&printer, 2);
7732         SAFE_FREE(list);
7733
7734         return status;
7735 }
7736
7737 /****************************************************************************
7738 ****************************************************************************/
7739
7740 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7741 {
7742         POLICY_HND *handle = &q_u->handle;
7743         FORM *form = &q_u->form;
7744         nt_forms_struct tmpForm;
7745         int snum;
7746         WERROR status = WERR_OK;
7747         NT_PRINTER_INFO_LEVEL *printer = NULL;
7748
7749         int count=0;
7750         nt_forms_struct *list=NULL;
7751         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7752
7753         DEBUG(5,("spoolss_setform\n"));
7754
7755         if (!Printer) {
7756                 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7757                 return WERR_BADFID;
7758         }
7759
7760         /* forms can be modified on printer of on the print server handle */
7761         
7762         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7763         {
7764                 if (!get_printer_snum(p,handle, &snum))
7765                         return WERR_BADFID;
7766          
7767                 status = get_a_printer(&printer, 2, lp_servicename(snum));
7768                 if (!W_ERROR_IS_OK(status))
7769                         goto done;
7770         }
7771
7772         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7773                 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7774                 status = WERR_ACCESS_DENIED;
7775                 goto done;
7776         }
7777
7778         /* can't set if builtin */
7779         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7780                 status = WERR_INVALID_PARAM;
7781                 goto done;
7782         }
7783
7784         count = get_ntforms(&list);
7785         update_a_form(&list, form, count);
7786         write_ntforms(&list, count);
7787
7788         /*
7789          * ChangeID must always be set if this is a printer
7790          */
7791          
7792         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7793                 status = mod_a_printer(*printer, 2);
7794         
7795         
7796 done:
7797         if ( printer )
7798                 free_a_printer(&printer, 2);
7799         SAFE_FREE(list);
7800
7801         return status;
7802 }
7803
7804 /****************************************************************************
7805  enumprintprocessors level 1.
7806 ****************************************************************************/
7807
7808 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7809 {
7810         PRINTPROCESSOR_1 *info_1=NULL;
7811         
7812         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7813                 return WERR_NOMEM;
7814
7815         (*returned) = 0x1;
7816         
7817         init_unistr(&info_1->name, "winprint");
7818
7819         *needed += spoolss_size_printprocessor_info_1(info_1);
7820
7821         if (!alloc_buffer_size(buffer, *needed))
7822                 return WERR_INSUFFICIENT_BUFFER;
7823
7824         smb_io_printprocessor_info_1("", buffer, info_1, 0);
7825
7826         SAFE_FREE(info_1);
7827
7828         if (*needed > offered) {
7829                 *returned=0;
7830                 return WERR_INSUFFICIENT_BUFFER;
7831         }
7832
7833         return WERR_OK;
7834 }
7835
7836 /****************************************************************************
7837 ****************************************************************************/
7838
7839 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7840 {
7841         uint32 level = q_u->level;
7842         NEW_BUFFER *buffer = NULL;
7843         uint32 offered = q_u->offered;
7844         uint32 *needed = &r_u->needed;
7845         uint32 *returned = &r_u->returned;
7846
7847         /* that's an [in out] buffer */
7848         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7849         buffer = r_u->buffer;
7850
7851         DEBUG(5,("spoolss_enumprintprocessors\n"));
7852
7853         /*
7854          * Enumerate the print processors ...
7855          *
7856          * Just reply with "winprint", to keep NT happy
7857          * and I can use my nice printer checker.
7858          */
7859         
7860         *returned=0;
7861         *needed=0;
7862         
7863         switch (level) {
7864         case 1:
7865                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7866         default:
7867                 return WERR_UNKNOWN_LEVEL;
7868         }
7869 }
7870
7871 /****************************************************************************
7872  enumprintprocdatatypes level 1.
7873 ****************************************************************************/
7874
7875 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7876 {
7877         PRINTPROCDATATYPE_1 *info_1=NULL;
7878         
7879         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7880                 return WERR_NOMEM;
7881
7882         (*returned) = 0x1;
7883         
7884         init_unistr(&info_1->name, "RAW");
7885
7886         *needed += spoolss_size_printprocdatatype_info_1(info_1);
7887
7888         if (!alloc_buffer_size(buffer, *needed))
7889                 return WERR_INSUFFICIENT_BUFFER;
7890
7891         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7892
7893         SAFE_FREE(info_1);
7894
7895         if (*needed > offered) {
7896                 *returned=0;
7897                 return WERR_INSUFFICIENT_BUFFER;
7898         }
7899
7900         return WERR_OK;
7901 }
7902
7903 /****************************************************************************
7904 ****************************************************************************/
7905
7906 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7907 {
7908         uint32 level = q_u->level;
7909         NEW_BUFFER *buffer = NULL;
7910         uint32 offered = q_u->offered;
7911         uint32 *needed = &r_u->needed;
7912         uint32 *returned = &r_u->returned;
7913
7914         /* that's an [in out] buffer */
7915         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7916         buffer = r_u->buffer;
7917
7918         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7919         
7920         *returned=0;
7921         *needed=0;
7922         
7923         switch (level) {
7924         case 1:
7925                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7926         default:
7927                 return WERR_UNKNOWN_LEVEL;
7928         }
7929 }
7930
7931 /****************************************************************************
7932  enumprintmonitors level 1.
7933 ****************************************************************************/
7934
7935 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7936 {
7937         PRINTMONITOR_1 *info_1=NULL;
7938         
7939         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7940                 return WERR_NOMEM;
7941
7942         (*returned) = 0x1;
7943         
7944         init_unistr(&info_1->name, "Local Port");
7945
7946         *needed += spoolss_size_printmonitor_info_1(info_1);
7947
7948         if (!alloc_buffer_size(buffer, *needed))
7949                 return WERR_INSUFFICIENT_BUFFER;
7950
7951         smb_io_printmonitor_info_1("", buffer, info_1, 0);
7952
7953         SAFE_FREE(info_1);
7954
7955         if (*needed > offered) {
7956                 *returned=0;
7957                 return WERR_INSUFFICIENT_BUFFER;
7958         }
7959
7960         return WERR_OK;
7961 }
7962
7963 /****************************************************************************
7964  enumprintmonitors level 2.
7965 ****************************************************************************/
7966
7967 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7968 {
7969         PRINTMONITOR_2 *info_2=NULL;
7970         
7971         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7972                 return WERR_NOMEM;
7973
7974         (*returned) = 0x1;
7975         
7976         init_unistr(&info_2->name, "Local Port");
7977         init_unistr(&info_2->environment, "Windows NT X86");
7978         init_unistr(&info_2->dll_name, "localmon.dll");
7979
7980         *needed += spoolss_size_printmonitor_info_2(info_2);
7981
7982         if (!alloc_buffer_size(buffer, *needed))
7983                 return WERR_INSUFFICIENT_BUFFER;
7984
7985         smb_io_printmonitor_info_2("", buffer, info_2, 0);
7986
7987         SAFE_FREE(info_2);
7988
7989         if (*needed > offered) {
7990                 *returned=0;
7991                 return WERR_INSUFFICIENT_BUFFER;
7992         }
7993
7994         return WERR_OK;
7995 }
7996
7997 /****************************************************************************
7998 ****************************************************************************/
7999
8000 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8001 {
8002         uint32 level = q_u->level;
8003         NEW_BUFFER *buffer = NULL;
8004         uint32 offered = q_u->offered;
8005         uint32 *needed = &r_u->needed;
8006         uint32 *returned = &r_u->returned;
8007
8008         /* that's an [in out] buffer */
8009         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8010         buffer = r_u->buffer;
8011
8012         DEBUG(5,("spoolss_enumprintmonitors\n"));
8013
8014         /*
8015          * Enumerate the print monitors ...
8016          *
8017          * Just reply with "Local Port", to keep NT happy
8018          * and I can use my nice printer checker.
8019          */
8020         
8021         *returned=0;
8022         *needed=0;
8023         
8024         switch (level) {
8025         case 1:
8026                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8027         case 2:
8028                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8029         default:
8030                 return WERR_UNKNOWN_LEVEL;
8031         }
8032 }
8033
8034 /****************************************************************************
8035 ****************************************************************************/
8036
8037 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8038 {
8039         int i=0;
8040         BOOL found=False;
8041         JOB_INFO_1 *info_1=NULL;
8042
8043         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8044
8045         if (info_1 == NULL) {
8046                 SAFE_FREE(queue);
8047                 return WERR_NOMEM;
8048         }
8049                 
8050         for (i=0; i<count && found==False; i++) { 
8051                 if (queue[i].job==(int)jobid)
8052                         found=True;
8053         }
8054         
8055         if (found==False) {
8056                 SAFE_FREE(queue);
8057                 SAFE_FREE(info_1);
8058                 /* NT treats not found as bad param... yet another bad choice */
8059                 return WERR_INVALID_PARAM;
8060         }
8061         
8062         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8063         
8064         *needed += spoolss_size_job_info_1(info_1);
8065
8066         if (!alloc_buffer_size(buffer, *needed)) {
8067                 SAFE_FREE(info_1);
8068                 return WERR_INSUFFICIENT_BUFFER;
8069         }
8070
8071         smb_io_job_info_1("", buffer, info_1, 0);
8072
8073         SAFE_FREE(info_1);
8074
8075         if (*needed > offered)
8076                 return WERR_INSUFFICIENT_BUFFER;
8077
8078         return WERR_OK;
8079 }
8080
8081 /****************************************************************************
8082 ****************************************************************************/
8083
8084 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8085 {
8086         int             i = 0;
8087         BOOL            found = False;
8088         JOB_INFO_2      *info_2;
8089         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8090         WERROR          ret;
8091         DEVICEMODE      *devmode = NULL;
8092         NT_DEVICEMODE   *nt_devmode = NULL;
8093
8094         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8095
8096         ZERO_STRUCTP(info_2);
8097
8098         if (info_2 == NULL) {
8099                 ret = WERR_NOMEM;
8100                 goto done;
8101         }
8102
8103         for ( i=0; i<count && found==False; i++ ) 
8104         {
8105                 if (queue[i].job == (int)jobid)
8106                         found = True;
8107         }
8108         
8109         if ( !found ) 
8110         {
8111                 /* NT treats not found as bad param... yet another bad
8112                    choice */
8113                 ret = WERR_INVALID_PARAM;
8114                 goto done;
8115         }
8116         
8117         ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8118         if (!W_ERROR_IS_OK(ret))
8119                 goto done;
8120         
8121         /* 
8122          * if the print job does not have a DEVMODE associated with it, 
8123          * just use the one for the printer. A NULL devicemode is not
8124          *  a failure condition
8125          */
8126          
8127         if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8128                 devmode = construct_dev_mode(snum);
8129         else {
8130                 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8131                         ZERO_STRUCTP( devmode );
8132                         convert_nt_devicemode( devmode, nt_devmode );
8133                 }
8134         }
8135         
8136         fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8137         
8138         *needed += spoolss_size_job_info_2(info_2);
8139
8140         if (!alloc_buffer_size(buffer, *needed)) {
8141                 ret = WERR_INSUFFICIENT_BUFFER;
8142                 goto done;
8143         }
8144
8145         smb_io_job_info_2("", buffer, info_2, 0);
8146
8147         if (*needed > offered) {
8148                 ret = WERR_INSUFFICIENT_BUFFER;
8149                 goto done;
8150         }
8151
8152         ret = WERR_OK;
8153         
8154  done:
8155         /* Cleanup allocated memory */
8156
8157         free_job_info_2(info_2);        /* Also frees devmode */
8158         SAFE_FREE(info_2);
8159         free_a_printer(&ntprinter, 2);
8160
8161         return ret;
8162 }
8163
8164 /****************************************************************************
8165 ****************************************************************************/
8166
8167 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8168 {
8169         POLICY_HND *handle = &q_u->handle;
8170         uint32 jobid = q_u->jobid;
8171         uint32 level = q_u->level;
8172         NEW_BUFFER *buffer = NULL;
8173         uint32 offered = q_u->offered;
8174         uint32 *needed = &r_u->needed;
8175         WERROR          wstatus = WERR_OK;
8176
8177         int snum;
8178         int count;
8179         print_queue_struct      *queue = NULL;
8180         print_status_struct prt_status;
8181
8182         /* that's an [in out] buffer */
8183         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8184         buffer = r_u->buffer;
8185
8186         DEBUG(5,("spoolss_getjob\n"));
8187         
8188         *needed = 0;
8189         
8190         if (!get_printer_snum(p, handle, &snum))
8191                 return WERR_BADFID;
8192         
8193         count = print_queue_status(snum, &queue, &prt_status);
8194         
8195         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8196                      count, prt_status.status, prt_status.message));
8197                 
8198         switch ( level ) {
8199         case 1:
8200                         wstatus = getjob_level_1(queue, count, snum, jobid, 
8201                                 buffer, offered, needed);
8202                         break;
8203         case 2:
8204                         wstatus = getjob_level_2(queue, count, snum, jobid, 
8205                                 buffer, offered, needed);
8206                         break;
8207         default:
8208                         wstatus = WERR_UNKNOWN_LEVEL;
8209                         break;
8210         }
8211         
8212         SAFE_FREE(queue);
8213         return wstatus;
8214 }
8215
8216 /********************************************************************
8217  spoolss_getprinterdataex
8218  
8219  From MSDN documentation of GetPrinterDataEx: pass request
8220  to GetPrinterData if key is "PrinterDriverData".
8221  ********************************************************************/
8222
8223 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8224 {
8225         POLICY_HND      *handle = &q_u->handle;
8226         uint32          in_size = q_u->size;
8227         uint32          *type = &r_u->type;
8228         uint32          *out_size = &r_u->size;
8229         uint8           **data = &r_u->data;
8230         uint32          *needed = &r_u->needed;
8231         fstring         keyname, valuename;
8232         
8233         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8234         
8235         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8236         int                     snum = 0;
8237         WERROR                  status = WERR_OK;
8238
8239         DEBUG(4,("_spoolss_getprinterdataex\n"));
8240
8241         unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8242         unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8243         
8244         DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n", 
8245                 keyname, valuename));
8246
8247         /* in case of problem, return some default values */
8248         
8249         *needed   = 0;
8250         *type     = 0;
8251         *out_size = in_size;
8252
8253         if (!Printer) {
8254                 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8255                 status = WERR_BADFID;
8256                 goto done;
8257         }
8258
8259         /* Is the handle to a printer or to the server? */
8260
8261         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8262                 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8263                 status = WERR_INVALID_PARAM;
8264                 goto done;
8265         }
8266         
8267         if ( !get_printer_snum(p,handle, &snum) )
8268                 return WERR_BADFID;
8269
8270         status = get_a_printer(&printer, 2, lp_servicename(snum));
8271         if ( !W_ERROR_IS_OK(status) )
8272                 goto done;
8273
8274         /* check to see if the keyname is valid */
8275         if ( !strlen(keyname) ) {
8276                 status = WERR_INVALID_PARAM;
8277                 goto done;
8278         }
8279         
8280         if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8281                 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8282                 free_a_printer( &printer, 2 );
8283                 status = WERR_BADFILE;
8284                 goto done;
8285         }
8286         
8287         /* When given a new keyname, we should just create it */
8288
8289         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8290         
8291         if (*needed > *out_size)
8292                 status = WERR_MORE_DATA;
8293
8294 done:
8295         if ( !W_ERROR_IS_OK(status) ) 
8296         {
8297                 DEBUG(5, ("error: allocating %d\n", *out_size));
8298                 
8299                 /* reply this param doesn't exist */
8300                 
8301                 if ( *out_size ) 
8302                 {
8303                         if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8304                                 status = WERR_NOMEM;
8305                                 goto done;
8306                         }
8307                 } 
8308                 else {
8309                         *data = NULL;
8310         }
8311         }
8312         
8313         if ( printer )
8314         free_a_printer( &printer, 2 );
8315         
8316         return status;
8317 }
8318
8319 /********************************************************************
8320  * spoolss_setprinterdataex
8321  ********************************************************************/
8322
8323 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8324 {
8325         POLICY_HND              *handle = &q_u->handle; 
8326         uint32                  type = q_u->type;
8327         uint8                   *data = q_u->data;
8328         uint32                  real_len = q_u->real_len;
8329
8330         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8331         int                     snum = 0;
8332         WERROR                  status = WERR_OK;
8333         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
8334         fstring                 valuename;
8335         fstring                 keyname;
8336         char                    *oid_string;
8337         
8338         DEBUG(4,("_spoolss_setprinterdataex\n"));
8339
8340         /* From MSDN documentation of SetPrinterDataEx: pass request to
8341            SetPrinterData if key is "PrinterDriverData" */
8342
8343         if (!Printer) {
8344                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8345                 return WERR_BADFID;
8346         }
8347
8348         if ( !get_printer_snum(p,handle, &snum) )
8349                 return WERR_BADFID;
8350
8351         /* 
8352          * Access check : NT returns "access denied" if you make a 
8353          * SetPrinterData call without the necessary privildge.
8354          * we were originally returning OK if nothing changed
8355          * which made Win2k issue **a lot** of SetPrinterData
8356          * when connecting to a printer  --jerry
8357          */
8358
8359         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
8360         {
8361                 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8362                 return WERR_ACCESS_DENIED;
8363         }
8364
8365         status = get_a_printer(&printer, 2, lp_servicename(snum));
8366         if (!W_ERROR_IS_OK(status))
8367                 return status;
8368
8369         unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8370         unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8371         
8372         /* check for OID in valuename */
8373         
8374         if ( (oid_string = strchr( valuename, ',' )) != NULL )
8375         {
8376                 *oid_string = '\0';
8377                 oid_string++;
8378         }
8379
8380         /* save the registry data */
8381         
8382         status = set_printer_dataex( printer, keyname, valuename, type, data, real_len ); 
8383         
8384         /* save the OID if one was specified and the previous set call succeeded */
8385         
8386         if ( W_ERROR_IS_OK(status) && oid_string )
8387         {
8388
8389                 fstrcat( keyname, "\\" );
8390                 fstrcat( keyname, SPOOL_OID_KEY );
8391                 
8392                 /* 
8393                  * I'm not checking the status here on purpose.  Don't know 
8394                  * if this is right, but I'm returning the status from the 
8395                  * previous set_printer_dataex() call.  I have no idea if 
8396                  * this is right.    --jerry
8397                  */
8398                  
8399                 set_printer_dataex( printer, keyname, valuename, 
8400                                     REG_SZ, (void*)oid_string, strlen(oid_string)+1 );          
8401         }
8402         
8403         free_a_printer(&printer, 2);
8404
8405         return status;
8406 }
8407
8408
8409 /********************************************************************
8410  * spoolss_deleteprinterdataex
8411  ********************************************************************/
8412
8413 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8414 {
8415         POLICY_HND      *handle = &q_u->handle;
8416         UNISTR2         *value = &q_u->valuename;
8417         UNISTR2         *key = &q_u->keyname;
8418
8419         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8420         int             snum=0;
8421         WERROR          status = WERR_OK;
8422         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8423         pstring         valuename, keyname;
8424         
8425         DEBUG(5,("spoolss_deleteprinterdataex\n"));
8426         
8427         if (!Printer) {
8428                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8429                 return WERR_BADFID;
8430         }
8431
8432         if (!get_printer_snum(p, handle, &snum))
8433                 return WERR_BADFID;
8434
8435         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8436                 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8437                 return WERR_ACCESS_DENIED;
8438         }
8439
8440         status = get_a_printer(&printer, 2, lp_servicename(snum));
8441         if (!W_ERROR_IS_OK(status))
8442                 return status;
8443
8444         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8445         unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8446
8447         status = delete_printer_dataex( printer, keyname, valuename );
8448
8449         free_a_printer(&printer, 2);
8450
8451         return status;
8452 }
8453
8454 /********************************************************************
8455  * spoolss_enumprinterkey
8456  ********************************************************************/
8457
8458
8459 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8460 {
8461         fstring         key;
8462         fstring         *keynames = NULL;
8463         uint16          *enumkeys = NULL;
8464         int             num_keys;
8465         int             printerkey_len;
8466         POLICY_HND      *handle = &q_u->handle;
8467         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8468         NT_PRINTER_DATA *data;
8469         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8470         int             snum = 0;
8471         WERROR          status = WERR_BADFILE;
8472         
8473         
8474         DEBUG(4,("_spoolss_enumprinterkey\n"));
8475
8476         if (!Printer) {
8477                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8478                 return WERR_BADFID;
8479         }
8480
8481         if ( !get_printer_snum(p,handle, &snum) )
8482                 return WERR_BADFID;
8483
8484         status = get_a_printer(&printer, 2, lp_servicename(snum));
8485         if (!W_ERROR_IS_OK(status))
8486                 return status;
8487                 
8488         /* get the list of subkey names */
8489         
8490         unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8491         data = &printer->info_2->data;
8492
8493         num_keys = get_printer_subkeys( data, key, &keynames );
8494
8495         if ( num_keys == -1 ) {
8496                 status = WERR_BADFILE;
8497                 goto done;
8498         }
8499
8500         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
8501
8502         r_u->needed = printerkey_len*2;
8503
8504         if ( q_u->size < r_u->needed ) {
8505                 status = WERR_MORE_DATA;
8506                 goto done;
8507         }
8508
8509         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8510                 status = WERR_NOMEM;
8511                 goto done;
8512         }
8513                         
8514         status = WERR_OK;
8515
8516         if ( q_u->size < r_u->needed ) 
8517                 status = WERR_MORE_DATA;
8518
8519 done:
8520         free_a_printer( &printer, 2 );
8521         SAFE_FREE( keynames );
8522         
8523         return status;
8524 }
8525
8526 /********************************************************************
8527  * spoolss_deleteprinterkey
8528  ********************************************************************/
8529
8530 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8531 {
8532         POLICY_HND              *handle = &q_u->handle;
8533         Printer_entry           *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8534         fstring                 key;
8535         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8536         int                     snum=0;
8537         WERROR                  status;
8538         
8539         DEBUG(5,("spoolss_deleteprinterkey\n"));
8540         
8541         if (!Printer) {
8542                 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8543                 return WERR_BADFID;
8544         }
8545
8546         /* if keyname == NULL, return error */
8547         
8548         if ( !q_u->keyname.buffer )
8549                 return WERR_INVALID_PARAM;
8550                 
8551         if (!get_printer_snum(p, handle, &snum))
8552                 return WERR_BADFID;
8553
8554         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8555                 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8556                 return WERR_ACCESS_DENIED;
8557         }
8558
8559         status = get_a_printer(&printer, 2, lp_servicename(snum));
8560         if (!W_ERROR_IS_OK(status))
8561                 return status;
8562         
8563         /* delete the key and all subneys */
8564         
8565         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8566  
8567         status = delete_all_printer_data( printer->info_2, key );       
8568
8569         if ( W_ERROR_IS_OK(status) )
8570                 status = mod_a_printer(*printer, 2);
8571         
8572         free_a_printer( &printer, 2 );
8573         
8574         return status;
8575 }
8576
8577
8578 /********************************************************************
8579  * spoolss_enumprinterdataex
8580  ********************************************************************/
8581
8582 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8583 {
8584         POLICY_HND      *handle = &q_u->handle; 
8585         uint32          in_size = q_u->size;
8586         uint32          num_entries, 
8587                         needed;
8588         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8589         PRINTER_ENUM_VALUES     *enum_values = NULL;
8590         NT_PRINTER_DATA         *p_data;
8591         fstring         key;
8592         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8593         int             snum;
8594         WERROR          result;
8595         int             key_index;
8596         int             i;
8597         REGISTRY_VALUE  *val;
8598         char            *value_name;
8599         int             data_len;
8600         
8601
8602         DEBUG(4,("_spoolss_enumprinterdataex\n"));
8603
8604         if (!Printer) {
8605                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8606                 return WERR_BADFID;
8607         }
8608
8609         /* first get the printer off of disk */
8610         
8611         if (!get_printer_snum(p,handle, &snum))
8612                 return WERR_BADFID;
8613         
8614         ZERO_STRUCT(printer);
8615         result = get_a_printer(&printer, 2, lp_servicename(snum));
8616         if (!W_ERROR_IS_OK(result))
8617                 return result;
8618         
8619         /* now look for a match on the key name */
8620         
8621         p_data = &printer->info_2->data;
8622         
8623         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8624         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
8625         {
8626                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8627                 result = WERR_INVALID_PARAM;
8628                 goto done;
8629         }
8630         
8631         result = WERR_OK;
8632         needed = 0;
8633         
8634         /* allocate the memory for the array of pointers -- if necessary */
8635         
8636         num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8637         if ( num_entries )
8638         {
8639                 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8640                 {
8641                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8642                                 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8643                         result = WERR_NOMEM;
8644                         goto done;
8645                 }
8646
8647                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8648         }
8649                 
8650         /* 
8651          * loop through all params and build the array to pass 
8652          * back to the  client 
8653          */
8654          
8655         for ( i=0; i<num_entries; i++ )
8656         {
8657                 /* lookup the registry value */
8658                 
8659                 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8660                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8661
8662                 /* copy the data */
8663                 
8664                 value_name = regval_name( val );
8665                 init_unistr( &enum_values[i].valuename, value_name );
8666                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8667                 enum_values[i].type      = regval_type( val );
8668                 
8669                 data_len = regval_size( val );
8670                 if ( data_len ) {
8671                         if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) ) 
8672                         {
8673                                 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n", 
8674                                         data_len ));
8675                                 result = WERR_NOMEM;
8676                                 goto done;
8677                         }
8678                 }
8679                 enum_values[i].data_len = data_len;
8680
8681                 /* keep track of the size of the array in bytes */
8682                 
8683                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8684         }
8685         
8686         /* housekeeping information in the reply */
8687         
8688         r_u->needed     = needed;
8689         r_u->returned   = num_entries;
8690
8691         if (needed > in_size) {
8692                 result = WERR_MORE_DATA;
8693                 goto done;
8694         }
8695                 
8696         /* copy data into the reply */
8697         
8698         r_u->ctr.size           = r_u->needed;
8699         r_u->ctr.size_of_array  = r_u->returned;
8700         r_u->ctr.values         = enum_values;
8701         
8702         
8703                 
8704 done:   
8705         free_a_printer(&printer, 2);
8706
8707         return result;
8708 }
8709
8710 /****************************************************************************
8711 ****************************************************************************/
8712
8713 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8714 {
8715         init_unistr(&info->name, name);
8716 }
8717
8718 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
8719                                                  UNISTR2 *environment, 
8720                                                  NEW_BUFFER *buffer, 
8721                                                  uint32 offered, 
8722                                                  uint32 *needed)
8723 {
8724         pstring path;
8725         pstring long_archi;
8726         pstring short_archi;
8727         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8728
8729         unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8730
8731         if (get_short_archi(short_archi, long_archi)==False)
8732                 return WERR_INVALID_ENVIRONMENT;
8733
8734         if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8735                 return WERR_NOMEM;
8736
8737         pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8738
8739         fill_printprocessordirectory_1(info, path);
8740         
8741         *needed += spoolss_size_printprocessordirectory_info_1(info);
8742
8743         if (!alloc_buffer_size(buffer, *needed)) {
8744                 safe_free(info);
8745                 return WERR_INSUFFICIENT_BUFFER;
8746         }
8747
8748         smb_io_printprocessordirectory_1("", buffer, info, 0);
8749
8750         safe_free(info);
8751         
8752         if (*needed > offered)
8753                 return WERR_INSUFFICIENT_BUFFER;
8754         else
8755                 return WERR_OK;
8756 }
8757
8758 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8759 {
8760         uint32 level = q_u->level;
8761         NEW_BUFFER *buffer = NULL;
8762         uint32 offered = q_u->offered;
8763         uint32 *needed = &r_u->needed;
8764         WERROR result;
8765
8766         /* that's an [in out] buffer */
8767         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8768         buffer = r_u->buffer;
8769
8770         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8771         
8772         *needed=0;
8773
8774         switch(level) {
8775         case 1:
8776                 result = getprintprocessordirectory_level_1
8777                   (&q_u->name, &q_u->environment, buffer, offered, needed);
8778                 break;
8779         default:
8780                 result = WERR_UNKNOWN_LEVEL;
8781         }
8782
8783         return result;
8784 }
8785
8786 #if 0
8787
8788 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u, 
8789                                  SPOOL_R_REPLYOPENPRINTER *r_u)
8790 {
8791         DEBUG(5,("_spoolss_replyopenprinter\n"));
8792
8793         DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8794
8795         return WERR_OK;
8796 }
8797
8798 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u, 
8799                                   SPOOL_R_REPLYCLOSEPRINTER *r_u)
8800 {
8801         DEBUG(5,("_spoolss_replycloseprinter\n"));
8802         return WERR_OK;
8803 }
8804
8805 #endif