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