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